X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=sigrok-meter;h=6f83443a5368df92dc4b4b7a6d20b8d2546edcc3;hb=b7b9327811fb89b29d434fb6b1ecccb889ca7c79;hp=6febbc393941d2738f42e7e6ce4460e220d65727;hpb=58d308d18b8e3c8394ff988737fb00f9ad20606f;p=sigrok-meter.git diff --git a/sigrok-meter b/sigrok-meter index 6febbc3..6f83443 100755 --- a/sigrok-meter +++ b/sigrok-meter @@ -123,22 +123,18 @@ class SamplingThread(QtCore.QObject): '''Helper class that does the actual work in another thread.''' '''Signal emitted when new data arrived.''' - measured = QtCore.Signal(object, object) + measured = QtCore.Signal(object, object, object) '''Signal emmited in case of an error.''' error = QtCore.Signal(str) - def __init__(self, drivers, loglevel): + def __init__(self, context, drivers): super(self.__class__, self).__init__() - self.sampling = False + self.context = context self.drivers = drivers - self.context = sr.Context_create() - self.context.log_level = loglevel - - self.sr_pkg_version = self.context.package_version - self.sr_lib_version = self.context.lib_version + self.sampling = False @QtCore.Slot() def start_sampling(self): @@ -173,20 +169,34 @@ class SamplingThread(QtCore.QObject): self.session.stop() def callback(self, device, packet): - if packet.type == sr.PacketType.ANALOG: - self.measured.emit(device, packet.payload) + if not sr: + # In rare cases it can happen that the callback fires while + # the interpreter is shutting down. Then the sigrok module + # is already set to 'None'. + return + + if packet.type != sr.PacketType.ANALOG: + return - # wait a short time so that in any case we don't flood the GUI - # with new data (for example if the demo device is used) - self.thread().msleep(100) + if not len(packet.payload.channels): + return + + # TODO: find a device with multiple channels in one packet + channel = packet.payload.channels[0] + + # the most recent value + value = packet.payload.data[0][-1] + + self.measured.emit(device, channel, + (value, packet.payload.unit, packet.payload.mq_flags)) # signal used to start the worker across threads _start_signal = QtCore.Signal() - def __init__(self, drivers, loglevel): + def __init__(self, context, drivers): super(self.__class__, self).__init__() - self.worker = self.Worker(drivers, loglevel) + self.worker = self.Worker(context, drivers) self.thread = QtCore.QThread() self.worker.moveToThread(self.thread) @@ -206,17 +216,7 @@ class SamplingThread(QtCore.QObject): '''Stops sampling and the background thread.''' self.worker.stop_sampling() self.thread.quit() - # the timeout is needed when the demo device is used, because it - # produces so much outstanding data that quitting takes a long time - self.thread.wait(500) - - def sr_pkg_version(self): - '''Returns the version number of the libsigrok package.''' - return self.worker.sr_pkg_version - - def sr_lib_version(self): - '''Returns the version number fo the libsigrok library.''' - return self.worker.sr_lib_version + self.thread.wait() class MeasurementDataModel(QtGui.QStandardItemModel): '''Model to hold the measured values.''' @@ -230,7 +230,11 @@ class MeasurementDataModel(QtGui.QStandardItemModel): def __init__(self, parent): super(self.__class__, self).__init__(parent) - # used in 'format_mag()' to check against + # Use the description text to sort the items for now, because the + # _idRole holds tuples, and using them to sort doesn't work. + self.setSortRole(MeasurementDataModel.descRole) + + # Used in 'format_value()' to check against. self.inf = float('inf') def format_unit(self, u): @@ -273,7 +277,7 @@ class MeasurementDataModel(QtGui.QStandardItemModel): else: return '' - def format_mag(self, mag): + def format_value(self, mag): if mag == self.inf: return u'\u221E' return '{:f}'.format(mag) @@ -308,28 +312,22 @@ class MeasurementDataModel(QtGui.QStandardItemModel): item.setData(uid, MeasurementDataModel._idRole) item.setData(desc, MeasurementDataModel.descRole) self.appendRow(item) + self.sort(0) return item - @QtCore.Slot(object, object) - def update(self, device, payload): + @QtCore.Slot(object, object, object) + def update(self, device, channel, data): '''Updates the data for the device (+channel) with the most recent measurement from the given payload.''' - if not len(payload.channels): - return - - # TODO: find a device with multiple channels in one packet - channel = payload.channels[0] - item = self.getItem(device, channel) - # the most recent value - mag = payload.data[0][-1] + value, unit, mqflags = data + value_str = self.format_value(value) + unit_str = self.format_unit(unit) + mqflags_str = self.format_mqflags(mqflags) - unit_str = self.format_unit(payload.unit) - mqflags_str = self.format_mqflags(payload.mq_flags) - mag_str = self.format_mag(mag) - disp = ' '.join([mag_str, unit_str, mqflags_str]) + disp = ' '.join([value_str, unit_str, mqflags_str]) item.setData(disp, QtCore.Qt.DisplayRole) class MultimeterDelegate(QtGui.QStyledItemDelegate): @@ -399,16 +397,18 @@ class EmptyMessageListView(QtGui.QListView): class SigrokMeter(QtGui.QMainWindow): '''The main window of the application.''' - def __init__(self, thread): + def __init__(self, context, drivers): super(SigrokMeter, self).__init__() + self.context = context + self.delegate = MultimeterDelegate(self, self.font()) self.model = MeasurementDataModel(self) self.model.rowsInserted.connect(self.modelRowsInserted) self.setup_ui() - self.thread = thread + self.thread = SamplingThread(self.context, drivers) self.thread.measured.connect(self.model.update) self.thread.error.connect(self.error) self.thread.start() @@ -455,6 +455,10 @@ class SigrokMeter(QtGui.QMainWindow): self.setCentralWidget(self.listView) self.centralWidget().setContentsMargins(0, 0, 0, 0) + def closeEvent(self, event): + self.thread.stop() + event.accept() + @QtCore.Slot() def show_about(self): text = textwrap.dedent('''\ @@ -470,7 +474,7 @@ class SigrokMeter(QtGui.QMainWindow): http://www.gnu.org/licenses/gpl.html - '''.format(self.thread.sr_pkg_version(), self.thread.sr_lib_version())) + '''.format(self.context.package_version, self.context.lib_version)) QtGui.QMessageBox.about(self, 'About sigrok-meter', text) @@ -489,12 +493,11 @@ class SigrokMeter(QtGui.QMainWindow): self.listView.setMinimumHeight(dh * rows) if __name__ == '__main__': - thread = SamplingThread(args['drivers'], args['loglevel']) + context = sr.Context_create() + context.log_level = args['loglevel'] app = QtGui.QApplication([]) - s = SigrokMeter(thread) + s = SigrokMeter(context, args['drivers']) s.show() - r = app.exec_() - thread.stop() - sys.exit(r) + sys.exit(app.exec_())