def cleanup(): logger.debug("cleaning up loaded services") Services.removeAll() logger.debug("cleaning up loaded plugins") for v in ("last_traceback", "last_type", "last_value"): if hasattr(sys, v): del sys.__dict__[v] #PluginManager.singleton().unloadAll() logger.debug("cleaning up complete")
def test_smoke(): # most of this is already tested in testGraph Services.addService("Profiling", None) mockup = FilterMockup( "pyfile://" + os.path.dirname(__file__) + "/../interface/SimpleDynamicFilter.py", "SimpleDynInFilter", PropertyCollectionImpl("mockup", None), None) mockup.createFilterAndUpdate() mockup.addDynamicPort("dynin", InputPortInterface) res = mockup.createFilter()
def setupConsoleServices(config): """ Adds services available in console mode. :param config: a nexxT.core.Configuration instance :return: None """ Services.addService("Logging", ConsoleLogger()) Services.addService("PlaybackControl", PlaybackControlConsole(config)) Services.addService("RecordingControl", MVCRecordingControlBase(config)) Services.addService("Configuration", MVCConfigurationBase(config)) Services.addService("Profiling", ProfilingService())
def activeAppStateChange(self, newState): """ Called when the active application changes its state. :param newState: the new application's state (see FilterState) :return: """ assertMainThread() if newState == FilterState.CONSTRUCTED: self.actActivate.setEnabled(True) else: self.actActivate.setEnabled(False) if newState == FilterState.ACTIVE: if self._waitForOpenState is not None: app, pbfile, startPlay = self._waitForOpenState self._waitForOpenState = None if app == Application.activeApplication.getApplication( ).getName(): pbsrv = Services.getService("PlaybackControl") if startPlay: pbsrv.playbackPaused.connect(self._singleShotPlay) QTimer.singleShot(2000, self._disconnectSingleShotPlay) MethodInvoker(pbsrv.browser.setActive, Qt.QueuedConnection, pbfile) self.actDeactivate.setEnabled(True) self.actSaveWithGuiState.setEnabled(False) else: self.actDeactivate.setEnabled(False) self.actSaveWithGuiState.setEnabled(True)
def __init__(self, name): """ Creates a NexTThread instance with a name. If this is not the main thread, create a corresponding QThread and start it (i.e., the event loop). :param name: name of the thread """ super().__init__() self._filters = {} self._filter2name = {} self._mockups = {} self._name = name try: self._profsrv = Services.getService("Profiling") if hasattr(self._profsrv, "data") and self._profsrv.data() is None: self._profsrv = None except KeyError: self._profsrv = None if not self.thread() is QCoreApplication.instance().thread(): raise NexTInternalError("unexpected thread") if name == "main": self._qthread = QCoreApplication.instance().thread() self._qthread.setObjectName(name) else: self._qthread = self.ThreadWithCoverage(parent=self) self._qthread.setObjectName(name) self._qthread.start() self.moveToThread(self._qthread) self.cleanUpCalled = False
def _execTreeViewContextMenu(self, point): index = self.treeView.indexAt(point) item = self.model.data(index, ITEM_ROLE) if isinstance(item, ConfigurationModel.SubConfigContent): m = QMenu() a1 = QAction("Edit graph") m.addAction(a1) a1.triggered.connect(lambda: self._addGraphView(item.subConfig)) if self.model.isApplication(index): a2 = QAction("Select Application") a2.triggered.connect(lambda: self.changeActiveApp( self.model.data(index, Qt.DisplayRole))) a3 = QAction("Init Application") a3.triggered.connect(lambda: self._changeActiveAppAndInit( self.model.data(index, Qt.DisplayRole))) m.addActions([a2, a3]) pbsrv = Services.getService("PlaybackControl") m2 = m.addMenu("Init and load sequence") m3 = m.addMenu("Init, load and play") s1 = [] s2 = [] for a in pbsrv.recentSeqs: assert isinstance(a, QAction) if a.isVisible(): # pylint: disable=cell-var-from-loop # the below statements are tested and work aseq = QAction(a.text()) aseq.triggered.connect(lambda arg1=a.data( ), seq=a.data(): self._changeActiveAppInitAndLoad( self.model.data(index, Qt.DisplayRole), seq, False) ) s1.append(aseq) aseq = QAction(a.text()) aseq.triggered.connect(lambda arg1=a.data( ), seq=a.data(): self._changeActiveAppInitAndLoad( self.model.data(index, Qt.DisplayRole), seq, True)) # pylint: enable=cell-var-from-loop s2.append(aseq) m2.addActions(s1) m3.addActions(s2) m.exec_(self.treeView.mapToGlobal(point)) return if self.model.isSubConfigParent( index) == Configuration.CONFIG_TYPE_APPLICATION: m = QMenu() a = QAction("Add application") m.addAction(a) a = m.exec_(self.treeView.mapToGlobal(point)) if a is not None: self._configuration.addNewApplication() return if self.model.isSubConfigParent( index) == Configuration.CONFIG_TYPE_COMPOSITE: m = QMenu() a = QAction("Add composite filter") m.addAction(a) a = m.exec_(self.treeView.mapToGlobal(point)) if a is not None: self._configuration.addNewCompositeFilter() return
def _addGraphView(self, subConfig): g = subConfig.getGraph() # remove already deleted graph views from internal list valid_graphViews = [] for gv in self._graphViews: if shiboken2.isValid(gv): # pylint: disable=no-member valid_graphViews.append(gv) self._graphViews = valid_graphViews # check if graph view is already there for gv in self._graphViews: if gv.widget().scene().graph == g: logger.info("Graph view already exists.") return # create new graph view srv = Services.getService("MainWindow") graphDw = srv.newDockWidget("Graph (%s)" % (subConfig.getName()), parent=None, defaultArea=Qt.RightDockWidgetArea, allowedArea=Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea) graphDw.setAttribute(Qt.WA_DeleteOnClose, True) assert isinstance(graphDw, QDockWidget) graphView = GraphEditorView(graphDw) graphView.setScene(GraphScene(subConfig.getGraph(), graphDw)) graphDw.setWidget(graphView) self._graphViews.append(graphDw) graphDw.visibleChanged.connect(self._removeGraphViewFromList)
def __init__(self): super().__init__() srv = Services.getService("MainWindow") profMenu = srv.menuBar().addMenu("Pr&ofiling") self.loadDockWidget = srv.newDockWidget("Load", None, Qt.BottomDockWidgetArea) self.loadDisplay = LoadDisplayWidget(self.loadDockWidget) self.loadDockWidget.setWidget(self.loadDisplay) self.loadDataUpdated.connect(self.loadDisplay.newLoadData) self.threadDeregistered.connect(self.loadDisplay.removeThread) self.spanDockWidget = srv.newDockWidget("Profiling", None, Qt.BottomDockWidgetArea) self.spanDisplay = SpanDisplayWidget(self.spanDockWidget) self.spanDockWidget.setWidget(self.spanDisplay) self.spanDataUpdated.connect(self.spanDisplay.newSpanData) self.threadDeregistered.connect(self.spanDisplay.removeThread) self.actLoadEnabled = QAction("Enable Load Monitor") self.actLoadEnabled.setCheckable(True) self.actLoadEnabled.setChecked(True) self.actLoadEnabled.toggled.connect(self.setLoadMonitorEnabled) self.actProfEnabled = QAction("Enable Port Profiling") self.actProfEnabled.setCheckable(True) self.actProfEnabled.setChecked(False) self.actProfEnabled.toggled.connect(self.setPortProfilingEnabled) self.setLoadMonitorEnabled(True) self.setPortProfilingEnabled(False) profMenu.addAction(self.actLoadEnabled) profMenu.addAction(self.actProfEnabled)
def onClose(self): """ overloaded from Filter :return: """ srv = Services.getService("PlaybackControl") srv.removeConnections(self)
def onStop(self): """ De-registers itself from the recording control service :return: """ srv = Services.getService("RecordingControl") srv.removeConnections(self)
def _disconnectSingleShotPlay(self): assertMainThread() pbsrv = Services.getService("PlaybackControl") try: pbsrv.playbackPaused.disconnect(self._singleShotPlay) except RuntimeError: # we are already disconnected. pass
def _dirtyChanged(self, dirty): srv = Services.getService("MainWindow") if self.cfgfile is None: title = "nexxT: <unnamed>" else: title = "nexxT: " + self.cfgfile if dirty: title += " *" srv.setWindowTitle(title)
def __init__(self): super().__init__() srv = Services.getService("MainWindow") self.dockWidget = srv.newDockWidget( "Log", parent=None, defaultArea=Qt.BottomDockWidgetArea, allowedArea=Qt.LeftDockWidgetArea | Qt.BottomDockWidgetArea) self.logWidget = LogView() self.dockWidget.setWidget(self.logWidget) logMenu = srv.menuBar().addMenu("&Log") mainLogger = logging.getLogger() self.handler = LogHandler(self.logWidget) mainLogger.addHandler(self.handler) self.logWidget.destroyed.connect( lambda: mainLogger.removeHandler(self.handler)) self.actFollow = QAction("Follow") self.actFollow.setCheckable(True) self.actFollow.setChecked(True) self.actClear = QAction("Clear") self.actSingleLine = QAction("Single Line") self.actSingleLine.setCheckable(True) self.actSingleLine.setChecked(True) self.logWidget.setUniformRowHeights(True) self.actFollow.toggled.connect(self.logWidget.setFollow) self.actClear.triggered.connect(self.logWidget.clear) self.actSingleLine.toggled.connect(self.logWidget.setUniformRowHeights) self.actDisable = QAction("Disable") self.actDisable.triggered.connect(self.setLogLevel) self.actGroup = QActionGroup(self) self.actGroup.setExclusive(True) levelno = mainLogger.level self.loglevelMap = {} for lv in ["INTERNAL", "DEBUG", "INFO", "WARNING", "ERROR"]: a = QAction(lv[:1] + lv[1:].lower()) a.setCheckable(True) loglevel = getattr(logging, lv) self.loglevelMap[a] = loglevel setattr(self, "setLogLevel_" + lv, self.setLogLevel) a.triggered.connect(getattr(self, "setLogLevel_" + lv)) self.actGroup.addAction(a) if levelno == loglevel: a.setChecked(True) else: a.setChecked(False) logMenu.addAction(a) self.loglevelMap[self.actDisable] = 100 logMenu.addAction(self.actDisable) logMenu.addSeparator() logMenu.addAction(self.actClear) logMenu.addAction(self.actFollow) logMenu.addAction(self.actSingleLine)
def onOpen(self): """ overloaded from Filter :return: """ srv = Services.getService("PlaybackControl") srv.setupConnections(self, ["*.h5", "*.hdf5", "*.hdf"]) if isMainThread(): logger.warning("Hdf5Reader seems to run in GUI thread. Consider to move it to a seperate thread.")
def onClose(self): """ Inverse of onOpen :return: """ mw = Services.getService("MainWindow") # de-register the subplot mw.releaseSubplot(self._widget) # delete the widget reference self._widget = None
def onStart(self): """ Registers itself to the recording control service :return: """ self._propertyChanged(self.propertyCollection(), "buffer_samples") srv = Services.getService("RecordingControl") srv.setupConnections(self) if isMainThread(): logger.warning("Hdf5Writer seems to run in GUI thread. Consider to move it to a seperate thread.")
def onOpen(self): """ Now we can create the widget. :return: """ pc = self.propertyCollection() # get the main window service, used for registering the "subplot" in a QMDISubWindow instance mw = Services.getService("MainWindow") # create the widget self._widget = DisplayWidget() # register the subplot in the main window mw.subplot(pc.getProperty("caption"), self, self._widget) # inform the display widget about the current scale self._widget.setScale(pc.getProperty("scale"))
def exception_setup(python, thread, where, activeTime_s): logging.getLogger(__name__).info("------------------------------------------------------") logging.getLogger(__name__).info("Starting exception_setup %d %s %s %f", python, thread, where, activeTime_s) from nexxT.services.ConsoleLogger import ConsoleLogger logger = ConsoleLogger() Services.addService("Logging", logger) class LogCollector(logging.StreamHandler): def __init__(self): super().__init__() self.logs = [] def emit(self, record): self.logs.append(record) # avoid warning flood about service profiling not found Services.addService("Profiling", None) collector = LogCollector() logging.getLogger().addHandler(collector) try: t = QTimer() t.setSingleShot(True) # timeout if test case hangs t2 = QTimer() t2.start((activeTime_s + 3)*1000) try: test_json = Path(__file__).parent / "test_except_constr.json" with test_json.open("r", encoding='utf-8') as fp: cfg = json.load(fp) if nexxT.useCImpl and not python: cfg["composite_filters"][0]["nodes"][2]["library"] = "binary://../binary/${NEXXT_PLATFORM}/${NEXXT_VARIANT}/test_plugins" cfg["composite_filters"][0]["nodes"][2]["thread"] = thread cfg["composite_filters"][0]["nodes"][2]["properties"]["whereToThrow"] = where mod_json = Path(__file__).parent / "test_except_constr_tmp.json" with mod_json.open("w", encoding="utf-8") as fp: json.dump(cfg, fp) config = Configuration() ConfigFileLoader.load(config, mod_json) config.activate("testApp") app.processEvents() aa = Application.activeApplication init = True def timeout(): nonlocal init if init: init = False aa.stop() aa.close() aa.deinit() else: app.exit(0) def timeout2(): print("Application timeout hit!") nonlocal init if init: init = False aa.stop() aa.close() aa.deinit() else: print("application exit!") app.exit(1) t2.timeout.connect(timeout2) t.timeout.connect(timeout) def state_changed(state): if state == FilterState.ACTIVE: t.setSingleShot(True) t.start(activeTime_s*1000) elif not init and state == FilterState.CONSTRUCTED: t.start(1000) aa.stateChanged.connect(state_changed) aa.init() aa.open() aa.start() app.exec_() finally: del t del t2 finally: logging.getLogger().removeHandler(collector) Services.removeAll() return collector.logs
def __init__(self, config): assertMainThread() super().__init__(config) # state self._directory = str(Path('.').absolute()) # gui srv = Services.getService("MainWindow") config.configLoaded.connect(self._restoreState) config.configAboutToSave.connect(self._saveState) self._config = config recMenu = srv.menuBar().addMenu("&Recording") style = QApplication.style() self.actStart = QAction( QIcon.fromTheme("media-record", QIcon(":icons/media-record.svg")), "Start Recording", self) self.actStop = QAction( QIcon.fromTheme("media-playback-stop", style.standardIcon(QStyle.SP_MediaStop)), "Stop Recording", self) self.actSetDir = QAction( QIcon.fromTheme("document-open-folder", style.standardIcon(QStyle.SP_DirIcon)), "Choose directory ...", self) self.actStart.setEnabled(False) self.actStop.setEnabled(False) self.actSetDir.setEnabled(False) self.actStart.triggered.connect(self._startTriggered) self.actStop.triggered.connect(self._stopTriggered) self.actSetDir.triggered.connect(self._setDir) recMenu.addAction(self.actStart) recMenu.addAction(self.actStop) recMenu.addAction(self.actSetDir) self.dockWidget = srv.newDockWidget("RecordingControl", None, Qt.LeftDockWidgetArea, defaultLoc="PlaybackControl") self.dockWidgetContents = QWidget(self.dockWidget) self.dockWidget.setWidget(self.dockWidgetContents) toolLayout = QBoxLayout(QBoxLayout.TopToBottom, self.dockWidgetContents) toolLayout.setContentsMargins(0, 0, 0, 0) toolBar = QToolBar() toolLayout.addWidget(toolBar) toolBar.addAction(self.actStart) toolBar.addAction(self.actStop) toolBar.addAction(self.actSetDir) self._directoryLabel = ElidedLabel(self._directory, parent=self.dockWidgetContents) to = self._directoryLabel.textOption() to.setWrapMode(QTextOption.NoWrap) self._directoryLabel.setTextOption(to) self._directoryLabel.setElideMode(Qt.ElideMiddle) self._statusLabel = ElidedLabel("(disabled)", parent=self.dockWidgetContents) to = self._statusLabel.textOption() to.setWrapMode(QTextOption.NoWrap) self._statusLabel.setTextOption(to) self._statusLabel.setElideMode(Qt.ElideMiddle) toolLayout.addWidget(self._directoryLabel) toolLayout.addWidget(self._statusLabel, stretch=100) #toolLayout.addStretch(100) self.statusUpdate.connect(self._onUpdateStatus) self.notifyError.connect(self._onNotifyError)
def __init__(self, configuration): super().__init__(configuration) assertMainThread() srv = Services.getService("MainWindow") srv.aboutToClose.connect(self._aboutToClose) confMenu = srv.menuBar().addMenu("&Configuration") toolBar = srv.getToolBar() configuration.configNameChanged.connect(self._configNameChanged) configuration.dirtyChanged.connect(self._dirtyChanged) style = QApplication.style() self.actLoad = QAction( QIcon.fromTheme("document-open", style.standardIcon(QStyle.SP_DialogOpenButton)), "Open config", self) self.actLoad.triggered.connect(self._execLoad) self.actSave = QAction( QIcon.fromTheme("document-save", style.standardIcon(QStyle.SP_DialogSaveButton)), "Save config", self) self.actSave.triggered.connect(self._execSaveConfig) self.actSaveWithGuiState = QAction( QIcon.fromTheme("document-save", style.standardIcon(QStyle.SP_DialogSaveButton)), "Save config sync gui state", self) self.actSaveWithGuiState.triggered.connect( self._execSaveConfigWithGuiState) self.actNew = QAction( QIcon.fromTheme("document-new", style.standardIcon(QStyle.SP_FileIcon)), "New config", self) self.actNew.triggered.connect(self._execNew) self.actActivate = QAction( QIcon.fromTheme("arrow-up", style.standardIcon(QStyle.SP_ArrowUp)), "Initialize", self) self.actActivate.triggered.connect(self.activate) self.actDeactivate = QAction( QIcon.fromTheme("arrow-down", style.standardIcon(QStyle.SP_ArrowDown)), "Deinitialize", self) self.actDeactivate.triggered.connect(self.deactivate) confMenu.addAction(self.actLoad) confMenu.addAction(self.actSave) confMenu.addAction(self.actSaveWithGuiState) confMenu.addAction(self.actNew) confMenu.addAction(self.actActivate) confMenu.addAction(self.actDeactivate) toolBar.addAction(self.actLoad) toolBar.addAction(self.actSave) toolBar.addAction(self.actNew) toolBar.addAction(self.actActivate) toolBar.addAction(self.actDeactivate) self.recentConfigs = [QAction() for i in range(10)] self.recentConfigs[0].setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R)) confMenu.addSeparator() recentMenu = confMenu.addMenu("Recent") for a in self.recentConfigs: a.setVisible(False) a.triggered.connect(self._openRecent) recentMenu.addAction(a) self.mainWidget = srv.newDockWidget("Configuration", None, Qt.LeftDockWidgetArea) self.treeView = QTreeView(self.mainWidget) self.treeView.setHeaderHidden(False) self.treeView.setSelectionMode(QAbstractItemView.NoSelection) self.treeView.setEditTriggers(self.treeView.EditKeyPressed | self.treeView.AnyKeyPressed) self.treeView.setAllColumnsShowFocus(True) self.treeView.setExpandsOnDoubleClick(False) self.treeView.setDragEnabled(True) self.treeView.setDropIndicatorShown(True) self.treeView.setDragDropMode(QAbstractItemView.DragOnly) self.mainWidget.setWidget(self.treeView) self.treeView.setModel(self.model) self.treeView.header().setStretchLastSection(True) self.treeView.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.treeView.doubleClicked.connect(self._onItemDoubleClicked) self.treeView.setContextMenuPolicy(Qt.CustomContextMenu) self.treeView.customContextMenuRequested.connect( self._execTreeViewContextMenu) # expand applications by default self.treeView.setExpanded(self.model.index(1, 0), True) self.delegate = PropertyDelegate(self.model, ITEM_ROLE, ConfigurationModel.PropertyContent, self) self.treeView.setItemDelegate(self.delegate) self.restoreState() srv.aboutToClose.connect(self.saveState) # a list of dock widgets displaying subgraphs self._graphViews = [] # make sure that the graph views are closed when the config is closed self._configuration.subConfigRemoved.connect(self._subConfigRemoved) self._waitForActivated = None self._waitForOpenState = None
def startNexT(cfgfile, active, execScripts, execCode, withGui): """ Starts next with the given config file and activates the given application. :param cfgfile: path to config file :param active: active application (if None, the first application in the config will be used) :return: None """ logger.debug("Starting nexxT...") config = Configuration() lcl = QLocale.system() lcl.setNumberOptions(QLocale.c().numberOptions()) QLocale.setDefault(lcl) if withGui: app = QApplication() if QApplication.instance() is None else QApplication.instance() app.setWindowIcon(QIcon(":icons/nexxT.svg")) app.setOrganizationName("nexxT") app.setApplicationName("nexxT") setupGuiServices(config) else: app = QCoreApplication() if QCoreApplication.instance() is None else QCoreApplication.instance() app.setOrganizationName("nexxT") app.setApplicationName("nexxT") setupConsoleServices(config) if cfgfile is not None: ConfigFileLoader.load(config, cfgfile) if withGui: mainWindow = Services.getService("MainWindow") mainWindow.restoreState() mainWindow.show() # the reference will still be held by the service, but here we don't need it anymore del mainWindow if active is not None: config.activate(active) # pylint: disable=unused-variable # need to hold the reference of this until the method is called i2 = MethodInvoker(dict(object=Application, method="initialize", thread=app.thread()), MethodInvoker.IDLE_TASK) # pylint: disable=unused-variable waitForSignal(config.appActivated) if Application.activeApplication.getState() != FilterState.ACTIVE: waitForSignal(Application.activeApplication.stateChanged, lambda s: s == FilterState.ACTIVE) logger.info("done") def cleanup(): logger.debug("cleaning up loaded services") Services.removeAll() logger.debug("cleaning up loaded plugins") for v in ("last_traceback", "last_type", "last_value"): if hasattr(sys, v): del sys.__dict__[v] #PluginManager.singleton().unloadAll() logger.debug("cleaning up complete") code_globals = {} for c in execCode: logger.info("Executing code '%s'", c) # note that exec is used intentionally here to provide the user with scripting posibilities exec(compile(c, "<string>", 'exec'), code_globals) # pylint: disable=exec-used logger.debug("Executing code done") for s in execScripts: logger.info("Executing script '%s'", s) with open(s) as fscript: # note that exec is used intentionally here to provide the user with scripting possibilities exec(compile(fscript.read(), s, 'exec'), code_globals) # pylint: disable=exec-used logger.debug("Executing script done") res = app.exec_() logger.debug("closing config") config.close() cleanup() logger.internal("app.exec_ returned") return res
def setupGuiServices(config): """ Adds services available in console mode. :param config: a nexxT.core.Configuration instance :return: None """ mainWindow = MainWindow(config) Services.addService("MainWindow", mainWindow) Services.addService("Logging", GuiLogger()) Services.addService("PlaybackControl", MVCPlaybackControlGUI(config)) Services.addService("RecordingControl", MVCRecordingControlGUI(config)) Services.addService("Configuration", MVCConfigurationGUI(config)) Services.addService("Profiling", Profiling())
def _singleShotPlay(self): assertMainThread() pbsrv = Services.getService("PlaybackControl") MethodInvoker(pbsrv.startPlayback, Qt.QueuedConnection) self._disconnectSingleShotPlay()
def onClose(self): mw = Services.getService("MainWindow") mw.releaseSubplot(self.label) self.label = None
def __init__(self, config): assertMainThread() super().__init__(config) # state self.preventSeek = False self.beginTime = None self.timeRatio = 1.0 # gui srv = Services.getService("MainWindow") config.configLoaded.connect(self.restoreState) config.configAboutToSave.connect(self.saveState) self.config = config playbackMenu = srv.menuBar().addMenu("&Playback") style = QApplication.style() self.actStart = QAction(QIcon.fromTheme("media-playback-start", style.standardIcon(QStyle.SP_MediaPlay)), "Start Playback", self) self.actPause = QAction(QIcon.fromTheme("media-playback-pause", style.standardIcon(QStyle.SP_MediaPause)), "Pause Playback", self) self.actPause.setEnabled(False) self.actStepFwd = QAction(QIcon.fromTheme("media-seek-forward", style.standardIcon(QStyle.SP_MediaSeekForward)), "Step Forward", self) self.actStepBwd = QAction(QIcon.fromTheme("media-seek-backward", style.standardIcon(QStyle.SP_MediaSeekBackward)), "Step Backward", self) self.actSeekEnd = QAction(QIcon.fromTheme("media-skip-forward", style.standardIcon(QStyle.SP_MediaSkipForward)), "Seek End", self) self.actSeekBegin = QAction(QIcon.fromTheme("media-skip-backward", style.standardIcon(QStyle.SP_MediaSkipBackward)), "Seek Begin", self) self.actSetTimeFactor = {r : QAction("x 1/%d" % (1/r), self) if r < 1 else QAction("x %d" % r, self) for r in (1/8, 1/4, 1/2, 1, 2, 4, 8)} # pylint: disable=unnecessary-lambda # let's stay on the safe side and do not use emit as a slot... self.actStart.triggered.connect(lambda: self._startPlayback.emit()) self.actPause.triggered.connect(lambda: self._pausePlayback.emit()) self.actStepFwd.triggered.connect(lambda: self._stepForward.emit(self.selectedStream())) self.actStepBwd.triggered.connect(lambda: self._stepBackward.emit(self.selectedStream())) self.actSeekEnd.triggered.connect(lambda: self._seekEnd.emit()) self.actSeekBegin.triggered.connect(lambda: self._seekBeginning.emit()) # pylint: enable=unnecessary-lambda def setTimeFactor(newFactor): logger.debug("new time factor %f", newFactor) self._setTimeFactor.emit(newFactor) for r in self.actSetTimeFactor: logger.debug("adding action for time factor %f", r) self.actSetTimeFactor[r].triggered.connect(functools.partial(setTimeFactor, r)) self.dockWidget = srv.newDockWidget("PlaybackControl", None, Qt.LeftDockWidgetArea) self.dockWidgetContents = QWidget(self.dockWidget) self.dockWidget.setWidget(self.dockWidgetContents) toolLayout = QBoxLayout(QBoxLayout.TopToBottom, self.dockWidgetContents) toolLayout.setContentsMargins(0, 0, 0, 0) toolBar = QToolBar() toolLayout.addWidget(toolBar) toolBar.addAction(self.actSeekBegin) toolBar.addAction(self.actStepBwd) toolBar.addAction(self.actStart) toolBar.addAction(self.actPause) toolBar.addAction(self.actStepFwd) toolBar.addAction(self.actSeekEnd) playbackMenu.addAction(self.actSeekBegin) playbackMenu.addAction(self.actStepBwd) playbackMenu.addAction(self.actStart) playbackMenu.addAction(self.actPause) playbackMenu.addAction(self.actStepFwd) playbackMenu.addAction(self.actSeekEnd) playbackMenu.addSeparator() for r in self.actSetTimeFactor: playbackMenu.addAction(self.actSetTimeFactor[r]) self.timeRatioLabel = QLabel("x 1") self.timeRatioLabel.addActions(list(self.actSetTimeFactor.values())) self.timeRatioLabel.setContextMenuPolicy(Qt.ActionsContextMenu) toolBar.addSeparator() toolBar.addWidget(self.timeRatioLabel) contentsLayout = QGridLayout() toolLayout.addLayout(contentsLayout, 10) # now we add a position view self.positionSlider = QSlider(Qt.Horizontal, self.dockWidgetContents) self.beginLabel = QLabel(parent=self.dockWidgetContents) self.beginLabel.setAlignment(Qt.AlignLeft|Qt.AlignCenter) self.currentLabel = QLabel(parent=self.dockWidgetContents) self.currentLabel.setAlignment(Qt.AlignHCenter|Qt.AlignCenter) self.endLabel = QLabel(parent=self.dockWidgetContents) self.endLabel.setAlignment(Qt.AlignRight|Qt.AlignCenter) contentsLayout.addWidget(self.beginLabel, 0, 0, alignment=Qt.AlignLeft) contentsLayout.addWidget(self.currentLabel, 0, 1, alignment=Qt.AlignHCenter) contentsLayout.addWidget(self.endLabel, 0, 2, alignment=Qt.AlignRight) contentsLayout.addWidget(self.positionSlider, 1, 0, 1, 3) self.positionSlider.setTracking(False) self.positionSlider.valueChanged.connect(self.onSliderValueChanged, Qt.DirectConnection) self.positionSlider.sliderMoved.connect(self.displayPosition) # file browser self.browser = BrowserWidget(self.dockWidget) self.nameFiltersChanged.connect(self._onNameFiltersChanged, Qt.QueuedConnection) contentsLayout.addWidget(self.browser, 3, 0, 1, 3) contentsLayout.setRowStretch(3, 100) self.browser.activated.connect(self.browserActivated) self.actShowAllFiles = QAction("Show all files") self.actShowAllFiles.setCheckable(True) self.actShowAllFiles.setChecked(False) self.actShowAllFiles.toggled.connect(self._onShowAllFiles) playbackMenu.addSeparator() playbackMenu.addAction(self.actShowAllFiles) self.actGroupStream = QActionGroup(self) self.actGroupStream.setExclusionPolicy(QActionGroup.ExclusionPolicy.ExclusiveOptional) playbackMenu.addSeparator() self.actGroupStreamMenu = playbackMenu.addMenu("Step Stream") self._selectedStream = None self.recentSeqs = [QAction() for i in range(10)] playbackMenu.addSeparator() recentMenu = playbackMenu.addMenu("Recent") for a in self.recentSeqs: a.setVisible(False) a.triggered.connect(self.openRecent) recentMenu.addAction(a) self._supportedFeaturesChanged(set(), set())
def onStop(self): ctrlSrv = Services.getService("PlaybackControl") ctrlSrv.removeConnections(self) self._closeVideo()
def onStart(self): ctrlSrv = Services.getService("PlaybackControl") ctrlSrv.setupConnections(self) self.playbackPaused.emit() if self.filename != "": self._openVideo()
def execute_0(): """ Creates a new application with an app and a composite filter and saves it to a file; finally activate the created app. :return: """ logger.info("execute_0:begin") cfg = Services.getService("Configuration") # create a new configuration with a composite graph and an application execute_0.i = MethodInvoker(cfg.newConfig, Qt.QueuedConnection, "basicworkflow.json") waitForSignal(cfg.configuration().configNameChanged) # create simple composite filter cfg.configuration().renameComposite( cfg.configuration().addNewCompositeFilter(), "composite") comp = cfg.configuration().compositeFilterByName("composite") node = comp.getGraph().addNode(library="pyfile://./SimpleStaticFilter.py", factoryFunction="SimpleStaticFilter") idx = _getIndex(cfg.model, ["composite", "composite", node, "sleep_time"]) cfg.model.setData(idx.siblingAtColumn(1), 0.01, Qt.EditRole) execute_0.i = MethodInvoker(comp.getGraph().addDynamicInputPort, Qt.QueuedConnection, "CompositeOutput", "out") waitForSignal(comp.getGraph().dynInputPortAdded) execute_0.i = MethodInvoker(comp.getGraph().addDynamicOutputPort, Qt.QueuedConnection, "CompositeInput", "in") waitForSignal(comp.getGraph().dynOutputPortAdded) comp.getGraph().addConnection("CompositeInput", "in", node, "inPort") comp.getGraph().addConnection(node, "outPort", "CompositeOutput", "out") # create simple application (live/recorder) cfg.configuration().renameApp(cfg.configuration().addNewApplication(), "myApp") app = cfg.configuration().applicationByName("myApp") import nexxT if nexxT.useCImpl: src = app.getGraph().addNode( library="entry_point://tests.nexxT.CSimpleSource", factoryFunction="entry_point") else: src = app.getGraph().addNode( library="pyfile://./SimpleStaticFilter.py", factoryFunction="SimpleSource") src2 = app.getGraph().addNode(library="pyfile://./SimpleStaticFilter.py", factoryFunction="SimpleSource") idx = _getIndex(cfg.model, ["apps", "myApp", src, "frequency"]) cfg.model.setData(idx.siblingAtColumn(1), 10.0, Qt.EditRole) idx = _getIndex(cfg.model, ["apps", "myApp", src2, "frequency"]) cfg.model.setData(idx.siblingAtColumn(1), 2.0, Qt.EditRole) idx = _getIndex(cfg.model, ["apps", "myApp", src2, "log_tr"]) cfg.model.setData(idx.siblingAtColumn(1), False, Qt.EditRole) flt = app.getGraph().addNode(library=comp, factoryFunction="compositeNode") app.getGraph().addConnection(src, "outPort", flt, "in") # add a recorder rec = app.getGraph().addNode(library="pymod://nexxT.filters.hdf5", factoryFunction="Hdf5Writer") execute_0.i = MethodInvoker(app.getGraph().addDynamicInputPort, Qt.QueuedConnection, rec, "stream1") waitForSignal(app.getGraph().dynInputPortAdded) execute_0.i = MethodInvoker(app.getGraph().addDynamicInputPort, Qt.QueuedConnection, rec, "stream2") waitForSignal(app.getGraph().dynInputPortAdded) app.getGraph().addConnection(src, "outPort", rec, "stream1") app.getGraph().addConnection(src2, "outPort", rec, "stream2") # assign threads app.getGraph().getMockup(src).propertyCollection().getChildCollection( "_nexxT").setProperty("thread", "source-thread") app.getGraph().getMockup(src2).propertyCollection().getChildCollection( "_nexxT").setProperty("thread", "source2-thread") app.getGraph().getMockup(rec).propertyCollection().getChildCollection( "_nexxT").setProperty("thread", "rec-thread") # create another application (playback) # hdf5 reader cfg.configuration().renameApp(cfg.configuration().addNewApplication(), "pbApp") app = cfg.configuration().applicationByName("pbApp") pb = app.getGraph().addNode(library="pymod://nexxT.filters.hdf5", factoryFunction="Hdf5Reader", suggestedName="player") assert pb == "player" execute_0.i = MethodInvoker(app.getGraph().addDynamicOutputPort, Qt.QueuedConnection, pb, "stream1") waitForSignal(app.getGraph().dynOutputPortAdded) execute_0.i = MethodInvoker(app.getGraph().addDynamicOutputPort, Qt.QueuedConnection, pb, "stream2") waitForSignal(app.getGraph().dynOutputPortAdded) # 2 filters flt1 = app.getGraph().addNode(library="pyfile://./SimpleStaticFilter.py", factoryFunction="SimpleStaticFilter", suggestedName="flt1") assert flt1 == "flt1" idx = _getIndex(cfg.model, ["apps", "pbApp", "flt1", "sleep_time"]) cfg.model.setData(idx.siblingAtColumn(1), 0.01, Qt.EditRole) idx = _getIndex(cfg.model, ["apps", "pbApp", "flt1", "log_rcv"]) cfg.model.setData(idx.siblingAtColumn(1), True, Qt.EditRole) idx = _getIndex(cfg.model, ["apps", "pbApp", "flt1", "log_prefix"]) cfg.model.setData(idx.siblingAtColumn(1), "(flt1) ", Qt.EditRole) flt2 = app.getGraph().addNode(library="pyfile://./SimpleStaticFilter.py", factoryFunction="SimpleStaticFilter", suggestedName="flt2") assert flt2 == "flt2" idx = _getIndex(cfg.model, ["apps", "pbApp", "flt2", "sleep_time"]) cfg.model.setData(idx.siblingAtColumn(1), 0.01, Qt.EditRole) idx = _getIndex(cfg.model, ["apps", "pbApp", "flt2", "log_rcv"]) cfg.model.setData(idx.siblingAtColumn(1), True, Qt.EditRole) idx = _getIndex(cfg.model, ["apps", "pbApp", "flt2", "log_prefix"]) cfg.model.setData(idx.siblingAtColumn(1), "(flt2) ", Qt.EditRole) app.getGraph().addConnection("player", "stream1", "flt1", "inPort") app.getGraph().addConnection("player", "stream2", "flt2", "inPort") # save application execute_0.i = MethodInvoker(cfg.saveConfig, Qt.QueuedConnection) waitForSignal(cfg.configuration().configNameChanged) # change active app execute_1.i = MethodInvoker(cfg.changeActiveApp, Qt.QueuedConnection, "myApp") waitForSignal(cfg.configuration().appActivated) # activate execute_1.i = MethodInvoker(cfg.activate, Qt.QueuedConnection) waitForSignal(cfg.configuration().appActivated) if app.activeApplication.getState() != FilterState.ACTIVE: waitForSignal(app.activeApplication.stateChanged, lambda s: s == FilterState.ACTIVE) logger.info("execute_0:end")
def execute_2(): logger.info("execute_2:begin") cfg = Services.getService("Configuration") pbc = Services.getService("PlaybackControl") app = cfg.configuration().applicationByName("pbApp") logger.info("app activated") execute_2.i = MethodInvoker(pbc.setSequence, Qt.QueuedConnection, glob.glob("./*.h5")[0]) _, tbegin, tend, _ = waitForSignal(pbc.sequenceOpened) execute_2.i = MethodInvoker(pbc.startPlayback, Qt.QueuedConnection) waitForSignal(pbc.playbackStarted) waitForSignal(pbc.playbackPaused) logger.info("played") execute_2.i = MethodInvoker(pbc.seekBeginning, Qt.QueuedConnection) waitForSignal(pbc.currentTimestampChanged) logger.info("seekBeginning") for i in range(10): execute_2.i = MethodInvoker(pbc.stepForward, Qt.QueuedConnection, None) waitForSignal(pbc.playbackPaused) logger.info("stepForward[None]") for i in range(10): execute_2.i = MethodInvoker(pbc.stepForward, Qt.QueuedConnection, "stream1") waitForSignal(pbc.playbackPaused) logger.info("stepForward[stream1]") for i in range(2): execute_2.i = MethodInvoker(pbc.stepForward, Qt.QueuedConnection, "stream2") waitForSignal(pbc.playbackPaused) logger.info("stepForward[stream2]") execute_2.i = MethodInvoker(pbc.seekTime, Qt.QueuedConnection, (tbegin + tend) // 2) waitForSignal(pbc.currentTimestampChanged) logger.info("seekTime") execute_2.i = MethodInvoker(pbc.seekEnd, Qt.QueuedConnection) waitForSignal(pbc.currentTimestampChanged) logger.info("seekEnd") for i in range(10): execute_2.i = MethodInvoker(pbc.stepBackward, Qt.QueuedConnection, None) waitForSignal(pbc.playbackPaused) logger.info("stepBackward[None]") execute_2.i = MethodInvoker(pbc.seekTime, Qt.QueuedConnection, tbegin - 1000000000) waitForSignal(pbc.currentTimestampChanged) logger.info("seekTimeBegin") execute_2.i = MethodInvoker(pbc.seekTime, Qt.QueuedConnection, tend + 1000000000) waitForSignal(pbc.currentTimestampChanged) logger.info("seekTimeEnd") execute_2.i = MethodInvoker(QCoreApplication.quit, Qt.QueuedConnection) logger.info("execute_2:end")
def execute_1(): """ after 3 seconds, deactivate and re-activate the app after 3 seconds, re-open and re-activate the app after 3 more seconds, quit :return: """ logger.info("execute_1:begin") cfg = Services.getService("Configuration") rc = Services.getService("RecordingControl") logger.info("app activated") app = cfg.configuration().applicationByName("myApp") t = QTimer() t.setSingleShot(True) t.setInterval(3000) t.start() waitForSignal(t.timeout) execute_1.i = MethodInvoker(cfg.deactivate, Qt.QueuedConnection) waitForSignal(app.activeApplication.stateChanged, lambda s: s == FilterState.CONSTRUCTED) logger.info("app deactivated") execute_1.i = MethodInvoker(cfg.activate, Qt.QueuedConnection) waitForSignal(cfg.configuration().appActivated) if app.activeApplication.getState() != FilterState.ACTIVE: waitForSignal(app.activeApplication.stateChanged, lambda s: s == FilterState.ACTIVE) execute_1.i = MethodInvoker(rc.startRecording, Qt.QueuedConnection, ".") logger.info("app activated") t = QTimer() t.setSingleShot(True) t.setInterval(3000) t.start() waitForSignal(t.timeout) execute_1.i = MethodInvoker(cfg.deactivate, Qt.QueuedConnection) waitForSignal(app.activeApplication.stateChanged, lambda s: s == FilterState.CONSTRUCTED) logger.info("app deactivated") # re-open this application execute_1.i = MethodInvoker(cfg.loadConfig, Qt.QueuedConnection, "basicworkflow.json") waitForSignal(cfg.configuration().configNameChanged) logger.info("config loaded") # activate execute_1.i = MethodInvoker(cfg.changeActiveApp, Qt.QueuedConnection, "myApp") waitForSignal(cfg.configuration().appActivated) execute_1.i = MethodInvoker(cfg.activate, Qt.QueuedConnection) waitForSignal(cfg.configuration().appActivated) if app.activeApplication.getState() != FilterState.ACTIVE: waitForSignal(app.activeApplication.stateChanged, lambda s: s == FilterState.ACTIVE) logger.info("app activated") t = QTimer() t.setSingleShot(True) t.setInterval(3000) t.start() waitForSignal(t.timeout) execute_1.i = MethodInvoker(QCoreApplication.quit, Qt.QueuedConnection) logger.info("execute_1:end")