Fri, 25 Jan 2008 21:00:34 +0100
refactoring: created a 'plotter' subdirectory and put everything related to GPIB/HPGL plotting under it
# import os, sys import time from PyQt4 import QtGui, QtCore, uic from PyQt4.QtCore import SIGNAL, Qt if "-m" in sys.argv: from gpib_plotter_mockup import GPIBplotter else: from gpib_plotter import GPIBplotter from hpgl_qt import QHPGLPlotterWidget form_class, base_class = uic.loadUiType(os.path.join(os.path.dirname(__file__), "qhpgl_plotter.ui")) from qpreferences import PreferenceItem, AbstractPreferences, PreferencesEditor class Preferences(AbstractPreferences): ORGANISATION="Logilab" APPLICATION="qgpib_plotter" device = PreferenceItem('/dev/ttyUSB0', name=u'device', description=u'GPIB device') address = PreferenceItem(5, name=u'GPIB address') _pos = PreferenceItem(basetype=QtCore.QPoint) _size = PreferenceItem(basetype=QtCore.QSize) _appState = PreferenceItem(basetype=QtCore.QByteArray) class QtHPGLPlotter(QtGui.QMainWindow, form_class): def __init__(self, parent=None): QtGui.QMainWindow.__init__(self, parent) self._plots = {} self._prefs = Preferences() self.setupUi() self.initializeGPIB() if self._prefs._pos: self.move(self._prefs._pos) if self._prefs._size: self.resize(self._prefs._size) if self._prefs._appState: self.restoreState(self._prefs._appState) def setupUi(self): form_class.setupUi(self, self) # call qtdesigner generated form creation # actions defined in designer self.connect(self.actionPreferences, SIGNAL('triggered(bool)'), self.preferencesTriggered) self.connect(self.actionQuit, SIGNAL('triggered(bool)'), self.quitTriggered) self.actionQuit.setShortcut(QtGui.QKeySequence(u'Ctrl+Q')) self.connect(self.actionOpen, SIGNAL('triggered(bool)'), self.openTriggered) self.actionOpen.setShortcut(QtGui.QKeySequence(u'Ctrl+O')) self.connect(self.actionSave, SIGNAL('triggered(bool)'), self.saveTriggered) self.actionSave.setShortcut(QtGui.QKeySequence(u'Ctrl+S')) self.connect(self.actionSaveAs, SIGNAL('triggered(bool)'), self.saveAsTriggered) self.plotterWidget = QHPGLPlotterWidget(self) self.setCentralWidget(self.plotterWidget) self.connect(self.captureButton, SIGNAL("toggled(bool)"), self.captureToggled) self._plots_list = QtGui.QStringListModel() self.plotsView.setModel(self._plots_list) self.connect(self.plotsView, SIGNAL('activated(const QModelIndex&)'), self.currentPlotChanged) self.connect(self.plotsView.selectionModel(), SIGNAL('currentChanged(const QModelIndex&, const QModelIndex&)'), self.currentPlotChanged) def currentPlotChanged(self, index, old_index=None): if index.isValid(): value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString()) self.plotterWidget.clear() self.plotterWidget.parse(self._plots[value]) def preferencesTriggered(self, checked=False): PreferencesEditor(self._prefs, self).exec_() def quitTriggered(self, checked=False): self.close() def closeEvent(self, event): if 1: #if self.promptForSave(): self._prefs._pos = self.pos() self._prefs._size = self.size() self._prefs._appState = self.saveState() event.accept() else: event.ignore() def openTriggered(self, checked=False): filenames = QtGui.QFileDialog.getOpenFileNames(self, "Open a HPGL file to display", '.', 'HPGL files (*.plt)\nAll files (*)') for filename in filenames: filename = str(filename) if os.path.exists(filename): data = open(filename).read() name = os.path.basename(filename) name = os.path.splitext(name)[0] lst = self.plotsView.model().stringList() lst.append(name) self._plots[name] = data self.plotsView.model().setStringList(lst) if not self.plotsView.currentIndex().isValid(): self.plotsView.setCurrentIndex(self.plotsView.model().index(0, 0)) def plotReceived(self, num): self._receiving = False self.setReceivingLed() plot, timestamp = self.captureThread.getPlot(num) name = "plot_%s"%(num) lst = self.plotsView.model().stringList() lst.append(name) self._plots[name] = plot self.plotsView.model().setStringList(lst) def plotStarted(self): self._receiving = True self.setReceivingLed() def saveTriggered(self, checked=False): print "save" def saveAsTriggered(self, checked=False): print "saveAs" def initializeGPIB(self): self._online = False try: self.gpib_plotter = QGPIBplotter(device=self._prefs.device, address=self._prefs.address, ) self.captureThread = GPIBReceiver(self.gpib_plotter) self.connect(self.captureThread, SIGNAL('plotReceived(int)'), self.plotReceived) self.connect(self.captureThread, SIGNAL('plotStarted()'), self.plotStarted) self.captureThread.start() except Exception, e: #print e self.gpib_plotter = None self.setCaptureLed() def captureToggled(self, state): if state: if self.gpib_plotter is None: self.initializeGPIB() if self.gpib_plotter is None: QtGui.QMessageBox.critical(self, self.tr("GPIB error"), self.tr("<b>Unable to initialize GPIB connection</b>.<br>Please check your GPIB dongle and settings.")) self._online = False self.setCaptureLed() return self._online = True self.captureThread.startCapture() else: if self.captureThread: self.captureThread.stopCapture() self._online = False self.setCaptureLed() def setCaptureLed(self): if self._online: icn = QtGui.QIcon(':/icons/led_green.svg') else: icn = QtGui.QIcon(':/icons/led_green_off.svg') self.captureButton.setIcon(icn) self.captureButton.setChecked(self._online) def setReceivingLed(self): if self._receiving: icn = QtGui.QIcon(':/icons/led_red.svg') else: icn = QtGui.QIcon(':/icons/led_red_off.svg') self.receivingButton.setIcon(icn) class QGPIBplotter(GPIBplotter): def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1, address=5): GPIBplotter.__init__(self, device, baudrate, timeout, address) self.emitter = None def plotStarted(self): if self.emitter: self.emitter.emit(SIGNAL('plotStarted()')) #self.emitter.msleep(1) class GPIBReceiver(QtCore.QThread): def __init__(self, cnx): QtCore.QThread.__init__(self) self.gpibplotter = cnx self.gpibplotter.emitter = self self._cancelmutex = QtCore.QMutex() self._cancel = False #self._nreceived = 0 self._plotsmutex = QtCore.QMutex() self._plots = [] self._startstopmutex = QtCore.QMutex() self._startstop = QtCore.QWaitCondition() self._capturing = False def cancel(self): self._cancelmutex.lock() self._cancel = True self._cancelmutex.unlock() def startCapture(self): self._startstop.wakeOne() def stopCapture(self): self._startstopmutex.lock() self._capturing = False self._startstopmutex.unlock() def run(self): while 1: self._cancelmutex.lock() if self._cancel: return self._cancelmutex.unlock() self._startstopmutex.lock() if not self._capturing: self._startstop.wait(self._startstopmutex) self._capturing = True self._startstopmutex.unlock() plot = self.gpibplotter.load_plot(wait_timeout=0.1) timestamp = time.time() if plot: self._plotsmutex.lock() self._plots.append((plot, timestamp)) n = len(self._plots) self._plotsmutex.unlock() self.emit(SIGNAL('plotReceived(int)'), n-1) self.msleep(10) def getPlot(self, num): self._plotsmutex.lock() try: return self._plots[num] finally: self._plotsmutex.unlock() def main(): import optparse opt = optparse.OptionParser('A simple PyQt4 HP7470A GPIB plotter emulator for USB-GPIB bundle (ProLogix)') opt.add_option('-m', '--mockup', default=False, action="store_true", dest='mockup', help='Use a pseudo GPIB connection (for test purpose)', ) opt.add_option('-v', '--verbose', default=False, action="store_true", dest="verbose", help="Verbose mode",) options, argv = opt.parse_args(sys.argv) if options.verbose: sys.stderr.write('connection established\n') a = QtGui.QApplication(argv) w = QtHPGLPlotter() w.show() a.exec_() if __name__ == '__main__': main()