class BackGround: """ class that provides a timer that checks on background processes, and method for adding new background workers. all workers should provide following methods: ui(),bg() """ def __init__(self): self.workers = {} self.checkTimer = QTimer() self.checkTimer.connect(self.checkTimer, SIGNAL("timeout()"), self.check) self.checkTimer.start(500) def check(self): for worker in self.workers.keys(): if not self.workers[worker].THREAD.isAlive(): self.workers[worker].ui() if self.workers[worker].SENDER: self.workers[worker].SENDER.setEnabled(True) del self.workers[worker] else: self.workers[worker].status() def add(self, worker, sender=None): if self.workers.has_key(str(worker)): # only add unique workers! return False worker.THREAD = Thread(args=[worker], target=worker.bg) worker.THREAD.start() if sender: sender.setEnabled(False) worker.SENDER = sender self.workers[str(worker)] = worker return True
def __init__(self, parent, updateinterval): SurfacePlot.__init__(self, parent) self.setRotation(30, 0, 15) self.setShift(0.1, 0, 0) self.setZoom(0.8) self.coordinates().setNumberFont("Courier", 8) axes = self.coordinates().axes # alias for axis in axes: axis.setMajors(7) axis.setMinors(4) axes[X1].setLabelString("x") axes[Y1].setLabelString("y") axes[Z1].setLabelString("z") axes[X2].setLabelString("x") axes[Y2].setLabelString("y") axes[Z2].setLabelString("z") axes[X3].setLabelString("x") axes[Y3].setLabelString("y") axes[Z3].setLabelString("z") axes[X4].setLabelString("x") axes[Y4].setLabelString("y") axes[Z4].setLabelString("z") timer = QTimer(self) self.connect(timer, SIGNAL('timeout()'), self.rotate) timer.start(updateinterval)
class BackGround: """ class that provides a timer that checks on background processes, and method for adding new background workers. all workers should provide following methods: ui(),bg() """ def __init__(self): self.workers = {} self.checkTimer = QTimer() self.checkTimer.connect(self.checkTimer, SIGNAL("timeout()"), self.check) self.checkTimer.start(500) def check(self): for worker in self.workers.keys(): if not self.workers[worker].THREAD.isAlive(): self.workers[worker].ui() if self.workers[worker].SENDER: self.workers[worker].SENDER.setEnabled(True) del self.workers[worker] else: self.workers[worker].status() def add(self, worker, sender=None): if self.workers.has_key(str(worker)): # only add unique workers! return False worker.THREAD = Thread(args = [worker], target = worker.bg) worker.THREAD.start() if sender: sender.setEnabled(False) worker.SENDER = sender self.workers[str(worker)] = worker return True
class BaseLogBrowser(KTextBrowser): def __init__(self, parent, name='BaseLogBrowser'): KTextBrowser.__init__(self, parent, name) self.setTextFormat(self.LogText) self.timer = QTimer(self) self.connect(self.timer, SIGNAL('timeout()'), self.update_logtext) self.resume_logging() def pause_logging(self): self.timer.stop() def resume_logging(self): self.timer.start(500) def update_logtext(self): raise NotImplementedError
def simulate(self): global _timer if _timer: _timer.stop() if not self.running: self.running = 1 self.qApp.exit_loop() return self.runUntilCurrent() # gah timeout = self.timeout() if timeout is None: timeout = 1.0 timeout = min(timeout, 0.1) * 1010 if not _timer: _timer = QTimer() QObject.connect( _timer, SIGNAL("timeout()"), self.simulate ) _timer.start(timeout, 1)
class updateCheckWorker: """ class that provides new version checking in background """ def __init__(self, notifier): from pyqlogger import VERSION self.notifier = notifier self.notified = LooseVersion(VERSION) self.Timer = QTimer() self.Timer.connect(self.Timer, SIGNAL("timeout()"), self.work) self.Timer.start(60*60*1000) def work(self): try: req = urllib2.urlopen('http://pyqlogger.berlios.de/ver.php') line = req.readline() newver = LooseVersion( line.strip() ) if newver > self.notified : self.notified = newver self.notifier.info("New version %s is available at the site!"%(str(newver))) except: pass
class updateCheckWorker: """ class that provides new version checking in background """ def __init__(self, notifier): from pyqlogger import VERSION self.notifier = notifier self.notified = LooseVersion(VERSION) self.Timer = QTimer() self.Timer.connect(self.Timer, SIGNAL("timeout()"), self.work) self.Timer.start(60 * 60 * 1000) def work(self): try: req = urllib2.urlopen('http://pyqlogger.berlios.de/ver.php') line = req.readline() newver = LooseVersion(line.strip()) if newver > self.notified: self.notified = newver self.notifier.info("New version %s is available at the site!" % (str(newver))) except: pass
class KSmartTray(QObject): class State: Waiting = 'StateWaiting' Updating = 'StateUpdating' Checking = 'StateChecking' Upgrading = 'StateUpgrading' RunningSmart = 'StateRunningSmart' def __init__(self): QObject.__init__(self) self.sysTray = KMySystemTray() self.sysTray.setPixmap(self.sysTray.loadIcon("ksmarttray")) self.sysTray.show() self.process = KProcIO() self.state = KSmartTray.State.Waiting self.lastKnownStatus = "" self.blinkFlag = False self.updateFailed = False self.checkTimer = QTimer() self.blinkTimer = QTimer() QObject.connect(self.checkTimer, SIGNAL("timeout()"), self.checkUpgrades) QObject.connect(self.process, SIGNAL("processExited(KProcess *)"), self.processDone) QObject.connect(self, PYSIGNAL("foundNewUpgrades()"), self.startBlinking) QObject.connect(self, PYSIGNAL("foundNoUpgrades()"), self.stopBlinking) QObject.connect(self.sysTray, PYSIGNAL("mouseEntered()"), self.stopBlinking) QObject.connect(self.blinkTimer, SIGNAL("timeout()"), self.toggleBlink) QObject.connect(self.sysTray.checkAction, SIGNAL("activated()"), self.manualCheckUpgrades) QObject.connect(self.sysTray.startSmartAction, SIGNAL("activated()"), self.startSmart) QObject.connect(self.sysTray.stopAction, SIGNAL("activated()"), self.stopChecking) QObject.connect(self.sysTray, SIGNAL("quitSelected()"), KApplication.kApplication(), SLOT("quit()")) QObject.connect(self.sysTray, PYSIGNAL("activated()"), self.runUpgrades) self.checkTimer.start(5 * 60 * 1000) self.checkUpgrades() def internalCheckUpgrades(self, manual): if not manual and self.blinkTimer.isActive(): return if self.state == KSmartTray.State.Waiting: self.sysTray.checkAction.setEnabled(False) self.sysTray.startSmartAction.setEnabled(False) self.sysTray.stopAction.setEnabled(True) self.process.resetAll() if manual: self.process.setArguments(["smart-update"]) else: self.process.setArguments(["smart-update", "--after", "60"]) if not self.process.start(): KNotifyClient.event(self.sysTray.winId(), "fatalerror", "Couldn't run 'smart-update'.") else: QToolTip.add(self.sysTray, "Updating channels...") self.state = KSmartTray.State.Updating def checkUpgrades(self): self.internalCheckUpgrades(False) def manualCheckUpgrades(self): self.internalCheckUpgrades(True) def runUpgrades(self): if self.state != KSmartTray.State.Waiting: KNotifyClient.event(self.sysTray.winId(), "fatalerror", "There is a running process.") else: self.sysTray.checkAction.setEnabled(False) self.sysTray.startSmartAction.setEnabled(False) self.sysTray.stopAction.setEnabled(False) self.process.resetAll() self.process.setArguments( ["kdesu", "-d", "-c", "smart --gui upgrade"]) if not self.process.start(): KNotifyClient.event(self.sysTray.winId(), "fatalerror", "Couldn't run 'smart upgrade'.") else: self.state = KSmartTray.State.Upgrading QToolTip.remove(self.sysTray) QToolTip.add(self.sysTray, "Running Smart Package Manager...") def startSmart(self): if self.state != KSmartTray.State.Waiting: KNotifyClient.event(self.sysTray.winId(), "fatalerror", "There is a running process.") else: self.sysTray.checkAction.setEnabled(False) self.sysTray.startSmartAction.setEnabled(False) self.sysTray.stopAction.setEnabled(False) self.process.resetAll() self.process.setArguments(["kdesu", "-d", "-c", "smart --gui"]) if not self.process.start(): KNotifyClient.event(self.sysTray.winId(), "fatalerror", "Couldn't run 'smart'.") else: self.state = KSmartTray.State.RunningSmart QToolTip.remove(self.sysTray) QToolTip.add(self.sysTray, "Running Smart Package Manager...") def stopChecking(self): self.process.kill() def processDone(self, process): if self.state == KSmartTray.State.Updating: if not process.normalExit() or process.exitStatus() != 0: self.updateFailed = True if self.updateFailed and not self.lastKnownStatus == "": self.state = KSmartTray.State.Waiting else: process.resetAll() process.setArguments(["smart", "upgrade", "--check-update"]) if not process.start(): KNotifyClient.event(self.sysTray.winId(), "fatalerror", "Couldn't run 'smart upgrade'.") self.state = KSmartTray.State.Waiting self.lastKnownStatus = "" else: QToolTip.remove(self.sysTray) QToolTip.add(self.sysTray, "Verifying upgradable packages...") self.state = KSmartTray.State.Checking elif self.state == KSmartTray.State.Checking: self.state = KSmartTray.State.Waiting if process.normalExit(): if process.exitStatus() == 0: self.lastKnownStatus = "There are new upgrades available!" KNotifyClient.event(self.sysTray.winId(), "found-new-upgrades", self.lastKnownStatus) self.emit(PYSIGNAL("foundNewUpgrades()"), ()) elif process.exitStatus() == 1: self.lastKnownStatus = "There are pending upgrades!" if not self.updateFailed: KNotifyClient.event(self.sysTray.winId(), "found-old-upgrades", self.lastKnownStatus) self.emit(PYSIGNAL("foundOldUpgrades()"), ()) elif process.exitStatus() == 2: self.lastKnownStatus = "No interesting upgrades available." if not self.updateFailed: KNotifyClient.event(self.sysTray.winId(), "found-no-upgrades", self.lastKnownStatus) self.emit(PYSIGNAL("foundNoUpgrades()"), ()) else: self.lastKnownStatus = "" elif self.state == KSmartTray.State.Upgrading: self.state = KSmartTray.State.Waiting self.lastKnownStatus = "" elif self.state == KSmartTray.State.RunningSmart: self.state = KSmartTray.State.Waiting self.lastKnownStatus = "" else: # Error! pass if self.state == KSmartTray.State.Waiting: self.updateFailed = False self.sysTray.checkAction.setEnabled(True) self.sysTray.startSmartAction.setEnabled(True) self.sysTray.stopAction.setEnabled(False) if not self.lastKnownStatus == "": QToolTip.remove(self.sysTray) QToolTip.add(self.sysTray, self.lastKnownStatus) else: QToolTip.remove(self.sysTray) def startBlinking(self): if not self.blinkTimer.isActive(): self.blinkTimer.start(500) def stopBlinking(self): if self.blinkTimer.isActive(): self.blinkTimer.stop() self.sysTray.setPixmap(self.sysTray.loadIcon("ksmarttray")) def toggleBlink(self): if self.blinkFlag: self.sysTray.setPixmap(QPixmap()) else: self.sysTray.setPixmap(self.sysTray.loadIcon("ksmarttray")) self.blinkFlag = not self.blinkFlag
class qSlicerMultiVolumeExplorerSimplifiedModuleWidget: def __init__(self, parent=None): logging.debug("qSlicerMultiVolumeExplorerSimplifiedModuleWidget:init() called") if not parent or not hasattr(parent, "layout"): self.parent = slicer.qMRMLWidget() self.parent.setLayout(QVBoxLayout()) else: self.parent = parent self.layout = self.parent.layout() self._bgMultiVolumeNode = None self._fgMultiVolumeNode = None self.styleObserverTags = [] self.sliceWidgetsPerStyle = {} self.chartPopupWindow = None self.chartPopupSize = QSize(600, 300) self.chartPopupPosition = QPoint(0,0) def hide(self): self.widget.hide() def show(self): self.widget.show() def setup(self): self.widget = QWidget() layout = QGridLayout() self.widget.setLayout(layout) self.layout.addWidget(self.widget) self.widget.show() self.layout = layout self.setupInputFrame() self.setupFrameControlFrame() self.setupAdditionalFrames() self.setupPlottingFrame() self.setFramesEnabled(False) self.timer = QTimer() self.timer.setInterval(50) self.setupConnections() # initialize slice observers (from DataProbe.py) # keep list of pairs: [observee,tag] so they can be removed easily self.styleObserverTags = [] # keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic self.sliceWidgetsPerStyle = {} self.refreshObservers() def setupInputFrame(self, parent=None): if not parent: parent = self.layout self.bgMultiVolumeSelector = slicer.qMRMLNodeComboBox() self.bgMultiVolumeSelector.nodeTypes = ['vtkMRMLMultiVolumeNode'] self.bgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene) self.bgMultiVolumeSelector.addEnabled = 0 self._bgMultiVolumeSelectorLabel = QLabel('Input multivolume') inputFrameWidget = QWidget() self.inputFrameLayout = QFormLayout() inputFrameWidget.setLayout(self.inputFrameLayout) self.inputFrameLayout.addRow(self._bgMultiVolumeSelectorLabel, self.bgMultiVolumeSelector) parent.addWidget(inputFrameWidget) def setupFrameControlFrame(self): # TODO: initialize the slider based on the contents of the labels array self.frameSlider = ctk.ctkSliderWidget() self.frameLabel = QLabel('Current frame number') self.playButton = QPushButton('Play') self.playButton.toolTip = 'Iterate over multivolume frames' self.playButton.checkable = True frameControlHBox = QHBoxLayout() frameControlHBox.addWidget(self.frameLabel) frameControlHBox.addWidget(self.frameSlider) frameControlHBox.addWidget(self.playButton) self.inputFrameLayout.addRow(frameControlHBox) def setupAdditionalFrames(self): pass def setupPlottingFrame(self, parent=None): if not parent: parent = self.layout self.plottingFrameWidget = QWidget() self.plottingFrameLayout = QGridLayout() self.plottingFrameWidget.setLayout(self.plottingFrameLayout) self._multiVolumeIntensityChart = MultiVolumeIntensityChartView() self.popupChartButton = QPushButton("Undock chart") self.popupChartButton.setCheckable(True) self.plottingFrameLayout.addWidget(self._multiVolumeIntensityChart.chartView) self.plottingFrameLayout.addWidget(self.popupChartButton) parent.addWidget(self.plottingFrameWidget) def setupConnections(self): self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVCMRMLSceneChanged) self.bgMultiVolumeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onBackgroundInputChanged) self.playButton.connect('toggled(bool)', self.onPlayButtonToggled) self.frameSlider.connect('valueChanged(double)', self.onSliderChanged) self.timer.connect('timeout()', self.goToNext) self.popupChartButton.connect('toggled(bool)', self.onDockChartViewToggled) def onDockChartViewToggled(self, checked): if checked: self.chartPopupWindow = QDialog() self.chartPopupWindow.setWindowFlags(PythonQt.QtCore.Qt.WindowStaysOnTopHint) layout = QGridLayout() self.chartPopupWindow.setLayout(layout) layout.addWidget(self._multiVolumeIntensityChart.chartView) layout.addWidget(self.popupChartButton) self.chartPopupWindow.finished.connect(self.dockChartView) self.chartPopupWindow.resize(self.chartPopupSize) self.chartPopupWindow.move(self.chartPopupPosition) self.chartPopupWindow.show() self.popupChartButton.setText("Dock chart") self._multiVolumeIntensityChart.chartView.show() else: self.chartPopupWindow.close() def dockChartView(self): self.chartPopupSize = self.chartPopupWindow.size self.chartPopupPosition = self.chartPopupWindow.pos self.plottingFrameLayout.addWidget(self._multiVolumeIntensityChart.chartView) self.plottingFrameLayout.addWidget(self.popupChartButton) self.popupChartButton.setText("Undock chart") self.popupChartButton.disconnect('toggled(bool)', self.onDockChartViewToggled) self.popupChartButton.checked = False self.popupChartButton.connect('toggled(bool)', self.onDockChartViewToggled) def onSliderChanged(self, frameId): if self._bgMultiVolumeNode is None: return newValue = int(frameId) self.setCurrentFrameNumber(newValue) def onVCMRMLSceneChanged(self, mrmlScene): logging.debug("qSlicerMultiVolumeExplorerSimplifiedModuleWidget:onVCMRMLSceneChanged") self.bgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene) self.onBackgroundInputChanged() def refreshGUIForNewBackgroundImage(self): self._multiVolumeIntensityChart.reset() self.setFramesEnabled(True) if self._fgMultiVolumeNode and self._bgMultiVolumeNode: Helper.SetBgFgVolumes(self._bgMultiVolumeNode.GetID(), self._fgMultiVolumeNode.GetID()) else: Helper.SetBgVolume(self._bgMultiVolumeNode.GetID()) self.refreshFrameSlider() self._multiVolumeIntensityChart.bgMultiVolumeNode = self._bgMultiVolumeNode self.refreshObservers() def getBackgroundMultiVolumeNode(self): return self.bgMultiVolumeSelector.currentNode() def onBackgroundInputChanged(self): self._bgMultiVolumeNode = self.getBackgroundMultiVolumeNode() if self._bgMultiVolumeNode is not None: self.refreshGUIForNewBackgroundImage() else: self.setFramesEnabled(False) def onPlayButtonToggled(self, checked): if self._bgMultiVolumeNode is None: return if checked: self.timer.start() self.playButton.text = 'Stop' else: self.timer.stop() self.playButton.text = 'Play' def processEvent(self, observee, event): # logging.debug("processing event %s" % event) if self._bgMultiVolumeNode is None: return # TODO: use a timer to delay calculation and compress events if event == 'LeaveEvent': # reset all the readouts # TODO: reset the label text return if not self.sliceWidgetsPerStyle.has_key(observee): return interactor = observee.GetInteractor() self.createChart(self.sliceWidgetsPerStyle[observee], interactor.GetEventPosition()) def createChart(self, sliceWidget, position): self._multiVolumeIntensityChart.createChart(sliceWidget, position) def setCurrentFrameNumber(self, frameNumber): mvDisplayNode = self._bgMultiVolumeNode.GetDisplayNode() mvDisplayNode.SetFrameComponent(frameNumber) def setFramesEnabled(self, enabled): pass def refreshObservers(self): """ When the layout changes, drop the observers from all the old widgets and create new observers for the newly created widgets""" self.removeObservers() # get new slice nodes layoutManager = slicer.app.layoutManager() sliceNodeCount = slicer.mrmlScene.GetNumberOfNodesByClass('vtkMRMLSliceNode') for nodeIndex in xrange(sliceNodeCount): # find the widget for each node in scene sliceNode = slicer.mrmlScene.GetNthNodeByClass(nodeIndex, 'vtkMRMLSliceNode') sliceWidget = layoutManager.sliceWidget(sliceNode.GetLayoutName()) if sliceWidget: # add observers and keep track of tags style = sliceWidget.sliceView().interactorStyle() self.sliceWidgetsPerStyle[style] = sliceWidget events = ("MouseMoveEvent", "EnterEvent", "LeaveEvent") for event in events: tag = style.AddObserver(event, self.processEvent) self.styleObserverTags.append([style,tag]) def removeObservers(self): for observee,tag in self.styleObserverTags: observee.RemoveObserver(tag) self.styleObserverTags = [] self.sliceWidgetsPerStyle = {} def refreshFrameSlider(self): self.frameSlider.minimum = 0 if not self._bgMultiVolumeNode: self.frameSlider.maximum = 0 return nFrames = self._bgMultiVolumeNode.GetNumberOfFrames() self.frameSlider.maximum = nFrames - 1 def goToNext(self): currentElement = self.frameSlider.value currentElement += 1 if currentElement > self.frameSlider.maximum: currentElement = 0 self.frameSlider.value = currentElement
class KSmartTray(QObject): class State: Waiting = 'StateWaiting' Updating = 'StateUpdating' Checking = 'StateChecking' Upgrading = 'StateUpgrading' RunningSmart = 'StateRunningSmart' def __init__(self): QObject.__init__(self) self.sysTray = KMySystemTray() self.sysTray.setPixmap(self.sysTray.loadIcon("ksmarttray")) self.sysTray.show() self.process = KProcIO() self.state = KSmartTray.State.Waiting self.lastKnownStatus = "" self.blinkFlag = False self.updateFailed = False self.checkTimer = QTimer() self.blinkTimer = QTimer() QObject.connect(self.checkTimer, SIGNAL("timeout()"), self.checkUpgrades) QObject.connect(self.process, SIGNAL("processExited(KProcess *)"), self.processDone) QObject.connect(self, PYSIGNAL("foundNewUpgrades()"), self.startBlinking) QObject.connect(self, PYSIGNAL("foundNoUpgrades()"), self.stopBlinking) QObject.connect(self.sysTray, PYSIGNAL("mouseEntered()"), self.stopBlinking) QObject.connect(self.blinkTimer, SIGNAL("timeout()"), self.toggleBlink) QObject.connect(self.sysTray.checkAction, SIGNAL("activated()"), self.manualCheckUpgrades) QObject.connect(self.sysTray.startSmartAction, SIGNAL("activated()"), self.startSmart) QObject.connect(self.sysTray.stopAction, SIGNAL("activated()"), self.stopChecking) QObject.connect(self.sysTray, SIGNAL("quitSelected()"), KApplication.kApplication(), SLOT("quit()")) QObject.connect(self.sysTray, PYSIGNAL("activated()"), self.runUpgrades) self.checkTimer.start(5*60*1000) self.checkUpgrades() def internalCheckUpgrades(self, manual): if not manual and self.blinkTimer.isActive(): return if self.state == KSmartTray.State.Waiting: self.sysTray.checkAction.setEnabled(False) self.sysTray.startSmartAction.setEnabled(False) self.sysTray.stopAction.setEnabled(True) self.process.resetAll() if manual: self.process.setArguments(["smart-update"]) else: self.process.setArguments(["smart-update", "--after", "60"]) if not self.process.start(): KNotifyClient.event(self.sysTray.winId(), "fatalerror", "Couldn't run 'smart-update'.") else: QToolTip.add(self.sysTray, "Updating channels...") self.state = KSmartTray.State.Updating def checkUpgrades(self): self.internalCheckUpgrades(False) def manualCheckUpgrades(self): self.internalCheckUpgrades(True) def runUpgrades(self): if self.state != KSmartTray.State.Waiting: KNotifyClient.event(self.sysTray.winId(), "fatalerror", "There is a running process.") else: self.sysTray.checkAction.setEnabled(False) self.sysTray.startSmartAction.setEnabled(False) self.sysTray.stopAction.setEnabled(False) self.process.resetAll() self.process.setArguments(["kdesu", "-d", "-c", "smart --gui upgrade"]) if not self.process.start(): KNotifyClient.event(self.sysTray.winId(), "fatalerror", "Couldn't run 'smart upgrade'.") else: self.state = KSmartTray.State.Upgrading QToolTip.remove(self.sysTray) QToolTip.add(self.sysTray, "Running Smart Package Manager...") def startSmart(self): if self.state != KSmartTray.State.Waiting: KNotifyClient.event(self.sysTray.winId(), "fatalerror", "There is a running process.") else: self.sysTray.checkAction.setEnabled(False) self.sysTray.startSmartAction.setEnabled(False) self.sysTray.stopAction.setEnabled(False) self.process.resetAll() self.process.setArguments(["kdesu", "-d", "-c", "smart --gui"]) if not self.process.start(): KNotifyClient.event(self.sysTray.winId(), "fatalerror", "Couldn't run 'smart'.") else: self.state = KSmartTray.State.RunningSmart QToolTip.remove(self.sysTray) QToolTip.add(self.sysTray, "Running Smart Package Manager...") def stopChecking(self): self.process.kill() def processDone(self, process): if self.state == KSmartTray.State.Updating: if not process.normalExit() or process.exitStatus() != 0: self.updateFailed = True if self.updateFailed and not self.lastKnownStatus == "": self.state = KSmartTray.State.Waiting else: process.resetAll() process.setArguments(["smart", "upgrade", "--check-update"]) if not process.start(): KNotifyClient.event(self.sysTray.winId(), "fatalerror", "Couldn't run 'smart upgrade'.") self.state = KSmartTray.State.Waiting self.lastKnownStatus = "" else: QToolTip.remove(self.sysTray) QToolTip.add(self.sysTray, "Verifying upgradable packages...") self.state = KSmartTray.State.Checking elif self.state == KSmartTray.State.Checking: self.state = KSmartTray.State.Waiting if process.normalExit(): if process.exitStatus() == 0: self.lastKnownStatus = "There are new upgrades available!" KNotifyClient.event(self.sysTray.winId(), "found-new-upgrades", self.lastKnownStatus) self.emit(PYSIGNAL("foundNewUpgrades()"), ()) elif process.exitStatus() == 1: self.lastKnownStatus = "There are pending upgrades!" if not self.updateFailed: KNotifyClient.event(self.sysTray.winId(), "found-old-upgrades", self.lastKnownStatus) self.emit(PYSIGNAL("foundOldUpgrades()"), ()) elif process.exitStatus() == 2: self.lastKnownStatus = "No interesting upgrades available." if not self.updateFailed: KNotifyClient.event(self.sysTray.winId(), "found-no-upgrades", self.lastKnownStatus) self.emit(PYSIGNAL("foundNoUpgrades()"), ()) else: self.lastKnownStatus = "" elif self.state == KSmartTray.State.Upgrading: self.state = KSmartTray.State.Waiting self.lastKnownStatus = "" elif self.state == KSmartTray.State.RunningSmart: self.state = KSmartTray.State.Waiting self.lastKnownStatus = "" else: # Error! pass if self.state == KSmartTray.State.Waiting: self.updateFailed = False self.sysTray.checkAction.setEnabled(True) self.sysTray.startSmartAction.setEnabled(True) self.sysTray.stopAction.setEnabled(False) if not self.lastKnownStatus == "": QToolTip.remove(self.sysTray) QToolTip.add(self.sysTray, self.lastKnownStatus) else: QToolTip.remove(self.sysTray) def startBlinking(self): if not self.blinkTimer.isActive(): self.blinkTimer.start(500) def stopBlinking(self): if self.blinkTimer.isActive(): self.blinkTimer.stop() self.sysTray.setPixmap(self.sysTray.loadIcon("ksmarttray")) def toggleBlink(self): if self.blinkFlag: self.sysTray.setPixmap(QPixmap()) else: self.sysTray.setPixmap(self.sysTray.loadIcon("ksmarttray")) self.blinkFlag = not self.blinkFlag
class QtReactor(posixbase.PosixReactorBase): def __init__(self): self._reads = {} self._writes = {} self._notifiers = {} self._timer = QTimer() self._timer.setSingleShot(True) self._timer.timeout.connect(self.iterate) if QCoreApplication.instance() is None: # Application Object has not been started yet self.qApp = QCoreApplication([]) self._ownApp = True else: self.qApp = QCoreApplication.instance() self._ownApp = False self._blockApp = None posixbase.PosixReactorBase.__init__(self) def _add(self, xer, primary, type): """ Private method for adding a descriptor from the event loop. It takes care of adding it if new or modifying it if already added for another state (read -> read/write for example). """ if xer not in primary: primary[xer] = TwistedSocketNotifier(None, self, xer, type) def addReader(self, reader): """ Add a FileDescriptor for notification of data available to read. """ self._add(reader, self._reads, QSocketNotifier.Read) def addWriter(self, writer): """ Add a FileDescriptor for notification of data available to write. """ self._add(writer, self._writes, QSocketNotifier.Write) def _remove(self, xer, primary): """ Private method for removing a descriptor from the event loop. It does the inverse job of _add, and also add a check in case of the fd has gone away. """ if xer in primary: notifier = primary.pop(xer) notifier.shutdown() def removeReader(self, reader): """ Remove a Selectable for notification of data available to read. """ self._remove(reader, self._reads) def removeWriter(self, writer): """ Remove a Selectable for notification of data available to write. """ self._remove(writer, self._writes) def removeAll(self): """ Remove all selectables, and return a list of them. """ rv = self._removeAll(self._reads, self._writes) return rv def getReaders(self): return self._reads.keys() def getWriters(self): return self._writes.keys() def callLater(self, howlong, *args, **kargs): rval = super(QtReactor, self).callLater(howlong, *args, **kargs) self.reactorInvocation() return rval def reactorInvocation(self): self._timer.stop() self._timer.setInterval(0) self._timer.start() def _iterate(self, delay=None, fromqt=False): """See twisted.internet.interfaces.IReactorCore.iterate. """ self.runUntilCurrent() self.doIteration(delay, fromqt) iterate = _iterate def doIteration(self, delay=None, fromqt=False): 'This method is called by a Qt timer or by network activity on a file descriptor' if not self.running and self._blockApp: self._blockApp.quit() self._timer.stop() delay = max(delay or 0, 1) if not fromqt: self.qApp.processEvents(QEventLoop.AllEvents, delay * 1000) if self.timeout() is None: timeout = 0.1 elif self.timeout() == 0: timeout = 0 else: timeout = self.timeout() self._timer.setInterval(timeout * 1000) self._timer.start() def runReturn(self, installSignalHandlers=True): self.startRunning(installSignalHandlers=installSignalHandlers) self.reactorInvocation() def run(self, installSignalHandlers=True): if self._ownApp: self._blockApp = self.qApp else: self._blockApp = QEventLoop() self.runReturn() self._blockApp.exec_()
class ClientDialog(QDialog): """a simple popup dialog for asking the player what he wants to do""" def __init__(self, client, parent=None): QDialog.__init__(self, parent) decorateWindow(self, m18n('Choose')) self.setObjectName('ClientDialog') self.client = client self.layout = QGridLayout(self) self.progressBar = QProgressBar() self.timer = QTimer() if not client.game.autoPlay: self.timer.timeout.connect(self.timeout) self.deferred = None self.buttons = [] self.setWindowFlags(Qt.SubWindow | Qt.WindowStaysOnTopHint) self.setModal(False) self.btnHeight = 0 self.answered = False self.move = None self.sorry = None def keyPressEvent(self, event): """ESC selects default answer""" if not self.client.game or self.client.game.autoPlay: return if event.key() in [Qt.Key_Escape, Qt.Key_Space]: self.selectButton() event.accept() else: for btn in self.buttons: if str(event.text()).upper() == btn.message.shortcut: self.selectButton(btn) event.accept() return QDialog.keyPressEvent(self, event) def __declareButton(self, message): """define a button""" maySay = self.client.game.myself.sayable[message] if Internal.Preferences.showOnlyPossibleActions and not maySay: return btn = DlgButton(message, self) btn.setAutoDefault(True) btn.clicked.connect(self.selectedAnswer) self.buttons.append(btn) def focusTileChanged(self): """update icon and tooltip for the discard button""" if not self.client.game: return for button in self.buttons: button.decorate(self.client.game.myself.handBoard.focusTile) for uiTile in self.client.game.myself.handBoard.lowerHalfTiles(): txt = [] for button in self.buttons: _, _, tileTxt = button.message.toolTip(button, uiTile.tile) if tileTxt: txt.append(tileTxt) uiTile.setToolTip('<br><br>'.join(txt)) if self.client.game.activePlayer == self.client.game.myself: Internal.scene.handSelectorChanged( self.client.game.myself.handBoard) def checkTiles(self): """does the logical state match the displayed tiles?""" for player in self.client.game.players: player.handBoard.checkTiles() def messages(self): """a list of all messages returned by the declared buttons""" return list(x.message for x in self.buttons) def proposeAction(self): """either intelligently or first button by default. May also focus a proposed tile depending on the action.""" result = self.buttons[0] game = self.client.game if game.autoPlay or Internal.Preferences.propose: answer, parameter = game.myself.intelligence.selectAnswer( self.messages()) result = [x for x in self.buttons if x.message == answer][0] result.setFocus() if answer in [Message.Discard, Message.OriginalCall]: for uiTile in game.myself.handBoard.uiTiles: if uiTile.tile is parameter: game.myself.handBoard.focusTile = uiTile return result def askHuman(self, move, answers, deferred): """make buttons specified by answers visible. The first answer is default. The default button only appears with blue border when this dialog has focus but we always want it to be recognizable. Hence setBackgroundRole.""" self.move = move self.deferred = deferred for answer in answers: self.__declareButton(answer) self.focusTileChanged() self.show() self.checkTiles() game = self.client.game myTurn = game.activePlayer == game.myself prefButton = self.proposeAction() if game.autoPlay: self.selectButton(prefButton) return prefButton.setFocus() self.progressBar.setVisible(not myTurn) if not myTurn: msecs = 50 self.progressBar.setMinimum(0) self.progressBar.setMaximum( game.ruleset.claimTimeout * 1000 // msecs) self.progressBar.reset() self.timer.start(msecs) def placeInField(self): """place the dialog at bottom or to the right depending on space.""" mainWindow = Internal.scene.mainWindow cwi = mainWindow.centralWidget() view = mainWindow.centralView geometry = self.geometry() if not self.btnHeight: self.btnHeight = self.buttons[0].height() vertical = view.width() > view.height() * 1.2 if vertical: height = (len(self.buttons) + 1) * self.btnHeight * 1.2 width = (cwi.width() - cwi.height()) // 2 geometry.setX(cwi.width() - width) geometry.setY(min(cwi.height() // 3, cwi.height() - height)) else: handBoard = self.client.game.myself.handBoard if not handBoard: # we are in the progress of logging out return hbLeftTop = view.mapFromScene( handBoard.mapToScene(handBoard.rect().topLeft())) hbRightBottom = view.mapFromScene( handBoard.mapToScene(handBoard.rect().bottomRight())) width = hbRightBottom.x() - hbLeftTop.x() height = self.btnHeight geometry.setY(cwi.height() - height) geometry.setX(hbLeftTop.x()) for idx, btn in enumerate(self.buttons + [self.progressBar]): self.layout.addWidget( btn, idx + 1 if vertical else 0, idx + 1 if not vertical else 0) idx = len(self.buttons) + 2 spacer = QSpacerItem( 20, 20, QSizePolicy.Expanding, QSizePolicy.Expanding) self.layout.addItem( spacer, idx if vertical else 0, idx if not vertical else 0) geometry.setWidth(width) geometry.setHeight(height) self.setGeometry(geometry) def showEvent(self, dummyEvent): """try to place the dialog such that it does not cover interesting information""" self.placeInField() def timeout(self): """the progressboard wants an update""" pBar = self.progressBar if isAlive(pBar): pBar.setValue(pBar.value() + 1) pBar.setVisible(True) if pBar.value() == pBar.maximum(): # timeout: we always return the original default answer, not # the one with focus self.selectButton() pBar.setVisible(False) def selectButton(self, button=None): """select default answer. button may also be of type Message.""" if self.answered: # sometimes we get this event twice return if button is None: button = self.focusWidget() if isinstance(button, Message): assert any(x.message == button for x in self.buttons) answer = button else: answer = button.message if not self.client.game.myself.sayable[answer]: self.proposeAction().setFocus() # go back to default action self.sorry = Sorry(m18n('You cannot say %1', answer.i18nName)) return self.timer.stop() self.answered = True if self.sorry: self.sorry.cancel() self.sorry = None Internal.scene.clientDialog = None self.deferred.callback(answer) def selectedAnswer(self, dummyChecked): """the user clicked one of the buttons""" game = self.client.game if game and not game.autoPlay: self.selectButton(self.sender())
class QTReactor(posixbase.PosixReactorBase): """Qt based reactor.""" # Reference to a DelayedCall for self.crash() when the reactor is # entered through .iterate() _crashCall = None _timer = None def __init__(self, app=None): self.running = 0 posixbase.PosixReactorBase.__init__(self) if app is None: app = QApplication([]) self.qApp = app self.addSystemEventTrigger('after', 'shutdown', self.cleanup) def addReader(self, reader): if not hasReader(reader): reads[reader] = TwistedSocketNotifier(self, reader, QSocketNotifier.Read) def addWriter(self, writer): if not hasWriter(writer): writes[writer] = TwistedSocketNotifier(self, writer, QSocketNotifier.Write) def removeReader(self, reader): if hasReader(reader): reads[reader].shutdown() del reads[reader] def removeWriter(self, writer): if hasWriter(writer): writes[writer].shutdown() del writes[writer] def removeAll(self): return self._removeAll(reads, writes) def simulate(self): if self._timer is not None: self._timer.stop() self._timer = None if not self.running: self.running = 1 self.qApp.exit_loop() return self.runUntilCurrent() if self._crashCall is not None: self._crashCall.reset(0) # gah timeout = self.timeout() if timeout is None: timeout = 1.0 timeout = min(timeout, 0.1) * 1010 if self._timer is None: self._timer = QTimer() QObject.connect(self._timer, SIGNAL("timeout()"), self.simulate) self._timer.start(timeout, 1) def cleanup(self): if self._timer is not None: self._timer.stop() self._timer = None def iterate(self, delay=0.0): log.msg(channel='system', event='iteration', reactor=self) self._crashCall = self.callLater(delay, self.crash) self.run() def run(self, installSignalHandlers=1): self.running = 1 self.startRunning(installSignalHandlers=installSignalHandlers) self.simulate() self.qApp.enter_loop() def crash(self): if self._crashCall is not None: if self._crashCall.active(): self._crashCall.cancel() self._crashCall = None self.running = 0
class ClientDialog(QDialog): """a simple popup dialog for asking the player what he wants to do""" def __init__(self, client, parent=None): QDialog.__init__(self, parent) decorateWindow(self, i18n('Choose')) self.setObjectName('ClientDialog') self.client = client self.layout = QGridLayout(self) self.progressBar = QProgressBar() self.progressBar.setMinimumHeight(25) self.timer = QTimer() if not client.game.autoPlay: self.timer.timeout.connect(self.timeout) self.deferred = None self.buttons = [] self.setWindowFlags(Qt.SubWindow | Qt.WindowStaysOnTopHint) self.setModal(False) self.btnHeight = 0 self.answered = False self.move = None self.sorry = None def keyPressEvent(self, event): """ESC selects default answer""" if not self.client.game or self.client.game.autoPlay: return if event.key() in [Qt.Key_Escape, Qt.Key_Space]: self.selectButton() event.accept() else: for btn in self.buttons: if str(event.text()).upper() == btn.message.shortcut: self.selectButton(btn) event.accept() return QDialog.keyPressEvent(self, event) def __declareButton(self, message): """define a button""" maySay = self.client.game.myself.sayable[message] if Internal.Preferences.showOnlyPossibleActions and not maySay: return btn = DlgButton(message, self) btn.setAutoDefault(True) btn.clicked.connect(self.selectedAnswer) self.buttons.append(btn) def focusTileChanged(self): """update icon and tooltip for the discard button""" if not self.client.game: return for button in self.buttons: button.setMeaning(self.client.game.myself.handBoard.focusTile) for uiTile in self.client.game.myself.handBoard.lowerHalfTiles(): txt = [] for button in self.buttons: _, _, tileTxt = button.message.toolTip(button, uiTile.tile) if tileTxt: txt.append(tileTxt) uiTile.setToolTip('<br><br>'.join(txt)) if self.client.game.activePlayer == self.client.game.myself: Internal.scene.handSelectorChanged( self.client.game.myself.handBoard) def checkTiles(self): """does the logical state match the displayed tiles?""" for player in self.client.game.players: player.handBoard.checkTiles() def messages(self): """a list of all messages returned by the declared buttons""" return list(x.message for x in self.buttons) def proposeAction(self): """either intelligently or first button by default. May also focus a proposed tile depending on the action.""" result = self.buttons[0] game = self.client.game if game.autoPlay or Internal.Preferences.propose: answer, parameter = game.myself.intelligence.selectAnswer( self.messages()) result = [x for x in self.buttons if x.message == answer][0] result.setFocus() if answer in [Message.Discard, Message.OriginalCall]: for uiTile in game.myself.handBoard.uiTiles: if uiTile.tile is parameter: game.myself.handBoard.focusTile = uiTile return result def askHuman(self, move, answers, deferred): """make buttons specified by answers visible. The first answer is default. The default button only appears with blue border when this dialog has focus but we always want it to be recognizable. Hence setBackgroundRole.""" self.move = move self.deferred = deferred for answer in answers: self.__declareButton(answer) self.focusTileChanged() self.show() self.checkTiles() game = self.client.game myTurn = game.activePlayer == game.myself prefButton = self.proposeAction() if game.autoPlay: self.selectButton(prefButton) return prefButton.setFocus() self.progressBar.setVisible(not myTurn) if not myTurn: msecs = 50 self.progressBar.setMinimum(0) self.progressBar.setMaximum( game.ruleset.claimTimeout * 1000 // msecs) self.progressBar.reset() self.timer.start(msecs) def placeInField(self): """place the dialog at bottom or to the right depending on space.""" mainWindow = Internal.scene.mainWindow cwi = mainWindow.centralWidget() view = mainWindow.centralView geometry = self.geometry() if not self.btnHeight: self.btnHeight = self.buttons[0].height() vertical = view.width() > view.height() * 1.2 if vertical: height = (len(self.buttons) + 1) * self.btnHeight * 1.2 width = (cwi.width() - cwi.height()) // 2 geometry.setX(cwi.width() - width) geometry.setY(min(cwi.height() // 3, cwi.height() - height)) else: handBoard = self.client.game.myself.handBoard if not handBoard: # we are in the progress of logging out return hbLeftTop = view.mapFromScene( handBoard.mapToScene(handBoard.rect().topLeft())) hbRightBottom = view.mapFromScene( handBoard.mapToScene(handBoard.rect().bottomRight())) width = hbRightBottom.x() - hbLeftTop.x() height = self.btnHeight geometry.setY(cwi.height() - height) geometry.setX(hbLeftTop.x()) for idx, btn in enumerate(self.buttons + [self.progressBar]): self.layout.addWidget( btn, idx + 1 if vertical else 0, idx + 1 if not vertical else 0) idx = len(self.buttons) + 2 spacer = QSpacerItem( 20, 20, QSizePolicy.Expanding, QSizePolicy.Expanding) self.layout.addItem( spacer, idx if vertical else 0, idx if not vertical else 0) geometry.setWidth(width) geometry.setHeight(height) self.setGeometry(geometry) def showEvent(self, dummyEvent): """try to place the dialog such that it does not cover interesting information""" self.placeInField() def timeout(self): """the progressboard wants an update""" pBar = self.progressBar if isAlive(pBar): pBar.setValue(pBar.value() + 1) pBar.setVisible(True) if pBar.value() == pBar.maximum(): # timeout: we always return the original default answer, not # the one with focus self.selectButton() pBar.setVisible(False) def selectButton(self, button=None): """select default answer. button may also be of type Message.""" if self.answered: # sometimes we get this event twice return if button is None: button = self.focusWidget() if isinstance(button, Message): assert any(x.message == button for x in self.buttons) answer = button else: answer = button.message if not self.client.game.myself.sayable[answer]: self.proposeAction().setFocus() # go back to default action self.sorry = Sorry(i18n('You cannot say %1', answer.i18nName)) return self.timer.stop() self.answered = True if self.sorry: self.sorry.cancel() self.sorry = None Internal.scene.clientDialog = None self.deferred.callback(answer) def selectedAnswer(self, dummyChecked): """the user clicked one of the buttons""" game = self.client.game if game and not game.autoPlay: self.selectButton(self.sender())
from ctk import * from qt import QTimer w = ctkMatrixWidget() w.show() if not _ctkPythonConsoleInstance.isInteractive: #QTimer().singleShot(0, app(), SLOT('quit()')) t = QTimer() t.setInterval(250) t.connect('timeout()', app(), 'quit()') t.start()
class ProstateTRUSNavUltrasound(UltraSound): OFFLINE_VOLUME_FILENAME = "RecVol_Reference.mha" SCOUT_VOLUME_FILENAME = "ScoutScan.mha" LIVE_VOLUME_FILENAME = "LiveReconstructedVolume.mha" RECORDING_FILENAME = "Recording.mha" SCOUT_RECORDING_FILENAME = "ScoutScanRecording.mha" LIVE_RECORDING_FILENAME = LIVE_VOLUME_FILENAME SCOUT_VOLUME_NODE_NAME = "ScoutScan" OFFLINE_VOLUME_NODE_NAME = "RecVol_Reference" LIVE_VOLUME_NODE_NAME = "liveReconstruction" APPLY_HOLE_FILLING_FOR_SNAPSHOT = False SNAPSHOT_INTERVAL = 3 OUTPUT_VOLUME_SPACING = 3 LIVE_OUTPUT_VOLUME_SPACING = 1 @property def roiNode(self): return self._roiNode @roiNode.setter def roiNode(self, node): self._roiNode = node if node is not None: self.startStopLiveReconstructionButton.setEnabled(True) else: self.startStopLiveReconstructionButton.setEnabled(False) def __init__(self, guideletParent): UltraSound.__init__(self, guideletParent) self.parameterNode = guideletParent.parameterNode self.parameterNodeObserver = None self._roiNode = None self.liveOutputSpacingValue = [ self.LIVE_OUTPUT_VOLUME_SPACING, self.LIVE_OUTPUT_VOLUME_SPACING, self.LIVE_OUTPUT_VOLUME_SPACING ] self.outputSpacing = [ self.OUTPUT_VOLUME_SPACING, self.OUTPUT_VOLUME_SPACING, self.OUTPUT_VOLUME_SPACING ] self.roiOrigin = None self.roiExtent = None self.defaultParameterNode = None self.logic = ProstateTRUSNavUltrasoundLogic() def setupPanel(self, parentWidget): logging.debug('ProstateTRUSNavUltrasound.setupPanel') self.connectorNode = self.guideletParent.connectorNode self.connectorNodeConnected = False collapsibleButton = ctkCollapsibleButton() collapsibleButton.setProperty('collapsedHeight', 20) setButtonStyle(collapsibleButton, 2.0) collapsibleButton.text = "Ultrasound" parentWidget.addWidget(collapsibleButton) ultrasoundLayout = QFormLayout(collapsibleButton) ultrasoundLayout.setContentsMargins(12, 4, 4, 4) ultrasoundLayout.setSpacing(4) self.connectDisconnectButton = QPushButton("Connect") self.connectDisconnectButton.setToolTip( "If clicked, connection OpenIGTLink") hbox = QHBoxLayout() hbox.addWidget(self.connectDisconnectButton) ultrasoundLayout.addRow(hbox) self.setupIcons() self.captureIDSelector = QComboBox() self.captureIDSelector.setToolTip("Pick capture device ID") self.captureIDSelector.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.volumeReconstructorIDSelector = QComboBox() self.volumeReconstructorIDSelector.setToolTip( "Pick volume reconstructor device ID") self.volumeReconstructorIDSelector.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopRecordingButton = QPushButton(" Start Recording") self.startStopRecordingButton.setCheckable(True) self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setEnabled(False) self.startStopRecordingButton.setToolTip("If clicked, start recording") self.startStopRecordingButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) recordParametersControlsLayout = QGridLayout() self.filenameLabel = self.createLabel("Filename:", visible=False) recordParametersControlsLayout.addWidget(self.filenameLabel, 1, 0) # Offline Reconstruction self.offlineReconstructButton = QPushButton(" Offline Reconstruction") self.offlineReconstructButton.setCheckable(True) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setEnabled(False) self.offlineReconstructButton.setToolTip( "If clicked, reconstruct recorded volume") self.offlineReconstructButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.offlineVolumeToReconstructSelector = QComboBox() self.offlineVolumeToReconstructSelector.setEditable(True) self.offlineVolumeToReconstructSelector.setToolTip( "Pick/set volume to reconstruct") self.offlineVolumeToReconstructSelector.visible = False hbox = QHBoxLayout() hbox.addWidget(self.startStopRecordingButton) hbox.addWidget(self.offlineReconstructButton) ultrasoundLayout.addRow(hbox) # Scout scan (record and low resolution reconstruction) and live reconstruction # Scout scan part self.startStopScoutScanButton = QPushButton( " Scout scan\n Start recording") self.startStopScoutScanButton.setCheckable(True) self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setToolTip("If clicked, start recording") self.startStopScoutScanButton.setEnabled(False) self.startStopScoutScanButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopLiveReconstructionButton = QPushButton( " Start live reconstruction") self.startStopLiveReconstructionButton.setCheckable(True) self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, start live reconstruction") self.startStopLiveReconstructionButton.setEnabled(False) self.startStopLiveReconstructionButton.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding) self.displayRoiButton = QToolButton() self.displayRoiButton.setCheckable(True) self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") hbox = QHBoxLayout() hbox.addWidget(self.startStopScoutScanButton) hbox.addWidget(self.startStopLiveReconstructionButton) # hbox.addWidget(self.displayRoiButton) ultrasoundLayout.addRow(hbox) self.snapshotTimer = QTimer() self.snapshotTimer.setSingleShot(True) self.onParameterSetSelected() return collapsibleButton def setupResliceDriver(self): layoutManager = slicer.app.layoutManager() # Show ultrasound in red view. redSlice = layoutManager.sliceWidget('Red') redSliceLogic = redSlice.sliceLogic() redSliceLogic.GetSliceCompositeNode().SetBackgroundVolumeID( self.liveUltrasoundNode_Reference.GetID()) resliceLogic = slicer.modules.volumereslicedriver.logic() if resliceLogic: redNode = slicer.util.getNode('vtkMRMLSliceNodeRed') redNode.SetSliceResolutionMode( slicer.vtkMRMLSliceNode.SliceResolutionMatchVolumes) resliceLogic.SetDriverForSlice( self.liveUltrasoundNode_Reference.GetID(), redNode) resliceLogic.SetModeForSlice( 6, redNode) # Transverse mode, default for PLUS ultrasound. else: logging.warning('Logic not found for Volume Reslice Driver') def createCollapsibleButton(self, text, collapsed=False): collapsibleButton = ctkCollapsibleButton() collapsibleButton.text = text collapsibleButton.collapsed = collapsed return collapsibleButton def createLabel(self, text, visible=True): label = QLabel() label.setText(text) label.visible = visible return label def setupConnections(self): self.startStopRecordingButton.connect( 'clicked(bool)', self.onStartStopRecordingButtonClicked) self.offlineReconstructButton.connect('clicked(bool)', self.onReconstVolume) self.startStopScoutScanButton.connect( 'clicked(bool)', self.onStartStopScoutScanButtonClicked) self.startStopLiveReconstructionButton.connect( 'clicked(bool)', self.onStartStopLiveReconstructionButtonClicked) self.displayRoiButton.connect('clicked(bool)', self.onDisplayRoiButtonClicked) self.captureIDSelector.connect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.volumeReconstructorIDSelector.connect( 'currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.offlineVolumeToReconstructSelector.connect( 'currentIndexChanged(int)', self.updateParameterNodeFromGui) self.displayRoiButton.connect('clicked(bool)', self.updateParameterNodeFromGui) self.snapshotTimer.timeout.connect( self.onRequestVolumeReconstructionSnapshot) self.connectDisconnectButton.connect( 'clicked(bool)', self.onConnectDisconnectButtonClicked) def disconnect(self): self.startStopRecordingButton.disconnect( 'clicked(bool)', self.onStartStopRecordingButtonClicked) self.offlineReconstructButton.disconnect('clicked(bool)', self.onReconstVolume) self.startStopScoutScanButton.disconnect( 'clicked(bool)', self.onStartStopScoutScanButtonClicked) self.startStopLiveReconstructionButton.disconnect( 'clicked(bool)', self.onStartStopLiveReconstructionButtonClicked) self.displayRoiButton.disconnect('clicked(bool)', self.onDisplayRoiButtonClicked) self.captureIDSelector.disconnect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.volumeReconstructorIDSelector.disconnect( 'currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.offlineVolumeToReconstructSelector.disconnect( 'currentIndexChanged(int)', self.updateParameterNodeFromGui) self.displayRoiButton.disconnect('clicked(bool)', self.updateParameterNodeFromGui) self.snapshotTimer.timeout.disconnect( self.onRequestVolumeReconstructionSnapshot) self.connectDisconnectButton.disconnect( 'clicked(bool)', self.onConnectDisconnectButtonClicked) def setupIcons(self): self.plusRemoteModuleDirectoryPath = slicer.modules.plusremote.path.replace( "PlusRemote.py", "") self.recordIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Record.png') self.stopIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Stop.png') self.waitIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Wait.png') self.visibleOffIcon = QIcon(":Icons\VisibleOff.png") self.visibleOnIcon = QIcon(":Icons\VisibleOn.png") def onParameterSetSelected(self): # Set up default values for new nodes if self.parameterNode: self.plusRemoteLogic.setDefaultParameters(self.parameterNode) self.updateGuiFromParameterNode() def updateGuiFromParameterNode(self): self.parameterVolumeList = { 'OfflineVolumeToReconstruct': self.offlineVolumeToReconstructSelector } for parameter in self.parameterVolumeList: if self.parameterNode.GetParameter(parameter): self.parameterVolumeList[parameter].blockSignals(True) self.parameterVolumeList[parameter].blockSignals(False) if self.parameterNode.GetParameter('CaptureID'): self.captureIDSelector.blockSignals(True) for i in range(0, self.captureIDSelector.count): if self.parameterNode.GetParameter( 'CaptureID') == self.captureIDSelector.itemText(i): self.captureIDSelector.setCurrentIndex( int(self.parameterNode.GetParameter('CaptureIdIndex'))) self.captureIDSelector.blockSignals(False) if self.parameterNode.GetParameter('VolumeReconstructor'): self.volumeReconstructorIDSelector.blockSignals(True) for i in range(0, self.volumeReconstructorIDSelector.count): if self.parameterNode.GetParameter( 'VolumeReconstructor' ) == self.volumeReconstructorIDSelector.itemText(i): self.volumeReconstructorIDSelector.setCurrentIndex( int( self.parameterNode.GetParameter( 'VolumeReconstructorIndex'))) self.volumeReconstructorIDSelector.blockSignals(False) self.roiNode = self.parameterNode.GetNthNodeReference('ROI', 0) def updateParameterNodeFromGui(self): #Update parameter node value to save when user change value in the interface if not self.parameterNode: return self.parametersList = { 'CaptureID': self.captureIDSelector.currentText, 'CaptureIdIndex': self.captureIDSelector.currentIndex, 'VolumeReconstructor': self.volumeReconstructorIDSelector.currentText, 'VolumeReconstructorIndex': self.volumeReconstructorIDSelector.currentIndex, 'OfflineVolumeToReconstruct': self.offlineVolumeToReconstructSelector.currentIndex } for parameter in self.parametersList: self.parameterNode.SetParameter( parameter, str(self.parametersList[parameter])) if self.roiNode: roiNodeID = self.roiNode.GetID() self.parameterNode.SetNthNodeReferenceID('ROI', 0, roiNodeID) # # Connector observation and actions # def onConnectorNodeConnected(self): logging.debug("ProstateTrusUltrasound:onConnectorNodeConnected") self.connectorNodeConnected = True self.captureIDSelector.setDisabled(False) self.volumeReconstructorIDSelector.setDisabled(False) self.plusRemoteLogic.getCaptureDeviceIds( self.connectorNode.GetID(), self.onGetCaptureDeviceCommandResponseReceived) self.plusRemoteLogic.getVolumeReconstructorDeviceIds( self.connectorNode.GetID(), self.onGetVolumeReconstructorDeviceCommandResponseReceived) self.connectDisconnectButton.setText("Disconnect") def onConnectorNodeDisconnected(self): logging.debug("ProstateTrusUltrasound:onConnectorNodeDisconnected") self.connectorNodeConnected = False self.startStopRecordingButton.setEnabled(False) self.startStopScoutScanButton.setEnabled(False) self.startStopLiveReconstructionButton.setEnabled(False) self.offlineReconstructButton.setEnabled(False) self.captureIDSelector.setDisabled(True) self.volumeReconstructorIDSelector.setDisabled(True) self.connectDisconnectButton.setText("Connect") def getLiveVolumeRecNode(self): liveVolumeRecNode = slicer.util.getNode(self.LIVE_VOLUME_NODE_NAME) return liveVolumeRecNode def getOfflineVolumeRecNode(self): offlineVolumeRecNode = slicer.util.getNode( self.OFFLINE_VOLUME_NODE_NAME) return offlineVolumeRecNode def getScoutVolumeNode(self): scoutScanVolumeNode = slicer.util.getNode(self.SCOUT_VOLUME_NODE_NAME) return scoutScanVolumeNode def onConnectDisconnectButtonClicked(self): if self.connectorNode.GetState( ) == slicer.vtkMRMLIGTLConnectorNode.STATE_CONNECTED: self.connectorNode.Stop() else: self.connectorNode.Start() def onStartStopRecordingButtonClicked(self): if self.startStopRecordingButton.isChecked(): self.startStopRecordingButton.setText(" Stop Recording") self.startStopRecordingButton.setIcon(self.stopIcon) self.startStopRecordingButton.setToolTip( "If clicked, stop recording") self.onStartRecording(self.generateRecordingOutputFilename()) else: self.startStopRecordingButton.setText(" Start Recording") self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setToolTip( "If clicked, start recording") self.onStopRecording(self.onVolumeRecorded) def onStartStopScoutScanButtonClicked(self): if self.startStopScoutScanButton.isChecked(): self.startStopScoutScanButton.setText( " Scout Scan\n Stop Recording and Reconstruct Recorded Volume" ) self.startStopScoutScanButton.setIcon(self.stopIcon) self.startStopScoutScanButton.setToolTip( "If clicked, stop recording and reconstruct recorded volume") self.onStartRecording(self.generateScoutRecordingOutputFilename()) else: self.onStopRecording(self.onScoutVolumeRecorded) def onStartStopLiveReconstructionButtonClicked(self): if self.startStopLiveReconstructionButton.isChecked(): if self.roiNode: self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI( self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) self.startStopLiveReconstructionButton.setText( " Stop Live Reconstruction") self.startStopLiveReconstructionButton.setIcon(self.stopIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, stop live reconstruction") self.onStartRecording(self.getLiveRecordingOutputFilename()) self.onStartReconstruction() else: self.startStopLiveReconstructionButton.setText( " Start Live Reconstruction") self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, start live reconstruction") self.onStopRecording(self.printCommandResponse) self.onStopReconstruction() def onDisplayRoiButtonClicked(self): if self.displayRoiButton.isChecked(): self.displayRoiButton.setIcon(self.visibleOnIcon) self.displayRoiButton.setToolTip("If clicked, hide ROI") if self.roiNode: self.roiNode.SetDisplayVisibility(1) else: self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") if self.roiNode: self.roiNode.SetDisplayVisibility(0) def generateRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename( self.RECORDING_FILENAME) def generateScoutRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename( self.SCOUT_RECORDING_FILENAME) def getLiveRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename( self.LIVE_RECORDING_FILENAME) def getLiveReconstructionOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename( self.LIVE_VOLUME_FILENAME) def onStartRecording(self, filename): self.plusRemoteLogic.startRecording(self.connectorNode.GetID(), self.captureIDSelector.currentText, filename, self.printCommandResponse) def onStopRecording(self, callback): self.plusRemoteLogic.stopRecording(self.connectorNode.GetID(), self.captureIDSelector.currentText, callback) def onStartReconstruction(self): if self.roiNode: self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI( self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) self.plusRemoteLogic.startVolumeReconstuction( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.liveOutputSpacingValue, self.roiOrigin, self.roiExtent, self.printCommandResponse, self.getLiveReconstructionOutputFilename(), self.LIVE_VOLUME_NODE_NAME) # Set up timer for requesting snapshot self.snapshotTimer.start(self.SNAPSHOT_INTERVAL * 1000) def onStopReconstruction(self): self.snapshotTimer.stop() self.plusRemoteLogic.stopVolumeReconstruction( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.onVolumeLiveReconstructed, self.getLiveReconstructionOutputFilename(), self.LIVE_VOLUME_NODE_NAME) def onReconstVolume(self): self.offlineReconstructButton.setIcon(self.waitIcon) self.offlineReconstructButton.setText( " Offline Reconstruction in progress ...") self.offlineReconstructButton.setEnabled(False) self.plusRemoteLogic.reconstructRecorded( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.offlineVolumeToReconstructSelector.currentText, self.outputSpacing, self.onVolumeReconstructed, self.OFFLINE_VOLUME_FILENAME, self.OFFLINE_VOLUME_NODE_NAME) def onScoutScanReconstVolume(self): self.startStopScoutScanButton.setIcon(self.waitIcon) self.startStopScoutScanButton.setText( " Scout Scan\n Reconstruction in progress ...") self.startStopScoutScanButton.setEnabled(False) self.plusRemoteLogic.reconstructRecorded( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.lastScoutRecordingOutputFilename, self.outputSpacing, self.onScoutVolumeReconstructed, self.SCOUT_VOLUME_FILENAME, self.SCOUT_VOLUME_NODE_NAME) def onRequestVolumeReconstructionSnapshot(self, stopFlag=""): self.plusRemoteLogic.getVolumeReconstructionSnapshot( self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.LIVE_VOLUME_FILENAME, self.LIVE_VOLUME_NODE_NAME, self.APPLY_HOLE_FILLING_FOR_SNAPSHOT, self.onSnapshotAcquired) def executeCommandDelayed(self, method, delay=100): # Order of OpenIGTLink message receiving and processing is not guaranteed to be the same # therefore we wait a bit to make sure the image message is processed as well QTimer.singleShot(delay, method) def printCommandResponse(self, command, q): statusText = "Command {0} [{1}]: {2}\n".format( command.GetCommandName(), command.GetID(), command.StatusToString(command.GetStatus())) if command.GetResponseMessage(): statusText = statusText + command.GetResponseMessage() elif command.GetResponseText(): statusText = statusText + command.GetResponseText() logging.debug(statusText) def onGetCaptureDeviceCommandResponseReceived(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() != command.CommandSuccess: return captureDeviceIdsListString = command.GetResponseMessage() if captureDeviceIdsListString: captureDevicesIdsList = captureDeviceIdsListString.split(",") else: captureDevicesIdsList = [] for i in range(0, len(captureDevicesIdsList)): if self.captureIDSelector.findText(captureDevicesIdsList[i]) == -1: self.captureIDSelector.addItem(captureDevicesIdsList[i]) def onGetVolumeReconstructorDeviceCommandResponseReceived( self, command, q): self.printCommandResponse(command, q) if command.GetStatus() != command.CommandSuccess: return volumeReconstructorDeviceIdsListString = command.GetResponseMessage() if volumeReconstructorDeviceIdsListString: volumeReconstructorDeviceIdsList = volumeReconstructorDeviceIdsListString.split( ",") else: volumeReconstructorDeviceIdsList = [] self.volumeReconstructorIDSelector.clear() self.volumeReconstructorIDSelector.addItems( volumeReconstructorDeviceIdsList) self.startStopRecordingButton.setEnabled(True) self.offlineReconstructButton.setEnabled(True) self.startStopScoutScanButton.setEnabled(True) if self.roiNode: self.startStopLiveReconstructionButton.setEnabled(True) def onVolumeRecorded(self, command, q): self.printCommandResponse(command, q) self.offlineReconstructButton.setEnabled(True) volumeToReconstructFileName = os.path.basename( command.GetResponseMessage()) self.offlineVolumeToReconstructSelector.insertItem( 0, volumeToReconstructFileName) self.offlineVolumeToReconstructSelector.setCurrentIndex(0) def onScoutVolumeRecorded(self, command, q): self.printCommandResponse(command, q) self.offlineReconstructButton.setEnabled(True) if command.GetStatus() == command.CommandExpired: logging.fatal( "Scout Volume Recording: Timeout while waiting for volume reconstruction result" ) return if command.GetStatus() == command.CommandSuccess: self.lastScoutRecordingOutputFilename = os.path.basename( command.GetResponseMessage()) self.onScoutScanReconstVolume() def onVolumeReconstructed(self, command, q): self.printCommandResponse(command, q) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setText("Offline Reconstruction") self.offlineReconstructButton.setEnabled(True) self.offlineReconstructButton.setChecked(False) if command.GetStatus() == command.CommandExpired: # volume reconstruction command timed out logging.fatal( "Volume Reconstruction: Timeout while waiting for volume reconstruction result" ) return if command.GetStatus() != command.CommandSuccess: logging.debug("Volume Reconstruction: " + command.GetResponseMessage()) return self.executeCommandDelayed(self.onVolumeReconstructedFinalize) def onVolumeReconstructedFinalize(self): applicationLogic = slicer.app.applicationLogic() applicationLogic.FitSliceToAll() self.guideletParent.showVolumeRendering(self.getOfflineVolumeRecNode()) def onScoutVolumeReconstructed(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() == command.CommandExpired: logging.fatal( "Scout Volume Reconstruction: Timeout while waiting for scout volume reconstruction result" ) return self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setText( " Scout Scan\n Start Recording") self.startStopScoutScanButton.setEnabled(True) if command.GetStatus() != command.CommandSuccess: logging.debug("Scout Volume Reconstruction: " + command.GetResponseMessage()) return self.executeCommandDelayed(self.onScoutVolumeReconstructedFinalize) def onScoutVolumeReconstructedFinalize(self): # Create and initialize ROI after scout scan because low resolution scout scan is used to set # a smaller ROI for the live high resolution reconstruction self.roiNode = self.logic.onRoiInitialization( self.SCOUT_VOLUME_NODE_NAME, self.roiNode) self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI( self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) scoutScanVolumeNode = self.getScoutVolumeNode() applicationLogic = slicer.app.applicationLogic() applicationLogic.FitSliceToAll() self.guideletParent.showVolumeRendering(scoutScanVolumeNode) def onSnapshotAcquired(self, command, q): self.printCommandResponse(command, q) if not self.startStopLiveReconstructionButton.isChecked(): # live volume reconstruction is not active return self.executeCommandDelayed(self.onSnapshotAcquiredFinalize) def onSnapshotAcquiredFinalize(self): self.guideletParent.showVolumeRendering(self.getLiveVolumeRecNode()) self.snapshotTimer.start(self.SNAPSHOT_INTERVAL * 1000) def onVolumeLiveReconstructed(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() == command.CommandExpired: logging.fatal( "LIVE Volume Reconstruction: Failed to stop volume reconstruction" ) return if command.GetStatus() != command.CommandSuccess: logging.debug("LIVE Volume Reconstruction " + command.GetResponseMessage()) return self.executeCommandDelayed(self.getLiveVolumeRecNode) def onVolumeLiveReconstructedFinalize(self): self.guideletParent.showVolumeRendering(self.getLiveVolumeRecNode())
class SampleControl(QObject): """ Manages a sample's port connections and emits signals when it has changed. SIGNALS: PYSIGNAL('loaded'), () PYSIGNAL('unloaded'), () PYSIGNAL('volumeChanged'), (vol,) PYSIGNAL('start'), () PYSIGNAL('pause'), (pos,) PYSIGNAL('unpause'), (pos,) PYSIGNAL('cue'), () PYSIGNAL('cueChanged'), (cue,) PYSIGNAL('positionChanged'), (pos,) PYSIGNAL('reverbChanged'), (rev,) PYSIGNAL('delayChanged'), (del,) PYSIGNAL('looping'), (bool,) PYSIGNAL('pitchChanged'), (pitch,) PYSIGNAL('midiPitchChanged'), (pitch, ) PYSIGNAL('grouped'), (grouped,) PYSIGNAL('zoneChanged'), (zone, a0) # slotStart called, awaiting forceSlotStart() PYSIGNAL('waitingForStart'), ()) """ def __init__(self): """ sample -> splitter |-> volume -> pan -> muter -> mixers[0] |-> volume -> pan -> muter -> mixers[1] | ... |-> volume -> pan -> mute from globals import * """ QObject.__init__(self) self.sample = None self.currentCue = 0 self.cues = [] self.groupingEnabled = 0 self.beatSynced = 0 self.pitchRange = PITCH_RANGE self.savedPitchRange = 0 self.driver = pkaudio.Driver() # Pitch : when real/temp pitch match, pitch is not bent self.pitchTimer = QTimer(self) QObject.connect(self.pitchTimer, SIGNAL("timeout()"), self.slotDoPitchBend) self.pitchTemp = 0.0 # the bent pitch self.realPitch = 0.0 # the original pitch self.pitchDirection = "back" self.path = None self.splitter = pkaudio.Splitter() # Effect chains effectChain0 = {} effectChain1 = {} self.effectChains = [effectChain0, effectChain1] # connect eveything up for i, chain in enumerate(self.effectChains): chain['volume'] = pkaudio.Volume() chain['pan'] = pkaudio.Pan() chain['peak'] = pkaudio.PeakModule() chain['muter'] = pkaudio.Muter() chain['muter'].setOn(0) chain['volume'].outputPort().connect(chain['pan'].inputPort()) chain['pan'].outputPort().connect(chain['peak'].inputPort()) chain['peak'].outputPort().connect(chain['muter'].inputPort()) if i != 1: self.splitter.outputPort(i).connect(chain['volume'].inputPort()) else: self.splitter.outputPort(i).connect(chain['pan'].inputPort()) self.effectChains[0]['volume'].setProperty('volume', 75) self.slotConnectMixers() def __del__(self): for chain in self.effectChains: if chain['muter'].outputPort() != None: chain['muter'].outputPort().disconnect() self.unload() def load(self, path): """ Load the file and persistent data at 'path'. """ try: self.sample = pkaudio.Sample(path) except pkaudio.FileError: Globals.Print('Could not open '+path) self.sample = None return self.path = path conf = Globals.ConfFile() conf.readSampleData(self) # set cue points if len(self.cues): self.sample.setProperty('start', self.cues[self.currentCue][0]) self.sample.setProperty('end', self.cues[self.currentCue][1]) else: self.sample.setProperty('start', 0) self.sample.setProperty('end', self.sample.length()) # Set looping on samples < 300 secs (5 min) if self.sample.length() < 13230000: self.slotLooping(1) self.sample.outputPort().connect(self.splitter.inputPort()) self.emit(PYSIGNAL('loaded'), ()) def isLoaded(self): """ Returns true if the sample is loaded and can be played. """ return self.sample and True or False def unload(self): """ Delete the sample, saves persistent data. """ if self.isLoaded(): conf = Globals.ConfFile() conf.writeSampleData(self) conf.save() conf = None self.sample = None self.emit(PYSIGNAL('unloaded'), ()) self.path = None def getShortName(self): bn = os.path.basename(self.path) return bn[:bn.rfind('.')] def getPeak(self): chain = self.effectChains[0] return (chain['peak'].right() + chain['peak'].left()) / 1.5 def sampleId(self): """ Return he id of the sample, or -1 if no sampfrom Globals import * """ if self.sample: return self.sample.id() else: return -1 def isPlaying(self): if self.sample: return self.sample.isPlaying() else: return False def pos(self): if self.sample: return self.sample.pos() else: return 0 def getLength(self): if self.sample: return self.sample.length() else: return 0 def getVolume(self, zone=0): """ Return the volume for the passed zone. """ if not zone in self.effectChains: zone = 0 return self.effectChains[zone]['volume'].getProperty('volume') def setVolume(self, vol, zone=0): """ Just set the volume, don't emit the signal. """ if not zone in self.effectChains: zone = 0 self.effectChains[0]['volume'].setProperty('volume', vol) def slotVolume(self, a0): """ Called by the slider. 0 <= a0 <= 127. """ a0 = 127 - a0 volume = int((a0 * 100) / 127) self.setVolume(volume) self.emit(PYSIGNAL('volumeChanged'), (volume,)) def setGrouped(self, a0): """ Set whether the sample should be consdered part of a group. This value can be used for anything. """ self.emit(PYSIGNAL('grouped'), (a0,)) self.groupingEnabled = a0 return self.groupingEnabled def grouped(self): return self.groupingEnabled def setDeepGroup(self, id): """ Tell the C++ code that it manages this sample's grouping. """ if self.sample: self.sample.setGroup(int(id)) def slotStart(self): """ Starts playing the sample from the cue point. """ if self.sample: # the delay if self.sample.getGroup() > 0: self.startDeepSync() else: self.forceStart() def startDeepSync(self): """ Start using the more accurate C++ group. """ if self.sample and self.sample.getGroup() > 0: self.sample.startWithGroup() def notifyYouStarted(self): """ Get all the widgets rolling a/i the sample started. This will usually get called as a callback from startDeepSync(). """ self.emitStarted() def forceStart(self): """ Just start now. """ if self.sample: self.slotCue() self.sample.play() self.emitStarted() def emitStarted(self): """ Just emit the signal w/o starting the stream. """ if self.sample: self.emit(PYSIGNAL('start'), ()) def slotPause(self): """ Pauses/UnPauses the sample. """ if self.sample: if self.sample.isPlaying(): self.sample.stop() self.emit(PYSIGNAL('pause'), (self.sample.pos(), )) else: self.sample.play() self.emit(PYSIGNAL('unpause'), (self.sample.pos(), )) def slotUnpause(self): """ Pauses/UnPauses the sample. """ if self.sample: if not self.sample.isPlaying(): self.sample.play() self.emit(PYSIGNAL('unpause'), (self.sample.pos(), )) def slotCue(self): """ Plays or stops the play object """ if self.sample: self.sample.stop() self.sample.reset() self.emit(PYSIGNAL('cue'), ()) def slotSearch(self, pos): """ Set the location of the sample. """ if self.sample: self.sample.pos(pos) self.emit(PYSIGNAL('positionChanged'), (pos,)) def slotCuePoint(self, index): """ Sets the current cue point. """ if index < 0: index = 0 elif index >= Globals.n_cues: index = Globals.n_cues-1 if index != self.currentCue and self.sample: self.currentCue = index self.sample.setProperty('start', self.cues[self.currentCue][0]) self.sample.setProperty('end', self.cues[self.currentCue][1]) self.emit(PYSIGNAL('cueChanged'), (self.currentCue,)) def slotReverb(self, v): #if self.reverb.numControls(): # self.reverb.control(0).tick(v) self.emit(PYSIGNAL('reverbChanged'), (v,)) def slotDelay(self, v): #if self.delay.numControls(): # self.delay.control(1).tick((v/127.0) * 5) self.emit(PYSIGNAL('delayChanged'), (v,)) def slotLooping(self, a0): """ Set looping to a0. """ if self.sample: self.sample.setLooping(a0) self.emit(PYSIGNAL('looping'), (a0,)) def slotPitchUp(self): """ Starts bending the pitch up. """ if self.sample: self.pitchDirection = "up" self.pitchTemp = self.sample.getPitch() self.pitchTimer.stop() self.pitchTimer.start(PITCH_RES) def slotPitchDown(self): """ Starts bending the pitch down. """ if self.sample: self.pitchDirection = "down" self.pitchTemp = self.sample.getPitch() self.pitchTimer.stop() self.pitchTimer.start(PITCH_RES) def slotPitchStop(self): """ Starts bending the pitch back to normal. """ self.pitchDirection = "back" def slotDoPitchBend(self): """ Does the pitch bend, called by the pitch timer. """ if self.sample: if self.pitchDirection == "up": if self.pitchTemp < self.realPitch + PITCH_MAX: self.pitchTemp += PITCH_INC elif self.pitchDirection == "down": if self.pitchTemp > self.realPitch - PITCH_MAX: self.pitchTemp -= PITCH_INC elif self.pitchDirection == "back": if self.pitchTemp == self.realPitch: self.pitchTimer.stop() # adjust it else: # done if abs(self.pitchTemp - self.realPitch) < PITCH_INC: self.pitchTemp = self.realPitch self.pitchTimer.stop() # rolling up elif self.pitchTemp < self.realPitch: self.pitchTemp += PITCH_INC #rolling down elif self.pitchTemp > self.realPitch: self.pitchTemp -= PITCH_INC self.sample.setPitch(self.pitchTemp) self.emit(PYSIGNAL('pitch'), ()) def slotNudgeUp(self): """ Nudges the pitch setting up. """ if self.sample: if self.pitchTemp != self.realPitch: # then the pitch is being bent, # just set the real pitch self.realPitch += .02 self.emit(PYSIGNAL('pitchChanged'), (self.realPitch,)) else: self.slotPitch(self.sample.getPitch() + .02) def slotNudgeDown(self): """ Nudges the pitch setting down. """ if self.sample: if self.pitchTemp != self.realPitch: # then the pitch is being bent, # just set the real pitch self.realPitch -= .02 self.emit(PYSIGNAL('pitchChanged'), (self.realPitch,)) else: self.slotPitch(self.sample.getPitch() - .02) def slotPitch(self, pitch): """ Pass a floating point value. pitch should be in PK::DJEngine range. """ # self.pitchLabel.setText(str(fpformat.fix(pitch, 2)) + "%") if self.sample: self.sample.setPitch(pitch) self.realPitch = self.sample.getPitch() self.emit(PYSIGNAL('pitchChanged'), (self.sample.getPitch(),)) def slotMidiPitch(self, a0): """ Pass a midi value. """ self.emit(PYSIGNAL('midiPitchChanged'), (a0,)) a0 = 127 - a0 if a0 >= 64: a0 -= 1 pitch = self.pitchRange - (a0 / 63.0) * self.pitchRange elif a0 < 63: pitch = (self.pitchRange - (1 - ((a0 - 63) / 63.0)) * self.pitchRange) * -1 else: pitch = 0.0 self.slotPitch(pitch) def slotSetZone(self, zone, a0): """ Toggles the mute on a mixer. """ if zone < len(self.effectChains): self.effectChains[zone]['muter'].setOn(a0) self.emit(PYSIGNAL('zoneChanged'), (zone, a0,)) else: Globals.PrintErr('SampleControl.setZone: no such zone: '+str(zone)) def getZone(self, zone): if zone < len(self.effectChains): return self.effectChains[zone]['muter'].isOn() else: Globals.PrintErr('SampleControl.setZone: no such zone: '+str(zone)) def getPitch(self): """ Return a floating point value. """ if self.sample: return self.sample.getPitch() else: return 0.0 def looping(self): if self.sample and self.sample.getLooping(): return True else: return False def atEnd(self): if self.sample: return self.sample.atEnd() else: return True def setPitchRange(self, r): """ set the pitch range of the sample. """ self.savedPitchRange = 1 self.pitchRange = r def slotConnectMixers(self): """ Connect the effect chains to the mixers. Initialize mainMixer, cueMixer if necessary. """ global mainMixer, cueMixer for i, chain in enumerate(self.effectChains): if self.driver.numMixers() > i: if i == 0: if mainMixer == None: mainMixer = self.driver.getMixer(0) mainMixer.connect(self.effectChains[0]['muter'].outputPort()) elif i == 1: if cueMixer == None: cueMixer = self.driver.getMixer(1) cueMixer.connect(self.effectChains[1]['muter'].outputPort()) else: self.driver.getMixer(i).connect(self.effectChains[i]['muter'].outputPort())
class Commander(QObject): def __init__(self, parent): QObject.__init__(self) self.parent = parent # Modal dialogs freezes pm in dbus signal path self.delayTimer = QTimer(self) self.lastError = None ## self.connect(self.delayTimer, SIGNAL("timeout()"), self.exceptionHandler) self.iface = PisiIface.Iface() self.iface.setHandler(self.handler) self.iface.setExceptionHandler(self.exceptionHandler) def errHandler(self): self.iface.com_lock.unlock() self.parent.finished("System.Manager.cancelled") self.parent.resetState() self.parent.refreshState() def exceptionHandler(self, exception=None): exception = exception or self.lastError if "urlopen error" in str(exception) or "Socket Error" in str(exception): KMessageBox.error(None, i18n("Network error. Please check your network connections and try again or check your repository addresses."), i18n("COMAR Error")) elif "Access denied" in str(exception): message = i18n("You are not authorized for this operation.") KMessageBox.sorry(None, message, i18n("Error")) elif "PYCURL ERROR" in str(exception): message = i18n("Please check your network connection or repository addresses.") KMessageBox.sorry(None, message, i18n("Error")) else: KMessageBox.error(None, QString.fromUtf8(str(exception)), i18n("COMAR Error")) self.errHandler() def handler(self, package, signal, data): if len(data) > 1: args = data[1:] else: args = None if signal == "finished": command = data[0] self.iface.com_lock.unlock() self.parent.finished(command) elif signal == "progress": self.parent.displayProgress(data) elif signal == "error": self.iface.com_lock.unlock() print "Error: ", str(data) self.lastError = str(data) self.delayTimer.start(500, True) elif signal == "cancelled": self.parent.finished("System.Manager.cancelled") elif signal == "started": operation = signal self.parent.pisiNotify(operation, args) elif signal == "status": operation = data[0] self.parent.pisiNotify(operation, args) elif signal == "warning": self.iface.com_lock.unlock() # self.parent.showWarningMessage(str(args)) print "Warning: ", str(data) self.parent.resetState() self.parent.refreshState() elif signal == "PolicyKit" and "policy.no" in data: message = i18n("You are not authorized for this operation.") KMessageBox.sorry(None, message, i18n("Error")) else: print "Got notification : %s with data : %s" % (signal, data) def startUpdate(self, repo = None, handleErrors=True): if repo is None: self.updateAllRepos(handleErrors) else: self.updateRepo(repo) def install(self,apps): self.iface.installPackage(apps) def updatePackage(self,apps): self.iface.upgradePackages(apps) def remove(self,apps): self.iface.removePackages(apps) def updateRepo(self, repo): self.iface.updateRepository(repo) def updateAllRepos(self): self.iface.updateRepositories() def setRepositories(self, repos): self.iface.setRepositories(repos) def listUpgradable(self): return self.iface.getUpdates() def listPackages(self): return self.iface.getPackageList() def listNewPackages(self): return self.iface.getPackageList() def getRepoList(self): return map(lambda x:x[0], self.iface.getRepositories()) def getRepoUri(self,repoName): return self.iface.getRepositoryUrl(repoName) def cancel(self): self.iface.cancel() def checkConflicts(self, packages): return self.iface.getConflicts(packages) def inProgress(self): return self.iface.com_lock.locked() def clearCache(self, limit): self.iface.clearCache(limit) def setCache(self, enabled, limit): self.iface.setCacheLimit(enabled, limit) def setConfig(self, category, name, value): self.iface.setConfig(category, name, value)
class SystemTray(KSystemTray): def __init__(self, *args): apply(KSystemTray.__init__, (self, ) + args) ''' comarInterface instance ''' self.comarInterface = comarInterface(self.winId()) ''' wirelessInterface instance ''' self.wirelessInterface = wirelessInterface() ''' dcopInterface instance''' self.dcopInterface = dcopInterface(self.wirelessInterface) ''' Add /usr/share/PyWireless to KStandardDirs ''' self.KStandardDirs = KStandardDirs() self.KStandardDirs.addResourceDir('icon', '/usr/share/PyWireless') ''' Create tray icon Loader ''' self.icons = KIconLoader('PyWireless', self.KStandardDirs) ''' Timer event triggered every 3 second Until i found a way to use inotify or libfam ''' self.time = QTimer(self) self.connect(self.time, SIGNAL('timeout()'), self.timeoutSlot) self.time.start(3000) self.connect(app, SIGNAL("shutDown()"), self.slotQuit) ''' Popup Menu ''' connectionsMenu = KPopupMenu(self.contextMenu()) ''' list all connections into Connections menu ''' for entry in self.comarInterface.listConnections(): if self.comarInterface.isActive(entry): id = connectionsMenu.insertItem( QIconSet( self.icons.loadIcon('wireless-online', KIcon.Desktop, 16)), entry) else: id = connectionsMenu.insertItem( QIconSet( self.icons.loadIcon('wireless-offline', KIcon.Desktop, 16)), entry) self.connect(connectionsMenu, SIGNAL("activated(int)"), self.switchConnection) self.contextMenu().insertItem(_('Wireless Connections Profiles'), connectionsMenu) # FIXME: Use net-kga self.contextMenu().insertItem(_('Create New Wireless Connection')) self.show() def switchConnection(self, int): connection = self.contextMenu().text(int) if self.comarInterface.isActive(connection): ''' if selected is active then down it ''' self.comarInterface.deactivateConnection(connection) self.contextMenu().changeItem( int, QIconSet( self.icons.loadIcon('wireless-offline', KIcon.Desktop, 16)), self.contextMenu().text(int)) else: ''' if selected is not active then first down active one, up selected one ''' self.comarInterface.deactivateConnection( self.comarInterface.activeConnection()) self.comarInterface.activateConnection(connection) self.contextMenu().changeItem( int, QIconSet( self.icons.loadIcon('wireless-online', KIcon.Desktop, 16)), self.contextMenu().text(int)) def slotQuit(self): self.deleteLater() app.quit() def timeoutSlot(self): interfaceName = self.wirelessInterface.returnInterfaceName() interfaceESSID = self.wirelessInterface.returnESSID() interfaceMode = self.wirelessInterface.returnMode() linkStatus = self.wirelessInterface.returnLinkStatus() noiseStatus = self.wirelessInterface.returnNoiseStatus() signalStatus = self.wirelessInterface.returnSignalStatus() bitRate = self.wirelessInterface.returnBitrate() received = self.wirelessInterface.returnReceived() transferred = self.wirelessInterface.returnTransferred() status = self.wirelessInterface.returnInterfaceStatus() ''' Tray icon name ''' if int(status): index = int(linkStatus) / 20 iconName = 'pywireless_' + str(index) ''' Tooltip ''' toolTip = _('''<center><img align="center" src="/usr/share/PyWireless/%s.png"></center> <center> <table border="0" bgcolor="#000000" cellspacing="1" cellpadding="1"> <tr> <td colspan="2" bgcolor="#04CC1A"><center><b>Monitoring:</b> [ %s ]</b></center></td> <tr> <td bgcolor="#CCCCCC"><b>ESSID:</b></td> <td bgcolor="#CCCCCC"><center>%s</center></td> </tr> <tr> <td bgcolor="#EEEEEE"><b>Link Quality:</b></td> <td bgcolor="#EEEEEE"><center>%d</center></td> </tr> <tr> <td bgcolor="#CCCCCC"><b>Bitrate:</b></td> <td bgcolor="#CCCCCC"><center>%s</center></td> </tr> <tr> <td bgcolor="#EEEEEE"><b>Mode:</b></td> <td bgcolor="#EEEEEE"><center>%s</center></td> </tr> <tr> <td bgcolor="#CCCCCC"><b>Noise Level:</b></td> <td bgcolor="#CCCCCC"><center>%d dBm</center></td> </tr> <tr> <td bgcolor="#EEEEEE"><b>Signal Level:</b></td> <td bgcolor="#EEEEEE"><center>%d dBm</center></td> </tr> <tr> <td bgcolor="#CCCCCC"><b>Received:</b></td> <td bgcolor="#CCCCCC"><center>%s</center></td> </tr> <tr> <td bgcolor="#EEEEEE"><b>Transferred:</b></td> <td bgcolor="#EEEEEE"><center>%s</center></td> </tr> </table> </center> ''') % (iconName, interfaceName, interfaceESSID, \ linkStatus, bitRate, interfaceMode, \ noiseStatus, signalStatus, received, transferred) else: iconName = 'pywireless' toolTip = _( '''<center><img align="center" src="/usr/share/PyWireless/%s.png"></center> <center> <table border="0" bgcolor="#000000" cellspacing="1" cellpadding="1"> <tr> <td colspan="2" bgcolor="#DD0500"><center>[ %s ] <b>is powered off</b></center></td> tr> </table> </center>''') % (iconName, interfaceName) QToolTip.add(self, toolTip) self.setPixmap(self.icons.loadIcon(iconName, KIcon.Desktop, 22))
from ctk import * from qt import QTimer # Test display of a CTK widget w = ctkMatrixWidget() w.show() # Test command execution using Python manager pythonManager = _ctkPythonManagerInstance pythonManager.executeString("variableInPythonConsole=523") try: print("variableInPythonConsole was successfully set to {0}".format( variableInPythonConsole)) except: print "PythonManager.executeString failed" qt.QApplication.exit(1) if not _ctkPythonConsoleInstance.isInteractive: #QTimer().singleShot(0, app(), SLOT('quit()')) t = QTimer() t.setInterval(250) t.connect('timeout()', app(), 'quit()') t.start()
class MainWin(KMainWindow): """Main window""" SB_TEXT = 1 SB_TIMEOUT = 10000 MON_TIMEOUT = 1000 CHANGE_TIMEOUT = 3001 def __init__(self, *args): apply(KMainWindow.__init__, (self,) + args) self.lastDir = "/var/log" self.monitors = [] self.currentPage = None self.tab = QTabWidget(self) self.settingsDlg = SettingsDlg(self) self.cfg = LoviConfig().getInstance() self.bellIcon = \ QIconSet(KIconLoader().loadIcon("idea", KIcon.Small, 11)) self.noIcon = QIconSet() self.findDlg = KEdFind(self, "find", False) self.connect(self.findDlg, SIGNAL("search()"), self.doFind) self.setCentralWidget(self.tab) self.connect(self.tab, SIGNAL("currentChanged(QWidget *)"), self.onPageChange) self.setGeometry(0, 0, 600, 400) self.setCaption(makeCaption("(none)")) # Timers self.timer = QTimer(self) self.timer.start(MainWin.MON_TIMEOUT) self.statusTimer = QTimer(self) self.connect(self.statusTimer, SIGNAL("timeout()"), self.onStatusTimeout) self.changeTimer = QTimer(self) self.changeTimer.start(MainWin.CHANGE_TIMEOUT) self.connect(self.changeTimer, SIGNAL("timeout()"), self.onChangeTimeout) # Initialize actions actions = self.actionCollection() self.openAction = KStdAction.open(self.onOpen, actions) self.closeAction = KStdAction.close(self.onClose, actions) self.closeAction.setEnabled(False) self.quitAction = KStdAction.quit(self.onQuit, actions) self.copyAction = KStdAction.copy(self.onCopy, actions) self.copyAction.setEnabled(False) self.clearAction = KStdAction.clear(self.onClear, actions) self.clearAction.setEnabled(False) self.selectAllAction = KStdAction.selectAll(self.onSelectAll, actions) self.selectAllAction.setEnabled(False) self.addBookmarkAction = \ KStdAction.addBookmark(self.onAddBookmark, actions) self.addBookmarkAction.setEnabled(False) self.settingsAction = KStdAction.preferences(self.onSettings, actions) self.findAction = KStdAction.find(self.onFind, actions) self.findAction.setEnabled(False) self.findNextAction = KStdAction.findNext(self.onFindNext, actions) self.findNextAction.setEnabled(False) self.findPrevAction = KStdAction.findPrev(self.onFindPrev, actions) self.findPrevAction.setEnabled(False) # Initialize menus fileMenu = QPopupMenu(self) self.openAction.plug(fileMenu) self.closeAction.plug(fileMenu) fileMenu.insertSeparator() self.quitAction.plug(fileMenu) self.menuBar().insertItem(i18n("&File"), fileMenu) editMenu = QPopupMenu(self) self.copyAction.plug(editMenu) self.clearAction.plug(editMenu) editMenu.insertSeparator() self.selectAllAction.plug(editMenu) self.addBookmarkAction.plug(editMenu) editMenu.insertSeparator() self.findAction.plug(editMenu) self.findNextAction.plug(editMenu) self.findPrevAction.plug(editMenu) self.menuBar().insertItem(i18n("&Edit"), editMenu) settingsMenu = QPopupMenu(self) self.settingsAction.plug(settingsMenu) self.menuBar().insertItem(i18n("&Settings"), settingsMenu) helpMenu = self.helpMenu("") self.menuBar().insertItem(i18n("&Help"), helpMenu) # Initialize status bar self.sb = self.statusBar() self.bell = BellButton(None) self.displayStatus(False, "") def displayStatus(self, changed, msg): """Display a message in the status bar.""" self.statusTimer.stop() self.sb.removeWidget(self.bell) self.sb.removeItem(MainWin.SB_TEXT) if changed: self.sb.addWidget(self.bell, 1, False) self.sb.insertItem(msg, MainWin.SB_TEXT, 1000, True) self.sb.setItemAlignment(MainWin.SB_TEXT, Qt.AlignLeft|Qt.AlignVCenter) self.statusTimer.start(MainWin.SB_TIMEOUT, True) def onOpen(self, id = -1): """Open file for monitoring.""" fileName = KFileDialog.getOpenFileName(self.lastDir, "*", self, str(i18n("Open Log File"))) if not fileName.isEmpty(): fileName = str(fileName) self.lastDir = os.path.dirname(fileName) self.monitor(fileName) def onClose(self, id = -1): """Close a monitored file.""" self.monitors.remove(self.currentPage) self.currentPage.close() self.tab.removePage(self.currentPage) self.displayStatus(False, "") self.saveFileList() if len(self.monitors) == 0: # Update interface when the last page is deleted self.setCaption(makeCaption("(none)")) self.closeAction.setEnabled(False) self.copyAction.setEnabled(False) self.selectAllAction.setEnabled(False) self.clearAction.setEnabled(False) self.addBookmarkAction.setEnabled(False) self.findAction.setEnabled(False) self.findNextAction.setEnabled(False) self.findPrevAction.setEnabled(False) def onQuit(self, id = -1): """Quit application.""" self.close() def onCopy(self, id = -1): """Copy text to clipboard.""" self.currentPage.copy() def onClear(self, id = -1): """Clear text window.""" self.currentPage.setText("") def onSelectAll(self, id = -1): """Select all text.""" self.currentPage.selectAll(True) def onAddBookmark(self, id = -1): """Add a bookmark to the log.""" bookmark = "<font color=\"blue\">" bookmark += datetime.datetime.now().strftime("%b %d %H:%M:%S ") bookmark += "--------------------------------------------------------" bookmark += "</font>" self.currentPage.append(bookmark) def onSettings(self, id = -1): """Display settings dialog""" if self.settingsDlg.exec_loop(): self.cfg.writeConfig() self.cfg.processConfig() self.reconfigure() def onPageChange(self, page): """Update widget when the top level tab changes.""" self.currentPage = page self.setCaption(makeCaption(os.path.basename(page.getFileName()))) self.copyAction.setEnabled(page.hasSelectedText()) # self.tab.setTabIconSet(page, self.noIcon) def onStatusTimeout(self): """Clear status bar on timeout.""" self.displayStatus(False, "") for m in self.monitors: self.tab.setTabIconSet(m, self.noIcon) def onChangeTimeout(self): """Look for changes in monitored files. """ changeList = [] for m in self.monitors: if m.isChanged(): changeList.append(os.path.basename(m.getFileName())) self.tab.setTabIconSet(m, self.bellIcon) if len(changeList): msg = changeList[0] for f in changeList[1:]: msg += ", %s" % f msg = str(i18n("Change to %s")) % msg self.displayStatus(True, msg) def onCopyAvailable(self, available): """Update Copy menu item when there is a selection available.""" self.copyAction.setEnabled(available) def onFind(self): self.findDlg.show() def onFindPrev(self): if self.findDlg.getText() == "": self.onFind() else: self.currentPage.find(self.findDlg.getText(), self.findDlg.case_sensitive(), True) def onFindNext(self): if self.findDlg.getText() == "": self.onFind() else: self.currentPage.find(self.findDlg.getText(), self.findDlg.case_sensitive(), False) def monitor(self, fileName): """Start monitoring a file.""" try: tailer = Tail(fileName) except: KMessageBox.error(self, str(i18n("Cannot open file for monitoring:\n%s")) % fileName, makeCaption("Error")) return mon = Monitor(self.tab, tailer) base = os.path.basename(fileName) self.monitors.append(mon) self.tab.addTab(mon, base) self.tab.showPage(mon) self.tab.setTabToolTip(mon, fileName) self.currentPage = mon self.setCaption(makeCaption(base)) self.displayStatus(False, str(i18n("Monitoring %s")) % fileName) self.connect(self.timer, SIGNAL("timeout()"), mon.follow) self.saveFileList() self.connect(mon, SIGNAL("copyAvailable(bool)"), self.onCopyAvailable) self.closeAction.setEnabled(True) self.copyAction.setEnabled(False) self.clearAction.setEnabled(True) self.selectAllAction.setEnabled(True) self.addBookmarkAction.setEnabled(True) self.findAction.setEnabled(True) self.findNextAction.setEnabled(True) self.findPrevAction.setEnabled(True) def saveFileList(self): """Update the list of monitored files in the configuration file.""" files = [] for mon in self.monitors: files.append(mon.getFileName()) cfg = KApplication.kApplication().config() cfg.setGroup("Monitor") cfg.writeEntry("files", files) def reconfigure(self): """Update self with configuration changes.""" for mon in self.monitors: mon.reconfigure() def doFind(self): self.currentPage.find(self.findDlg.getText(), self.findDlg.case_sensitive(), self.findDlg.get_direction())
class ProstateTRUSNavUltrasound(UltraSound): OFFLINE_VOLUME_FILENAME = "RecVol_Reference.mha" SCOUT_VOLUME_FILENAME = "ScoutScan.mha" LIVE_VOLUME_FILENAME = "LiveReconstructedVolume.mha" RECORDING_FILENAME = "Recording.mha" SCOUT_RECORDING_FILENAME = "ScoutScanRecording.mha" LIVE_RECORDING_FILENAME = LIVE_VOLUME_FILENAME SCOUT_VOLUME_NODE_NAME = "ScoutScan" OFFLINE_VOLUME_NODE_NAME = "RecVol_Reference" LIVE_VOLUME_NODE_NAME = "liveReconstruction" APPLY_HOLE_FILLING_FOR_SNAPSHOT = False SNAPSHOT_INTERVAL = 3 OUTPUT_VOLUME_SPACING = 3 LIVE_OUTPUT_VOLUME_SPACING = 1 @property def roiNode(self): return self._roiNode @roiNode.setter def roiNode(self, node): self._roiNode=node if node is not None: self.startStopLiveReconstructionButton.setEnabled(True) else: self.startStopLiveReconstructionButton.setEnabled(False) def __init__(self, guideletParent): UltraSound.__init__(self, guideletParent) self.parameterNode = guideletParent.parameterNode self.parameterNodeObserver = None self._roiNode = None self.liveOutputSpacingValue = [self.LIVE_OUTPUT_VOLUME_SPACING, self.LIVE_OUTPUT_VOLUME_SPACING, self.LIVE_OUTPUT_VOLUME_SPACING] self.outputSpacing = [self.OUTPUT_VOLUME_SPACING, self.OUTPUT_VOLUME_SPACING, self.OUTPUT_VOLUME_SPACING] self.roiOrigin = None self.roiExtent = None self.defaultParameterNode = None self.logic = ProstateTRUSNavUltrasoundLogic() def setupPanel(self, parentWidget): logging.debug('ProstateTRUSNavUltrasound.setupPanel') self.connectorNode = self.guideletParent.connectorNode self.connectorNodeConnected = False collapsibleButton = ctkCollapsibleButton() collapsibleButton.setProperty('collapsedHeight', 20) setButtonStyle(collapsibleButton, 2.0) collapsibleButton.text = "Ultrasound" parentWidget.addWidget(collapsibleButton) ultrasoundLayout = QFormLayout(collapsibleButton) ultrasoundLayout.setContentsMargins(12,4,4,4) ultrasoundLayout.setSpacing(4) self.connectDisconnectButton = QPushButton("Connect") self.connectDisconnectButton.setToolTip("If clicked, connection OpenIGTLink") hbox = QHBoxLayout() hbox.addWidget(self.connectDisconnectButton) ultrasoundLayout.addRow(hbox) self.setupIcons() self.captureIDSelector = QComboBox() self.captureIDSelector.setToolTip("Pick capture device ID") self.captureIDSelector.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.volumeReconstructorIDSelector = QComboBox() self.volumeReconstructorIDSelector.setToolTip( "Pick volume reconstructor device ID" ) self.volumeReconstructorIDSelector.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopRecordingButton = QPushButton(" Start Recording") self.startStopRecordingButton.setCheckable(True) self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setEnabled(False) self.startStopRecordingButton.setToolTip("If clicked, start recording") self.startStopRecordingButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) recordParametersControlsLayout = QGridLayout() self.filenameLabel = self.createLabel("Filename:", visible=False) recordParametersControlsLayout.addWidget(self.filenameLabel, 1, 0) # Offline Reconstruction self.offlineReconstructButton = QPushButton(" Offline Reconstruction") self.offlineReconstructButton.setCheckable(True) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setEnabled(False) self.offlineReconstructButton.setToolTip("If clicked, reconstruct recorded volume") self.offlineReconstructButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.offlineVolumeToReconstructSelector = QComboBox() self.offlineVolumeToReconstructSelector.setEditable(True) self.offlineVolumeToReconstructSelector.setToolTip( "Pick/set volume to reconstruct" ) self.offlineVolumeToReconstructSelector.visible = False hbox = QHBoxLayout() hbox.addWidget(self.startStopRecordingButton) hbox.addWidget(self.offlineReconstructButton) ultrasoundLayout.addRow(hbox) # Scout scan (record and low resolution reconstruction) and live reconstruction # Scout scan part self.startStopScoutScanButton = QPushButton(" Scout scan\n Start recording") self.startStopScoutScanButton.setCheckable(True) self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setToolTip("If clicked, start recording") self.startStopScoutScanButton.setEnabled(False) self.startStopScoutScanButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.startStopLiveReconstructionButton = QPushButton(" Start live reconstruction") self.startStopLiveReconstructionButton.setCheckable(True) self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip("If clicked, start live reconstruction") self.startStopLiveReconstructionButton.setEnabled(False) self.startStopLiveReconstructionButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.displayRoiButton = QToolButton() self.displayRoiButton.setCheckable(True) self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") hbox = QHBoxLayout() hbox.addWidget(self.startStopScoutScanButton) hbox.addWidget(self.startStopLiveReconstructionButton) # hbox.addWidget(self.displayRoiButton) ultrasoundLayout.addRow(hbox) self.snapshotTimer = QTimer() self.snapshotTimer.setSingleShot(True) self.onParameterSetSelected() return collapsibleButton def setupResliceDriver(self): layoutManager = slicer.app.layoutManager() # Show ultrasound in red view. redSlice = layoutManager.sliceWidget('Red') redSliceLogic = redSlice.sliceLogic() redSliceLogic.GetSliceCompositeNode().SetBackgroundVolumeID(self.liveUltrasoundNode_Reference.GetID()) resliceLogic = slicer.modules.volumereslicedriver.logic() if resliceLogic: redNode = slicer.util.getNode('vtkMRMLSliceNodeRed') redNode.SetSliceResolutionMode(slicer.vtkMRMLSliceNode.SliceResolutionMatchVolumes) resliceLogic.SetDriverForSlice(self.liveUltrasoundNode_Reference.GetID(), redNode) resliceLogic.SetModeForSlice(6, redNode) # Transverse mode, default for PLUS ultrasound. else: logging.warning('Logic not found for Volume Reslice Driver') def createCollapsibleButton(self, text, collapsed=False): collapsibleButton = ctkCollapsibleButton() collapsibleButton.text = text collapsibleButton.collapsed = collapsed return collapsibleButton def createLabel(self, text, visible=True): label = QLabel() label.setText(text) label.visible = visible return label def setupConnections(self): self.startStopRecordingButton.connect('clicked(bool)', self.onStartStopRecordingButtonClicked) self.offlineReconstructButton.connect('clicked(bool)', self.onReconstVolume) self.startStopScoutScanButton.connect('clicked(bool)', self.onStartStopScoutScanButtonClicked) self.startStopLiveReconstructionButton.connect('clicked(bool)', self.onStartStopLiveReconstructionButtonClicked) self.displayRoiButton.connect('clicked(bool)', self.onDisplayRoiButtonClicked) self.captureIDSelector.connect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.volumeReconstructorIDSelector.connect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.offlineVolumeToReconstructSelector.connect('currentIndexChanged(int)', self.updateParameterNodeFromGui) self.displayRoiButton.connect('clicked(bool)', self.updateParameterNodeFromGui) self.snapshotTimer.timeout.connect(self.onRequestVolumeReconstructionSnapshot) self.connectDisconnectButton.connect('clicked(bool)', self.onConnectDisconnectButtonClicked) def disconnect(self): self.startStopRecordingButton.disconnect('clicked(bool)', self.onStartStopRecordingButtonClicked) self.offlineReconstructButton.disconnect('clicked(bool)', self.onReconstVolume) self.startStopScoutScanButton.disconnect('clicked(bool)', self.onStartStopScoutScanButtonClicked) self.startStopLiveReconstructionButton.disconnect('clicked(bool)', self.onStartStopLiveReconstructionButtonClicked) self.displayRoiButton.disconnect('clicked(bool)', self.onDisplayRoiButtonClicked) self.captureIDSelector.disconnect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.volumeReconstructorIDSelector.disconnect('currentIndexChanged(QString)', self.updateParameterNodeFromGui) self.offlineVolumeToReconstructSelector.disconnect('currentIndexChanged(int)', self.updateParameterNodeFromGui) self.displayRoiButton.disconnect('clicked(bool)', self.updateParameterNodeFromGui) self.snapshotTimer.timeout.disconnect(self.onRequestVolumeReconstructionSnapshot) self.connectDisconnectButton.disconnect('clicked(bool)', self.onConnectDisconnectButtonClicked) def setupIcons(self): self.plusRemoteModuleDirectoryPath = slicer.modules.plusremote.path.replace("PlusRemote.py", "") self.recordIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Record.png') self.stopIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Stop.png') self.waitIcon = QIcon(self.plusRemoteModuleDirectoryPath + '/Resources/Icons/icon_Wait.png') self.visibleOffIcon = QIcon(":Icons\VisibleOff.png") self.visibleOnIcon = QIcon(":Icons\VisibleOn.png") def onParameterSetSelected(self): # Set up default values for new nodes if self.parameterNode: self.plusRemoteLogic.setDefaultParameters(self.parameterNode) self.updateGuiFromParameterNode() def updateGuiFromParameterNode(self): self.parameterVolumeList = {'OfflineVolumeToReconstruct': self.offlineVolumeToReconstructSelector} for parameter in self.parameterVolumeList: if self.parameterNode.GetParameter(parameter): self.parameterVolumeList[parameter].blockSignals(True) self.parameterVolumeList[parameter].blockSignals(False) if self.parameterNode.GetParameter('CaptureID'): self.captureIDSelector.blockSignals(True) for i in range(0, self.captureIDSelector.count): if self.parameterNode.GetParameter('CaptureID') == self.captureIDSelector.itemText(i): self.captureIDSelector.setCurrentIndex(int(self.parameterNode.GetParameter('CaptureIdIndex'))) self.captureIDSelector.blockSignals(False) if self.parameterNode.GetParameter('VolumeReconstructor'): self.volumeReconstructorIDSelector.blockSignals(True) for i in range(0, self.volumeReconstructorIDSelector.count): if self.parameterNode.GetParameter('VolumeReconstructor') == self.volumeReconstructorIDSelector.itemText(i): self.volumeReconstructorIDSelector.setCurrentIndex(int(self.parameterNode.GetParameter('VolumeReconstructorIndex'))) self.volumeReconstructorIDSelector.blockSignals(False) self.roiNode = self.parameterNode.GetNthNodeReference('ROI', 0) def updateParameterNodeFromGui(self): #Update parameter node value to save when user change value in the interface if not self.parameterNode: return self.parametersList = {'CaptureID': self.captureIDSelector.currentText, 'CaptureIdIndex': self.captureIDSelector.currentIndex, 'VolumeReconstructor': self.volumeReconstructorIDSelector.currentText, 'VolumeReconstructorIndex': self.volumeReconstructorIDSelector.currentIndex, 'OfflineVolumeToReconstruct': self.offlineVolumeToReconstructSelector.currentIndex} for parameter in self.parametersList: self.parameterNode.SetParameter(parameter, str(self.parametersList[parameter])) if self.roiNode: roiNodeID = self.roiNode.GetID() self.parameterNode.SetNthNodeReferenceID('ROI', 0, roiNodeID) # # Connector observation and actions # def onConnectorNodeConnected(self): logging.debug("ProstateTrusUltrasound:onConnectorNodeConnected") self.connectorNodeConnected = True self.captureIDSelector.setDisabled(False) self.volumeReconstructorIDSelector.setDisabled(False) self.plusRemoteLogic.getCaptureDeviceIds(self.connectorNode.GetID(), self.onGetCaptureDeviceCommandResponseReceived) self.plusRemoteLogic.getVolumeReconstructorDeviceIds(self.connectorNode.GetID(), self.onGetVolumeReconstructorDeviceCommandResponseReceived) self.connectDisconnectButton.setText("Disconnect") def onConnectorNodeDisconnected(self): logging.debug("ProstateTrusUltrasound:onConnectorNodeDisconnected") self.connectorNodeConnected = False self.startStopRecordingButton.setEnabled(False) self.startStopScoutScanButton.setEnabled(False) self.startStopLiveReconstructionButton.setEnabled(False) self.offlineReconstructButton.setEnabled(False) self.captureIDSelector.setDisabled(True) self.volumeReconstructorIDSelector.setDisabled(True) self.connectDisconnectButton.setText("Connect") def getLiveVolumeRecNode(self): liveVolumeRecNode = slicer.util.getNode(self.LIVE_VOLUME_NODE_NAME) return liveVolumeRecNode def getOfflineVolumeRecNode(self): offlineVolumeRecNode = slicer.util.getNode(self.OFFLINE_VOLUME_NODE_NAME) return offlineVolumeRecNode def getScoutVolumeNode(self): scoutScanVolumeNode = slicer.util.getNode(self.SCOUT_VOLUME_NODE_NAME) return scoutScanVolumeNode def onConnectDisconnectButtonClicked(self): if self.connectorNode.GetState() == slicer.vtkMRMLIGTLConnectorNode.STATE_CONNECTED: self.connectorNode.Stop() else: self.connectorNode.Start() def onStartStopRecordingButtonClicked(self): if self.startStopRecordingButton.isChecked(): self.startStopRecordingButton.setText(" Stop Recording") self.startStopRecordingButton.setIcon(self.stopIcon) self.startStopRecordingButton.setToolTip( "If clicked, stop recording" ) self.onStartRecording(self.generateRecordingOutputFilename()) else: self.startStopRecordingButton.setText(" Start Recording") self.startStopRecordingButton.setIcon(self.recordIcon) self.startStopRecordingButton.setToolTip( "If clicked, start recording" ) self.onStopRecording(self.onVolumeRecorded) def onStartStopScoutScanButtonClicked(self): if self.startStopScoutScanButton.isChecked(): self.startStopScoutScanButton.setText(" Scout Scan\n Stop Recording and Reconstruct Recorded Volume") self.startStopScoutScanButton.setIcon(self.stopIcon) self.startStopScoutScanButton.setToolTip( "If clicked, stop recording and reconstruct recorded volume" ) self.onStartRecording(self.generateScoutRecordingOutputFilename()) else: self.onStopRecording(self.onScoutVolumeRecorded) def onStartStopLiveReconstructionButtonClicked(self): if self.startStopLiveReconstructionButton.isChecked(): if self.roiNode: self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI(self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) self.startStopLiveReconstructionButton.setText(" Stop Live Reconstruction") self.startStopLiveReconstructionButton.setIcon(self.stopIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, stop live reconstruction" ) self.onStartRecording(self.getLiveRecordingOutputFilename()) self.onStartReconstruction() else: self.startStopLiveReconstructionButton.setText(" Start Live Reconstruction") self.startStopLiveReconstructionButton.setIcon(self.recordIcon) self.startStopLiveReconstructionButton.setToolTip( "If clicked, start live reconstruction" ) self.onStopRecording(self.printCommandResponse) self.onStopReconstruction() def onDisplayRoiButtonClicked(self): if self.displayRoiButton.isChecked(): self.displayRoiButton.setIcon(self.visibleOnIcon) self.displayRoiButton.setToolTip("If clicked, hide ROI") if self.roiNode: self.roiNode.SetDisplayVisibility(1) else: self.displayRoiButton.setIcon(self.visibleOffIcon) self.displayRoiButton.setToolTip("If clicked, display ROI") if self.roiNode: self.roiNode.SetDisplayVisibility(0) def generateRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename(self.RECORDING_FILENAME) def generateScoutRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename(self.SCOUT_RECORDING_FILENAME) def getLiveRecordingOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename(self.LIVE_RECORDING_FILENAME) def getLiveReconstructionOutputFilename(self): return self.plusRemoteLogic.addTimestampToFilename(self.LIVE_VOLUME_FILENAME) def onStartRecording(self, filename): self.plusRemoteLogic.startRecording(self.connectorNode.GetID(), self.captureIDSelector.currentText, filename, self.printCommandResponse) def onStopRecording(self, callback): self.plusRemoteLogic.stopRecording(self.connectorNode.GetID(), self.captureIDSelector.currentText, callback) def onStartReconstruction(self): if self.roiNode: self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI(self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) self.plusRemoteLogic.startVolumeReconstuction(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.liveOutputSpacingValue, self.roiOrigin, self.roiExtent, self.printCommandResponse, self.getLiveReconstructionOutputFilename(), self.LIVE_VOLUME_NODE_NAME) # Set up timer for requesting snapshot self.snapshotTimer.start(self.SNAPSHOT_INTERVAL*1000) def onStopReconstruction(self): self.snapshotTimer.stop() self.plusRemoteLogic.stopVolumeReconstruction(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.onVolumeLiveReconstructed, self.getLiveReconstructionOutputFilename(), self.LIVE_VOLUME_NODE_NAME) def onReconstVolume(self): self.offlineReconstructButton.setIcon(self.waitIcon) self.offlineReconstructButton.setText(" Offline Reconstruction in progress ...") self.offlineReconstructButton.setEnabled(False) self.plusRemoteLogic.reconstructRecorded(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.offlineVolumeToReconstructSelector.currentText, self.outputSpacing, self.onVolumeReconstructed, self.OFFLINE_VOLUME_FILENAME, self.OFFLINE_VOLUME_NODE_NAME) def onScoutScanReconstVolume(self): self.startStopScoutScanButton.setIcon(self.waitIcon) self.startStopScoutScanButton.setText(" Scout Scan\n Reconstruction in progress ...") self.startStopScoutScanButton.setEnabled(False) self.plusRemoteLogic.reconstructRecorded(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.lastScoutRecordingOutputFilename, self.outputSpacing, self.onScoutVolumeReconstructed, self.SCOUT_VOLUME_FILENAME, self.SCOUT_VOLUME_NODE_NAME) def onRequestVolumeReconstructionSnapshot(self, stopFlag = ""): self.plusRemoteLogic.getVolumeReconstructionSnapshot(self.connectorNode.GetID(), self.volumeReconstructorIDSelector.currentText, self.LIVE_VOLUME_FILENAME, self.LIVE_VOLUME_NODE_NAME, self.APPLY_HOLE_FILLING_FOR_SNAPSHOT, self.onSnapshotAcquired) def executeCommandDelayed(self, method, delay=100): # Order of OpenIGTLink message receiving and processing is not guaranteed to be the same # therefore we wait a bit to make sure the image message is processed as well QTimer.singleShot(delay, method) def printCommandResponse(self, command, q): statusText = "Command {0} [{1}]: {2}\n".format(command.GetCommandName(), command.GetID(), command.StatusToString(command.GetStatus())) if command.GetResponseMessage(): statusText = statusText + command.GetResponseMessage() elif command.GetResponseText(): statusText = statusText + command.GetResponseText() logging.debug(statusText) def onGetCaptureDeviceCommandResponseReceived(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() != command.CommandSuccess: return captureDeviceIdsListString = command.GetResponseMessage() if captureDeviceIdsListString: captureDevicesIdsList = captureDeviceIdsListString.split(",") else: captureDevicesIdsList = [] for i in range(0,len(captureDevicesIdsList)): if self.captureIDSelector.findText(captureDevicesIdsList[i]) == -1: self.captureIDSelector.addItem(captureDevicesIdsList[i]) def onGetVolumeReconstructorDeviceCommandResponseReceived(self, command, q): self.printCommandResponse(command, q) if command.GetStatus() != command.CommandSuccess: return volumeReconstructorDeviceIdsListString = command.GetResponseMessage() if volumeReconstructorDeviceIdsListString: volumeReconstructorDeviceIdsList = volumeReconstructorDeviceIdsListString.split(",") else: volumeReconstructorDeviceIdsList = [] self.volumeReconstructorIDSelector.clear() self.volumeReconstructorIDSelector.addItems(volumeReconstructorDeviceIdsList) self.startStopRecordingButton.setEnabled(True) self.offlineReconstructButton.setEnabled(True) self.startStopScoutScanButton.setEnabled(True) if self.roiNode: self.startStopLiveReconstructionButton.setEnabled(True) def onVolumeRecorded(self, command, q): self.printCommandResponse(command, q) self.offlineReconstructButton.setEnabled(True) volumeToReconstructFileName = os.path.basename(command.GetResponseMessage()) self.offlineVolumeToReconstructSelector.insertItem(0,volumeToReconstructFileName) self.offlineVolumeToReconstructSelector.setCurrentIndex(0) def onScoutVolumeRecorded(self, command, q): self.printCommandResponse(command,q) self.offlineReconstructButton.setEnabled(True) if command.GetStatus() == command.CommandExpired: logging.fatal("Scout Volume Recording: Timeout while waiting for volume reconstruction result") return if command.GetStatus() == command.CommandSuccess: self.lastScoutRecordingOutputFilename = os.path.basename(command.GetResponseMessage()) self.onScoutScanReconstVolume() def onVolumeReconstructed(self, command, q): self.printCommandResponse(command,q) self.offlineReconstructButton.setIcon(self.recordIcon) self.offlineReconstructButton.setText("Offline Reconstruction") self.offlineReconstructButton.setEnabled(True) self.offlineReconstructButton.setChecked(False) if command.GetStatus() == command.CommandExpired: # volume reconstruction command timed out logging.fatal("Volume Reconstruction: Timeout while waiting for volume reconstruction result") return if command.GetStatus() != command.CommandSuccess: logging.debug("Volume Reconstruction: " + command.GetResponseMessage()) return self.executeCommandDelayed(self.onVolumeReconstructedFinalize) def onVolumeReconstructedFinalize(self): applicationLogic = slicer.app.applicationLogic() applicationLogic.FitSliceToAll() self.guideletParent.showVolumeRendering(self.getOfflineVolumeRecNode()) def onScoutVolumeReconstructed(self, command, q): self.printCommandResponse(command,q) if command.GetStatus() == command.CommandExpired: logging.fatal("Scout Volume Reconstruction: Timeout while waiting for scout volume reconstruction result") return self.startStopScoutScanButton.setIcon(self.recordIcon) self.startStopScoutScanButton.setText(" Scout Scan\n Start Recording") self.startStopScoutScanButton.setEnabled(True) if command.GetStatus() != command.CommandSuccess: logging.debug("Scout Volume Reconstruction: " + command.GetResponseMessage()) return self.executeCommandDelayed(self.onScoutVolumeReconstructedFinalize) def onScoutVolumeReconstructedFinalize(self): # Create and initialize ROI after scout scan because low resolution scout scan is used to set # a smaller ROI for the live high resolution reconstruction self.roiNode = self.logic.onRoiInitialization(self.SCOUT_VOLUME_NODE_NAME, self.roiNode) self.roiOrigin, self.roiExtent = self.logic.updateVolumeOriginAndExtentFromROI(self.LIVE_OUTPUT_VOLUME_SPACING, self.roiNode) scoutScanVolumeNode = self.getScoutVolumeNode() applicationLogic = slicer.app.applicationLogic() applicationLogic.FitSliceToAll() self.guideletParent.showVolumeRendering(scoutScanVolumeNode) def onSnapshotAcquired(self, command, q): self.printCommandResponse(command,q) if not self.startStopLiveReconstructionButton.isChecked(): # live volume reconstruction is not active return self.executeCommandDelayed(self.onSnapshotAcquiredFinalize) def onSnapshotAcquiredFinalize(self): self.guideletParent.showVolumeRendering(self.getLiveVolumeRecNode()) self.snapshotTimer.start(self.SNAPSHOT_INTERVAL*1000) def onVolumeLiveReconstructed(self, command, q): self.printCommandResponse(command,q) if command.GetStatus() == command.CommandExpired: logging.fatal("LIVE Volume Reconstruction: Failed to stop volume reconstruction") return if command.GetStatus() != command.CommandSuccess: logging.debug("LIVE Volume Reconstruction " + command.GetResponseMessage()) return self.executeCommandDelayed(self.getLiveVolumeRecNode) def onVolumeLiveReconstructedFinalize(self): self.guideletParent.showVolumeRendering(self.getLiveVolumeRecNode())
class QTReactor(posixbase.PosixReactorBase): """Qt based reactor.""" _crashCall = None _timer = None def __init__(self, app=None): self.running = 0 posixbase.PosixReactorBase.__init__(self) if app is None: app = QApplication([]) self.qApp = app self.addSystemEventTrigger('after', 'shutdown', self.cleanup) def addReader(self, reader): if not hasReader(reader): reads[reader] = TwistedSocketNotifier(self, reader, QSocketNotifier.Read) def addWriter(self, writer): if not hasWriter(writer): writes[writer] = TwistedSocketNotifier(self, writer, QSocketNotifier.Write) def removeReader(self, reader): if hasReader(reader): reads[reader].shutdown() del reads[reader] def removeWriter(self, writer): if hasWriter(writer): writes[writer].shutdown() del writes[writer] def removeAll(self): return self._removeAll(reads, writes) def simulate(self): if self._timer is not None: self._timer.stop() self._timer = None if not self.running: self.running = 1 self.qApp.exit_loop() return self.runUntilCurrent() if self._crashCall is not None: self._crashCall.reset(0) timeout = self.timeout() if timeout is None: timeout = 1.0 timeout = min(timeout, 0.1) * 1010 if self._timer is None: self._timer = QTimer() QObject.connect(self._timer, SIGNAL("timeout()"), self.simulate) self._timer.start(timeout, 1) def cleanup(self): if self._timer is not None: self._timer.stop() self._timer = None def iterate(self, delay=0.0): log.msg(channel='system', event='iteration', reactor=self) self._crashCall = self.callLater(delay, self.crash) self.run() def run(self, installSignalHandlers=1): self.running = 1 self.startRunning(installSignalHandlers=installSignalHandlers) self.simulate() self.qApp.enter_loop() def crash(self): if self._crashCall is not None: if self._crashCall.active(): self._crashCall.cancel() self._crashCall = None self.running = 0
class qSlicerMultiVolumeExplorerSimplifiedModuleWidget: def __init__(self, parent=None): logging.debug( "qSlicerMultiVolumeExplorerSimplifiedModuleWidget:init() called") if not parent or not hasattr(parent, "layout"): self.parent = slicer.qMRMLWidget() self.parent.setLayout(QVBoxLayout()) else: self.parent = parent self.layout = self.parent.layout() self._bgMultiVolumeNode = None self._fgMultiVolumeNode = None self.styleObserverTags = [] self.sliceWidgetsPerStyle = {} self.chartPopupWindow = None self.chartPopupSize = QSize(600, 300) self.chartPopupPosition = QPoint(0, 0) def hide(self): self.widget.hide() def show(self): self.widget.show() def setup(self): self.widget = QWidget() layout = QGridLayout() self.widget.setLayout(layout) self.layout.addWidget(self.widget) self.widget.show() self.layout = layout self.setupInputFrame() self.setupFrameControlFrame() self.setupAdditionalFrames() self.setupPlottingFrame() self.setFramesEnabled(False) self.timer = QTimer() self.timer.setInterval(50) self.setupConnections() # initialize slice observers (from DataProbe.py) # keep list of pairs: [observee,tag] so they can be removed easily self.styleObserverTags = [] # keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic self.sliceWidgetsPerStyle = {} self.refreshObservers() def setupInputFrame(self, parent=None): if not parent: parent = self.layout self.bgMultiVolumeSelector = slicer.qMRMLNodeComboBox() self.bgMultiVolumeSelector.nodeTypes = ['vtkMRMLMultiVolumeNode'] self.bgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene) self.bgMultiVolumeSelector.addEnabled = 0 self._bgMultiVolumeSelectorLabel = QLabel('Input multivolume') inputFrameWidget = QWidget() self.inputFrameLayout = QFormLayout() inputFrameWidget.setLayout(self.inputFrameLayout) self.inputFrameLayout.addRow(self._bgMultiVolumeSelectorLabel, self.bgMultiVolumeSelector) parent.addWidget(inputFrameWidget) def setupFrameControlFrame(self): # TODO: initialize the slider based on the contents of the labels array self.frameSlider = ctk.ctkSliderWidget() self.frameSlider.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) self.frameLabel = QLabel('Current frame number') self.playButton = QPushButton('Play') self.playButton.toolTip = 'Iterate over multivolume frames' self.playButton.checkable = True frameControlHBox = QHBoxLayout() frameControlHBox.addWidget(self.frameLabel) frameControlHBox.addWidget(self.frameSlider) frameControlHBox.addWidget(self.playButton) self.inputFrameLayout.addRow(frameControlHBox) def setupAdditionalFrames(self): pass def setupPlottingFrame(self, parent=None): if not parent: parent = self.layout self.plottingFrameWidget = QWidget() self.plottingFrameLayout = QGridLayout() self.plottingFrameWidget.setLayout(self.plottingFrameLayout) self._multiVolumeIntensityChart = MultiVolumeIntensityChartView() self.popupChartButton = QPushButton("Undock chart") self.popupChartButton.setCheckable(True) self.plottingFrameLayout.addWidget( self._multiVolumeIntensityChart.chartView) self.plottingFrameLayout.addWidget(self.popupChartButton) parent.addWidget(self.plottingFrameWidget) def setupConnections(self): self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVCMRMLSceneChanged) self.bgMultiVolumeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onBackgroundInputChanged) self.playButton.connect('toggled(bool)', self.onPlayButtonToggled) self.frameSlider.connect('valueChanged(double)', self.onSliderChanged) self.timer.connect('timeout()', self.goToNext) self.popupChartButton.connect('toggled(bool)', self.onDockChartViewToggled) def onDockChartViewToggled(self, checked): if checked: self.chartPopupWindow = QDialog() self.chartPopupWindow.setWindowFlags( PythonQt.QtCore.Qt.WindowStaysOnTopHint) layout = QGridLayout() self.chartPopupWindow.setLayout(layout) layout.addWidget(self._multiVolumeIntensityChart.chartView) layout.addWidget(self.popupChartButton) self.chartPopupWindow.finished.connect(self.dockChartView) self.chartPopupWindow.resize(self.chartPopupSize) self.chartPopupWindow.move(self.chartPopupPosition) self.chartPopupWindow.show() self.popupChartButton.setText("Dock chart") self._multiVolumeIntensityChart.chartView.show() else: self.chartPopupWindow.close() def dockChartView(self): self.chartPopupSize = self.chartPopupWindow.size self.chartPopupPosition = self.chartPopupWindow.pos self.plottingFrameLayout.addWidget( self._multiVolumeIntensityChart.chartView) self.plottingFrameLayout.addWidget(self.popupChartButton) self.popupChartButton.setText("Undock chart") self.popupChartButton.disconnect('toggled(bool)', self.onDockChartViewToggled) self.popupChartButton.checked = False self.popupChartButton.connect('toggled(bool)', self.onDockChartViewToggled) def onSliderChanged(self, frameId): if self._bgMultiVolumeNode is None: return newValue = int(frameId) self.setCurrentFrameNumber(newValue) def onVCMRMLSceneChanged(self, mrmlScene): logging.debug( "qSlicerMultiVolumeExplorerSimplifiedModuleWidget:onVCMRMLSceneChanged" ) self.bgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene) self.onBackgroundInputChanged() def refreshGUIForNewBackgroundImage(self): self._multiVolumeIntensityChart.reset() self.setFramesEnabled(True) if self._fgMultiVolumeNode and self._bgMultiVolumeNode: Helper.SetBgFgVolumes(self._bgMultiVolumeNode.GetID(), self._fgMultiVolumeNode.GetID()) else: Helper.SetBgVolume(self._bgMultiVolumeNode.GetID()) self.refreshFrameSlider() self._multiVolumeIntensityChart.bgMultiVolumeNode = self._bgMultiVolumeNode self.refreshObservers() def getBackgroundMultiVolumeNode(self): return self.bgMultiVolumeSelector.currentNode() def onBackgroundInputChanged(self): self._bgMultiVolumeNode = self.getBackgroundMultiVolumeNode() if self._bgMultiVolumeNode is not None: self.refreshGUIForNewBackgroundImage() else: self.setFramesEnabled(False) def onPlayButtonToggled(self, checked): if self._bgMultiVolumeNode is None: return if checked: self.timer.start() self.playButton.text = 'Stop' else: self.timer.stop() self.playButton.text = 'Play' def processEvent(self, observee, event): # logging.debug("processing event %s" % event) if self._bgMultiVolumeNode is None: return # TODO: use a timer to delay calculation and compress events if event == 'LeaveEvent': # reset all the readouts # TODO: reset the label text return if not self.sliceWidgetsPerStyle.has_key(observee): return interactor = observee.GetInteractor() self.createChart(self.sliceWidgetsPerStyle[observee], interactor.GetEventPosition()) def createChart(self, sliceWidget, position): self._multiVolumeIntensityChart.createChart(sliceWidget, position) def setCurrentFrameNumber(self, frameNumber): mvDisplayNode = self._bgMultiVolumeNode.GetDisplayNode() mvDisplayNode.SetFrameComponent(frameNumber) def setFramesEnabled(self, enabled): pass def refreshObservers(self): """ When the layout changes, drop the observers from all the old widgets and create new observers for the newly created widgets""" self.removeObservers() # get new slice nodes layoutManager = slicer.app.layoutManager() sliceNodeCount = slicer.mrmlScene.GetNumberOfNodesByClass( 'vtkMRMLSliceNode') for nodeIndex in xrange(sliceNodeCount): # find the widget for each node in scene sliceNode = slicer.mrmlScene.GetNthNodeByClass( nodeIndex, 'vtkMRMLSliceNode') sliceWidget = layoutManager.sliceWidget(sliceNode.GetLayoutName()) if sliceWidget: # add observers and keep track of tags style = sliceWidget.sliceView().interactorStyle() self.sliceWidgetsPerStyle[style] = sliceWidget events = ("MouseMoveEvent", "EnterEvent", "LeaveEvent") for event in events: tag = style.AddObserver(event, self.processEvent) self.styleObserverTags.append([style, tag]) def removeObservers(self): for observee, tag in self.styleObserverTags: observee.RemoveObserver(tag) self.styleObserverTags = [] self.sliceWidgetsPerStyle = {} def refreshFrameSlider(self): self.frameSlider.minimum = 0 if not self._bgMultiVolumeNode: self.frameSlider.maximum = 0 return nFrames = self._bgMultiVolumeNode.GetNumberOfFrames() self.frameSlider.maximum = nFrames - 1 def goToNext(self): currentElement = self.frameSlider.value currentElement += 1 if currentElement > self.frameSlider.maximum: currentElement = 0 self.frameSlider.value = currentElement
class KTVMainWindow(KParts.MainWindow): """Implements the main KatchTV application window.""" def __init__(self, title): """Initialises a new window object.""" self._stopped = True KParts.MainWindow.__init__(self, None, str(title)) self.setCaption(config.appFullVersion) self._initWidgets() self.__mediaManager = Media.Manager() self.__downloadTimer = QTimer() self.__downloadTimer.connect(self.__downloadTimer,SIGNAL(str(u"timeout()")), self.__updateDownloads) self.browser.goToURL(u'katchtv:welcome:') def saveAll(self): self.__mediaManager._saveItems() def __updateDownloads(self): self.__mediaManager.beginNewDownloads() def enableThreads(self): # start everything, and mark as running self.__downloadTimer.start(config.updateDownloadsTimerMillisecs) self.bmarksList.enableThreads() self._stopped = False def disableThreads(self): # stop in the order of slowest to fastest, hoping it'll # all finish around the same time self.bmarksList.disableThreads() self.__mediaManager.stop() self.__downloadTimer.stop() self._stopped = True def getMediaManager(self): return self.__mediaManager def isStopped(self): """Returns True if the application should not run yet (ie, if it has not been fully initialised).""" return self._stopped def _initWidgets(self): """Initialises all of the main widgets in the window.""" global appRoot appIconPath = os.path.join(appRoot, "images/miniicon.png") self.setIcon(QPixmap(appIconPath)) self.mainBox = QHBox(self) self.mainSplitter = QSplitter(self.mainBox) self.bmarksListBox = QVBox(self.mainSplitter) self.bmarksListBox.setMaximumWidth(250) self.bmarksList = KTVBookmarksListView.KTVBookmarksListView(self.bmarksListBox, self) QObject.connect(self.bmarksList, SIGNAL(str(u'doubleClicked(QListViewItem *)')), self._bookmarkChosen) self.browserBox = QVBox(self.mainSplitter) self.browser = KTVHTMLPart.KTVHTMLPart(self.browserBox, self) self.setCentralWidget(self.mainBox) self._buttonBox = QHBox(self.bmarksListBox) self._addButton = QPushButton(u"&Add", self._buttonBox, str(u"")) QObject.connect(self._addButton, SIGNAL(str(u'clicked()')), self._addItem) self._deleteButton = QPushButton(u"&Delete", self._buttonBox, str(u"")) QObject.connect(self._deleteButton, SIGNAL(str(u'clicked()')), self._deleteItem) self._backButton = QPushButton(u"&Back", self.bmarksListBox, str(u"")) QObject.connect(self._backButton, SIGNAL(str(u'clicked()')), self._back) self._helpButton = QPushButton(u"&Help", self.bmarksListBox, str(u"")) QObject.connect(self._helpButton, SIGNAL(str(u'clicked()')), self._help) self.statusBar().message(u"KatchTV is now ready for use.") def _help(self): """A hook (a Qt signal slot, actually) which is called when the user clicks the "Help" button. Loads the manual into the browser.""" self.browser.goToURL(u'katchtv:help:') def _back(self): """A hook (a Qt signal slot) which is called when the user clicks the "Back" button. Navigates one step back through the browser history.""" self.browser.loadPreviousPage() def _addItem(self): """A hook (Qt signal slot) which is called when the user clicks the "Add" button. Presents a dialog, asking the user for the feed URI to add.""" validURI = False firstTry = True while not validURI: if firstTry: uri, confirmed = KInputDialog.text(u"Add Feed Bookmark", QString(u"Please enter the channel's feed URI (or URL) here.")) uri = unicode(uri) else: uri, confirmed = KInputDialog.text(u"Add Feed Bookmark", u"The URI you entered was invalid. Please try again, or cancel.", QString(uri)) uri = unicode(uri) firstTry = False if confirmed: validURI = utils.isAFeed(uri) else: # user cancelled the input return feed = Feed.FeedCache.getFeedFromURINoLock(uri) self.bmarksList.addChannel(feed) def _deleteItem(self): """A hook (Qt signal slot) which is called when the user clicks the Delete button. Deletes the selected item, if that item is a subscribed channel. Otherwise, informs the user that they cannot delete the item.""" self.bmarksList.delCurrentItem() def _bookmarkChosen(self, item): """A hook (Qt signal slot) which is called when the user double-clicks on an item in the listview. Checks if the item has a URI column entry, and if so, navigates to it.""" title = item.text(KTVBookmarksListView.COL_NAME) uri = item.text(KTVBookmarksListView.COL_URI) if title != u'' and uri != u'': self.browser.goToURL(uri) def getBookmarksList(self): return self.bmarksList