import acquisition
import datamodel
+import datetime
import icons
import multiplotwidget
import os.path
import qtcompat
import settings
+import sigrok.core as sr
+import sys
import textwrap
import time
import util
self.context = context
self.drivers = drivers
+ self.logModel = QtGui.QStringListModel(self)
+ self.context.set_log_callback(self._log_callback)
+
self.delegate = datamodel.MultimeterDelegate(self, self.font())
self.model = datamodel.MeasurementDataModel(self)
self.start_stop_acquisition()
+ def _log_callback(self, level, message):
+ if level.id > settings.logging.level.value().id:
+ return
+
+ t = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
+ message = '[{}] sr: {}'.format(t, message)
+
+ sys.stderr.write(message + '\n')
+
+ scrollBar = self.logView.verticalScrollBar()
+ bottom = scrollBar.value() == scrollBar.maximum()
+
+ rows = self.logModel.rowCount()
+ maxrows = settings.logging.lines.value()
+ while rows > maxrows:
+ self.logModel.removeRows(0, 1)
+ rows -= 1
+
+ if self.logModel.insertRow(rows):
+ index = self.logModel.index(rows)
+ self.logModel.setData(index, message, QtCore.Qt.DisplayRole)
+
+ if bottom:
+ self.logView.scrollToBottom()
+
def _setup_ui(self):
self.setWindowTitle('sigrok-meter')
# Resizing the listView below will increase this again.
#actionAdd.setIcon(icons.add)
#actionAdd.triggered.connect(self.showAddDevicePage)
- #actionLog = self.sideBar.addAction('Logs')
- #actionLog.setCheckable(True)
- #actionLog.setIcon(icons.log)
- #actionLog.triggered.connect(self.showLogPage)
+ actionLog = self.sideBar.addAction('Logs')
+ actionLog.setCheckable(True)
+ actionLog.setIcon(icons.log)
+ actionLog.triggered.connect(self.showLogPage)
actionPreferences = self.sideBar.addAction('Preferences')
actionPreferences.setCheckable(True)
self.actionGroup = QtGui.QActionGroup(self)
self.actionGroup.addAction(actionGraph)
#self.actionGroup.addAction(actionAdd)
- #self.actionGroup.addAction(actionLog)
+ self.actionGroup.addAction(actionLog)
self.actionGroup.addAction(actionPreferences)
# show graph at startup
layout.addWidget(label)
def _setup_logPage(self):
+ self.logView = QtGui.QListView(self)
+ self.logView.setModel(self.logModel)
+ self.logView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
+ self.logView.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
+
self.logPage = QtGui.QWidget(self)
layout = QtGui.QVBoxLayout(self.logPage)
- label = QtGui.QLabel('log page')
- layout.addWidget(label)
+ layout.addWidget(self.logView)
def _setup_preferencesPage(self):
self.preferencesPage = QtGui.QWidget(self)
spin.valueChanged[int].connect(settings.graph.backlog.setValue)
layout.addWidget(spin, 1, 1)
+ layout.addWidget(QtGui.QLabel('<b>Logging</b>'), 2, 0)
+ layout.addWidget(QtGui.QLabel('Log level:'), 3, 0)
+
+ cbox = QtGui.QComboBox()
+ descriptions = [
+ 'no messages at all',
+ 'error messages',
+ 'warnings',
+ 'informational messages',
+ 'debug messages',
+ 'very noisy debug messages'
+ ]
+ for i, desc in enumerate(descriptions):
+ level = sr.LogLevel.get(i)
+ text = '{} ({})'.format(level.name, desc)
+ # The numeric log level corresponds to the index of the text in the
+ # combo box. Should this ever change, we could use the 'userData'
+ # that can also be stored in the item.
+ cbox.addItem(text)
+
+ cbox.setCurrentIndex(settings.logging.level.value().id)
+ cbox.currentIndexChanged[int].connect(
+ (lambda i: settings.logging.level.setValue(sr.LogLevel.get(i))))
+ layout.addWidget(cbox, 3, 1)
+
+ layout.addWidget(QtGui.QLabel('Number of lines to log:'), 4, 0)
+
+ spin = QtGui.QSpinBox(self)
+ spin.setMinimum(100)
+ spin.setMaximum(10 * 1000 * 1000)
+ spin.setSingleStep(100)
+ spin.setValue(settings.logging.lines.value())
+ spin.valueChanged[int].connect(settings.logging.lines.setValue)
+ layout.addWidget(spin, 4, 1)
+
layout.setRowStretch(layout.rowCount(), 100)
def showPage(self, page):
##
import qtcompat
+import sigrok.core as sr
QtCore = qtcompat.QtCore
QtGui = qtcompat.QtGui
'''Signal emitted when the setting has changed.'''
changed = QtCore.Signal(object)
- def __init__(self, key, default=None, conv=None):
+ def __init__(self, key, default=None, s=None, d=None):
'''Initializes the Settings object.
:param key: The key of the used 'QSettings' object.
:param default: Value returned if the setting doesn't already exist.
- :param conv: Function used to convert the setting to the correct type.
+ :param s: Function used to serialize the value into a string.
+ :param d: Function used to convert a string into a value.
'''
super(self.__class__, self).__init__()
self._key = key
self._default = default
- self._conv = conv
+ self._serialize = s if s else (lambda x: x)
+ self._deserialize = d if d else (lambda x: x)
self._value = None
def value(self):
s = QtCore.QSettings()
v = s.value(self._key, self._default)
- self._value = self._conv(v) if self._conv else v
+ self._value = self._deserialize(v)
return self._value
@QtCore.Slot(object)
def setValue(self, value):
if value != self._value:
s = QtCore.QSettings()
- s.setValue(self._key, value)
+ s.setValue(self._key, self._serialize(value))
s.sync()
self._value = value
self.changed.emit(self._value)
'''Dummy class to group multiple 'Setting' objects together.'''
pass
+_default_loglevel = 'WARN'
+
+def _d_loglevel(s):
+ '''Converts a string into a sr.LogLevel.'''
+ d = {
+ 'NONE': sr.LogLevel.NONE,
+ 'ERR': sr.LogLevel.ERR,
+ 'WARN': sr.LogLevel.WARN,
+ 'INFO': sr.LogLevel.INFO,
+ 'DBG': sr.LogLevel.DBG,
+ 'SPEW': sr.LogLevel.SPEW
+ }
+
+ if not (s in d):
+ s = _default_loglevel
+
+ return d[s]
+
+def _s_loglevel(l):
+ '''Converts a sr.LogLevel into a string.'''
+ return l.name
+
def init():
'''Creates the 'Settings' objects for all known settings and places them
into the module's namespace.
globals()['mainwindow'] = mainwindow
graph = _SettingsGroup()
- graph.backlog = Setting('graph/backlog', 30, conv=int)
+ graph.backlog = Setting('graph/backlog', 30, d=int)
globals()['graph'] = graph
+
+ logging = _SettingsGroup()
+ logging.level = Setting('logging/level', _default_loglevel,
+ s=_s_loglevel, d=_d_loglevel)
+ logging.lines = Setting('logging/lines', 1000, d=int)
+ globals()['logging'] = logging
import signal
default_drivers = [('demo:analog_channels=4', 'samplerate=4')]
-default_loglevel = 2
def parse_cli():
parser = argparse.ArgumentParser(
help='Specify device configuration options')
parser.add_argument('-l', '--loglevel',
type=int,
- default=default_loglevel,
+ default=None,
help='Set loglevel (5 is most verbose)')
parser.add_argument('--pyside',
action='store_true',
QtGui = qtcompat.QtGui
import mainwindow
- context = sr.Context_create()
- try:
- loglevel = sr.LogLevel.get(args.loglevel)
- context.log_level = loglevel
- except:
- sys.exit('Error: invalid log level.')
-
app = QtGui.QApplication([])
# Initialize modules that need a QApplication to exist.
import icons
icons.load_icons()
+ context = sr.Context_create()
+
+ if args.loglevel != None:
+ try:
+ loglevel = sr.LogLevel.get(args.loglevel)
+ settings.logging.level.setValue(loglevel)
+ except:
+ sys.exit('Error: invalid log level.')
+
s = mainwindow.MainWindow(context, args.drivers)
s.show()