diff -r c869766e25ff -r 59da528bc470 plotter/qgpib_plotter.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plotter/qgpib_plotter.py Fri Jan 25 21:00:34 2008 +0100 @@ -0,0 +1,278 @@ +# + +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("Unable to initialize GPIB connection.
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()