Mon, 04 Feb 2008 19:49:48 +0100
refactoring in progress
# import os, sys import time import glob 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 import hpgl_plotter_rc ldir = os.path.abspath(os.path.dirname(__file__)) sys.path.append(ldir) form_class, base_class = uic.loadUiType(os.path.join(ldir, "qhpgl_plotter.ui")) from qpreferences import BaseItem, IntItem, UnicodeItem, ColorItem from qpreferences import PointItem, SizeItem, ByteArrayItem from qpreferences import AbstractPreferences from qpreferenceseditor import PreferencesEditor from tools import str_num_cmp class Preferences(AbstractPreferences): ORGANISATION="Logilab" APPLICATION="qgpib_plotter" _pos = PointItem() _size = SizeItem() _appState = ByteArrayItem() device = UnicodeItem(default='/dev/ttyUSB0', name=u'device', description=u'GPIB device', group="GPIB settings") address = IntItem(default=5, min=0, max=16, name=u'GPIB address', group="GPIB settings") background = ColorItem(default=QtGui.QColor("white"), name="Background", group="Colors") color0 = ColorItem(default=QtGui.QColor("black"), name="Pen #0", group="Colors") color1 = ColorItem(default=QtGui.QColor("green"), name="Pen #1", group="Colors") color2 = ColorItem(default=QtGui.QColor("red"), name="Pen #2", group="Colors") color3 = ColorItem(default=QtGui.QColor("blue"), name="Pen #3", group="Colors") color4 = ColorItem(default=QtGui.QColor("yellow"), name="Pen #4", group="Colors") color5 = ColorItem(default=QtGui.QColor("cyan"), name="Pen #5", group="Colors") color6 = ColorItem(default=QtGui.QColor("magenta"), name="Pen #6", group="Colors") color7 = ColorItem(default=QtGui.QColor("darkred"), name="Pen #7", group="Colors") 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) self.readPreferences() def readPreferences(self): bg = self._prefs.background if bg and bg.isValid(): self.plotterWidget.qview.setBackgroundBrush(QtGui.QBrush(bg)) pen_colors = [self._prefs["color%d"%i] for i in range(8)] self.plotterWidget.pen_colors = pen_colors def replotCurrent(self): self.currentPlotChanged(self.plotsView.currentIndex()) 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_() self.readPreferences() self.replotCurrent() 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 (*)') self.openFiles(filenames) self.displayFirst() def displayFirst(self): if not self.plotsView.currentIndex().isValid(): self.plotsView.setCurrentIndex(self.plotsView.model().index(0, 0)) def openFiles(self, filenames): ok = False 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) ok = True return ok 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): index = self.plotsView.selectionModel().currentIndex() if index.isValid(): filename = QtGui.QFileDialog.getSaveFileName(self, "Selecte a file name to save HPGL file", '.', 'HPGL files (*.plt)\nAll files (*)') n = index.row() value = unicode(self.plotsView.model().data(index, Qt.DisplayRole).toString()) open(filename, 'w').write(self._plots[value]) 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) a = QtGui.QApplication(argv) w = QtHPGLPlotter() files = [f for f in argv[1:] if os.path.isfile(f)] files.sort(cmp=str_num_cmp) if w.openFiles(files): w.displayFirst() w.show() a.exec_() if __name__ == '__main__': main()