def createWidgets(self): """ QtWidgets creation _______________________ | | | PyEditor | |_______________________| |________QSplitter______| | | | PyEditor | |_______________________| """ self.srcWidget = EditorWidget( self.TEST_DEF_EDITOR, "Test Definition:", self, wrappingText=QtHelper.str2bool( Settings.instance().readValue(key='Editor/code-wrapping'))) self.execWidget = EditorWidget( self.TEST_EXEC_EDITOR, "Test Execution:", self, wrappingText=QtHelper.str2bool( Settings.instance().readValue(key='Editor/code-wrapping')), toolbar=False) self.srcEditor = self.srcWidget.editor self.execEditor = self.execWidget.editor layout = QVBoxLayout() hSplitter = QSplitter(self) hSplitter.setOrientation(Qt.Vertical) hSplitter.addWidget(self.srcWidget) hSplitter.addWidget(self.execWidget) hSplitter.setContentsMargins(0, 0, 0, 0) hSplitter.setStretchFactor(0, 1) layout.addWidget(hSplitter) layout.setContentsMargins(2, 0, 0, 0) self.setLayout(layout)
class VolumeEditorWidget(QWidget): def __init__( self, volumeeditor, parent=None ): super(VolumeEditorWidget, self).__init__(parent=parent) self._ve = volumeeditor self.setFocusPolicy(Qt.StrongFocus) # setup quadview self.quadview = QuadView(self) self.quadview.addWidget(0, self._ve.imageViews[2]) self.quadview.addWidget(1, self._ve.imageViews[0]) self.quadview.addWidget(2, self._ve.imageViews[1]) #3d overview #self.overview = OverviewScene(self, self._ve._shape[1:4]) #self.quadview.addWidget(3, self.overview) self.quadview.addWidget(3, QWidget(self)) #FIXME: resurrect #self.overview.changedSlice.connect(self.changeSlice) #self._ve.changedSlice.connect(self.overview.ChangeSlice) # layout viewingLayout = QVBoxLayout() viewingLayout.setContentsMargins(10,2,0,2) viewingLayout.setSpacing(0) viewingLayout.addWidget(self.quadview) self.quadview.setContentsMargins(0,0,10,0) # Label below views labelLayout = QHBoxLayout() labelLayout.setMargin(0) labelLayout.setSpacing(5) labelLayout.setContentsMargins(0,0,0,0) self.posLabel = QLabel() self.pixelValuesLabel = QLabel() labelLayout.addWidget(self.posLabel) labelLayout.addWidget(self.pixelValuesLabel) labelLayout.addStretch() viewingLayout.addLayout(labelLayout) # Right side toolbox self._toolBox = QWidget() self._toolBox.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self._toolBoxLayout = QVBoxLayout() self._toolBoxLayout.setMargin(5) self._toolBox.setLayout(self._toolBoxLayout) self._toolBoxLayout.addStretch() # Toggle slice intersection marks self.indicateSliceIntersectionButton = QToolButton() self.indicateSliceIntersectionButton.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.indicateSliceIntersectionButton.setText("Indicate Current Position") self.indicateSliceIntersectionButton.setCheckable(True) self.indicateSliceIntersectionButton.setChecked(True) self._toolBoxLayout.addWidget(self.indicateSliceIntersectionButton) # Channel Selector QComboBox in right side tool box self._channelSpin = QSpinBox() self._channelSpin.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self._channelSpin.setEnabled(True) channelLayout = QHBoxLayout() channelLayout.addWidget(self._channelSpin) self._channelSpinLabel = QLabel("Channel:") self._toolBoxLayout.addWidget(self._channelSpinLabel) self._toolBoxLayout.addLayout(channelLayout) #time selector self._timeSpin = QSpinBox() self._timeSpin.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self._timeSpin.setEnabled(True) timeLayout = QHBoxLayout() timeLayout.addWidget(self._timeSpin) self._timeSpinLabel = QLabel("Time:") self._toolBoxLayout.addWidget(self._timeSpinLabel) self._toolBoxLayout.addLayout(timeLayout) self._toolBoxLayout.setAlignment(Qt.AlignTop) self._channelSpin.setRange(0,self._ve._shape[-1] - 1) self._timeSpin.setRange(0,self._ve._shape[0] - 1) def setChannel(c): print "set channel = %d, posModel has channel = %d" % (c, self._ve.posModel.channel) if c == self._ve.posModel.channel: return self._ve.posModel.channel = c self._channelSpin.valueChanged.connect(setChannel) def getChannel(newC): self._channelSpin.setValue(newC) self._ve.posModel.channelChanged.connect(getChannel) def setTime(t): print "set channel = %d, posModel has time = %d" % (t, self._ve.posModel.time) if t == self._ve.posModel.time: return self._ve.posModel.time = t self._timeSpin.valueChanged.connect(setTime) def getTime(newT): self._timeSpin.setValue(newT) self._ve.posModel.timeChanged.connect(getTime) # setup the layout for display self.splitter = QSplitter() self.splitter.setContentsMargins(0,0,0,0) tempWidget = QWidget() tempWidget.setLayout(viewingLayout) self.splitter.addWidget(tempWidget) self.splitter.addWidget(self._toolBox) splitterLayout = QVBoxLayout() splitterLayout.setMargin(0) splitterLayout.setSpacing(0) splitterLayout.addWidget(self.splitter) self.setLayout(splitterLayout) # drawing axisLabels = ["X:", "Y:", "Z:"] for i, v in enumerate(self._ve.imageViews): v.hud = SliceSelectorHud() #connect interpreter v.hud.sliceSelector.valueChanged.connect(partial(self._ve.navInterpret.changeSliceAbsolute, axis=i)) #hud v.hud.bgColor = self._ve.navCtrl.axisColors[i] #FIXME v.hud.label = axisLabels[i] v.hud.minimum = 0 v.hud.maximum = self._ve.posModel.volumeExtent(i) def toggleSliceIntersection(state): self._ve.navCtrl.indicateSliceIntersection = state self.indicateSliceIntersectionButton.toggled.connect(toggleSliceIntersection) #Enabling this makes cursor movement too slow... #self._ve.posModel.cursorPositionChanged.connect(self._updateInfoLabels) # shortcuts self._initShortcuts() self.updateGeometry() self.update() self.quadview.update() def _shortcutHelper(self, keySequence, group, description, parent, function, context = None, enabled = None): shortcut = QShortcut(QKeySequence(keySequence), parent, member=function, ambiguousMember=function) if context != None: shortcut.setContext(context) if enabled != None: shortcut.setEnabled(True) return shortcut, group, description def _initShortcuts(self): self.shortcuts = [] self.shortcuts.append(self._shortcutHelper("Ctrl+Z", "Labeling", "History undo", self, self._ve.historyUndo, Qt.ApplicationShortcut, True)) self.shortcuts.append(self._shortcutHelper("Ctrl+Shift+Z", "Labeling", "History redo", self, self._ve.historyRedo, Qt.ApplicationShortcut, True)) self.shortcuts.append(self._shortcutHelper("Ctrl+Y", "Labeling", "History redo", self, self._ve.historyRedo, Qt.ApplicationShortcut, True)) self.shortcuts.append(self._shortcutHelper("l", "Labeling", "Go to next label (cyclic, forward)", self, self._ve.nextLabel)) self.shortcuts.append(self._shortcutHelper("k", "Labeling", "Go to previous label (cyclic, backwards)", self, self._ve.prevLabel)) def fullscreenView(axis): m = not self.quadview.maximized print "maximize axis=%d = %r" % (axis, m) self.quadview.setMaximized(m, axis) maximizeShortcuts = ['x', 'y', 'z'] maximizeViews = [1, 2, 0] for i, v in enumerate(self._ve.imageViews): self.shortcuts.append(self._shortcutHelper(maximizeShortcuts[i], "Navigation", \ "Enlarge slice view %s to full size" % maximizeShortcuts[i], \ self, partial(fullscreenView, maximizeViews[i]), Qt.WidgetShortcut)) #self.shortcuts.append(self._shortcutHelper("n", "Labeling", "Increase brush size", v,self._ve._drawManager.brushSmaller, Qt.WidgetShortcut)) #self.shortcuts.append(self._shortcutHelper("m", "Labeling", "Decrease brush size", v, self._ve._drawManager.brushBigger, Qt.WidgetShortcut)) self.shortcuts.append(self._shortcutHelper("+", "Navigation", "Zoom in", v, v.zoomIn, Qt.WidgetShortcut)) self.shortcuts.append(self._shortcutHelper("-", "Navigation", "Zoom out", v, v.zoomOut, Qt.WidgetShortcut)) self.shortcuts.append(self._shortcutHelper("q", "Navigation", "Switch to next channel", v, self._ve.nextChannel, Qt.WidgetShortcut)) self.shortcuts.append(self._shortcutHelper("a", "Navigation", "Switch to previous channel", v, self._ve.previousChannel, Qt.WidgetShortcut)) def sliceDelta(axis, delta): newPos = copy.copy(self._ve.posModel.slicingPos) newPos[axis] += delta self._ve.posModel.slicingPos = newPos self.shortcuts.append(self._shortcutHelper("p", "Navigation", "Slice up", v, partial(sliceDelta, i, 1), Qt.WidgetShortcut)) self.shortcuts.append(self._shortcutHelper("o", "Navigation", "Slice down", v, partial(sliceDelta, i, -1), Qt.WidgetShortcut)) self.shortcuts.append(self._shortcutHelper("Ctrl+Up", "Navigation", "Slice up", v, partial(sliceDelta, i, 1), Qt.WidgetShortcut)) self.shortcuts.append(self._shortcutHelper("Ctrl+Down", "Navigation", "Slice down", v, partial(sliceDelta, i, -1), Qt.WidgetShortcut)) self.shortcuts.append(self._shortcutHelper("Ctrl+Shift+Up", "Navigation", "10 slices up", v, partial(sliceDelta, i, 10), Qt.WidgetShortcut)) self.shortcuts.append(self._shortcutHelper("Ctrl+Shift+Down", "Navigation", "10 slices down", v, partial(sliceDelta, i, -10), Qt.WidgetShortcut)) def _updateInfoLabels(self, pos): if any((pos[i] < 0 or pos[i] >= self._ve.posModel.shape[i] for i in xrange(3))): self._ve.posLabel.setText("") return self.posLabel.setText("<b>x:</b> %03i <b>y:</b> %03i <b>z:</b> %03i" % (pos[0], pos[1], pos[2]))
class WWorkspace(QWidget): """ Workspace widget """ WORKSPACE = 0 UpdateWindowTitle = pyqtSignal(str) RecentFile = pyqtSignal(dict) BusyCursor = pyqtSignal() ArrowCursor = pyqtSignal() def __init__(self, parent=None): """ Constructs WWorkspace widget Signals emited: * updateWindowTitle @param parent: @type parent: """ QWidget.__init__(self, parent) self.parent = parent self.type = self.WORKSPACE self.name = self.tr('Workspace') # create each part WRepositories.initialize(parent=self) WDocumentViewer.initialize(parent=self, iRepo=WRepositories.instance(), lRepo=WRepositories.LocalRepository, rRepo=WRepositories.RemoteRepository) WDocumentProperties.initialize(parent=self, iRepo=WRepositories.instance(), lRepo=WRepositories.LocalRepository, rRepo=WRepositories.RemoteRepository) WHelper.initialize(parent=self) # splitter state self.splitterState = None self.splitterHelperState = None # create widget self.createWidgets() self.createActions() self.creationConnections() def createWidgets(self): """ QtWidgets creation _________ _______________________ _________ / \__________ | | / \__ | | Q | | Q | | | WRepositories | S | | S | | | | p | | p | | |_____________________| l | | l | | _____QSplitter i | WDocumentViewer | i | WHelper | / \__________ t | | t | | | | t | | t | | | WDocumentProperties | e | | e | | | | r | | r | | |_____________________| |_______________________| |_____________| """ self.wCursorPosition = WCursorPosition(self) self.parent.addWidgetToStatusBar(self.wCursorPosition) WDocumentProperties.instance().setDisabled(True) layout = QHBoxLayout(self) # properties | viewer | helper self.vSplitter = QSplitter(self) if not QtHelper.str2bool( Settings.instance().readValue(key='View/tab-left')): self.hSplitter = QSplitter(self) self.hSplitter.setOrientation(Qt.Vertical) self.hSplitter.addWidget(WRepositories.instance()) self.hSplitter.addWidget(WDocumentProperties.instance()) self.hSplitter.setContentsMargins(0, 0, 0, 0) self.vSplitter.addWidget(self.hSplitter) else: WRepositories.instance().hideWidgetsHeader() WDocumentProperties.instance().hideWidgetsHeader() self.leftTab = QTabWidget(self) self.leftTab.addTab(WRepositories.instance(), QIcon(":/folders.png"), self.tr("Repositories")) self.leftTab.addTab(WDocumentProperties.instance(), QIcon(":/controls.png"), self.tr("Test Properties")) self.vSplitter.addWidget(self.leftTab) self.vSplitter.addWidget(WDocumentViewer.instance()) self.vSplitter.setStretchFactor(1, 1) layout.addWidget(self.vSplitter) self.hSplitter2 = QSplitter(self) self.hSplitter2.setOrientation(Qt.Vertical) self.vSplitter.addWidget(self.hSplitter2) self.hSplitter2.addWidget(WHelper.instance()) self.setLayout(layout) def creationConnections(self): """ QtSignals connection: * WRepositories <=> WDocumentViewer.newTab * WDocumentViewer <=> cursorPositionChanged * WDocumentViewer <=> focusChanged """ WRepositories.instance().local().OpenFile.connect( WDocumentViewer.instance().newTab) WDocumentViewer.instance().CursorPositionChanged.connect( self.cursorPositionChanged) WDocumentViewer.instance().TotalLinesChanged.connect( self.totalLinesChanged) WDocumentViewer.instance().FocusChanged.connect(self.focusChanged) WDocumentViewer.instance().BusyCursor.connect(self.emitBusy) WDocumentViewer.instance().ArrowCursor.connect(self.emitIdle) WDocumentViewer.instance().CurrentDocumentChanged.connect( self.currentDocumentChanged) WDocumentViewer.instance().DocumentOpened.connect(self.documentOpened) WDocumentViewer.instance().UpdateWindowTitle.connect( self.updateWindowTitle) WDocumentViewer.instance().DocumentViewerEmpty.connect( self.documentViewerEmpty) # from testplan when the test selection changed in the tree WDocumentViewer.instance().PropertiesChanged.connect( self.propertiesChanged) if WRepositories.instance().localConfigured != "Undefined": if RCI.instance().isAuthenticated(): WDocumentViewer.instance().RefreshLocalRepository.connect( WRepositories.instance().localRepository.refreshAll) WDocumentProperties.instance().RefreshLocalRepository.connect( WRepositories.instance().localRepository.refreshAll) WDocumentViewer.instance().RecentFile.connect(self.recentFileUpdated) WHelper.instance().ShowAssistant.connect(self.onEnterAssistant) WHelper.instance().HideAssistant.connect(self.onLeaveAssistant) # new in v16 WDocumentViewer.instance().ShowPropertiesTab.connect( self.onShowPropertiesTab) def onShowPropertiesTab(self): """ On show properties tabulation """ if QtHelper.str2bool( Settings.instance().readValue(key='View/tab-left')): self.leftTab.setCurrentIndex(TAB_PROPERTIES) def onEnterAssistant(self): """ On mouse enter in the online helper """ pass def onLeaveAssistant(self): """ On mouse leave in the online helper """ pass def createActions(self): """ Create qt actions """ self.hideDeveloperModeAction = QtHelper.createAction( self, self.tr("Developer"), self.hideDeveloperMode, checkable=True, icon=QIcon(":/window-fit.png"), shortcut=Settings.instance().readValue( key='KeyboardShorcuts/developer'), tip=self.tr('Fit the document viewer to maximize the editor area')) WDocumentViewer.instance().addActionToolbar( action=self.hideDeveloperModeAction) def emitBusy(self): """ Emit busy """ self.BusyCursor.emit() def emitIdle(self): """ Emit idle """ self.ArrowCursor.emit() def hideDeveloperMode(self): """ Hide developer mode """ if not self.hideDeveloperModeAction.isChecked(): Settings.instance().setValue(key='View/developer', value='False') self.deactiveDeveloperView() else: Settings.instance().setValue(key='View/developer', value='True') self.activeDeveloperView() def activeDeveloperView(self): """ Activate developer view """ self.splitterState = self.vSplitter.saveState() self.vSplitter.setSizes([0, self.vSplitter.sizes()[1], 0]) def deactiveDeveloperView(self): """ Deactive developer view """ if self.splitterState is not None: self.vSplitter.restoreState(self.splitterState) def mainSplitterMoved(self, index, pos): """ Memorize the new position of the splitter """ Settings.instance().setValue(key='View/helper-pos', value=self.vSplitter.sizes()[2]) def hideHelper(self): """ Hide assistant """ self.splitterHelperState = self.vSplitter.saveState() self.vSplitter.setSizes( [self.vSplitter.sizes()[0], self.vSplitter.sizes()[1], 0]) def showHelper(self): """ Show assistant """ if self.splitterHelperState is not None: self.vSplitter.restoreState(self.splitterHelperState) def documentViewerEmpty(self): """ Called to deactivate the WDocumentProperties widget Hide the WCursorPosition widget in the status bar """ WDocumentProperties.instance().clear() WDocumentProperties.instance().setDisabled(True) self.hideStatusBar() WDocumentViewer.instance().findWidget.hide() def currentDocumentChanged(self, wdocument): """ Called when the current document is changed @param wdocument: @type wdocument: """ # hide cursor position widget on disconnection or on the welcome page if isinstance(wdocument, WDocumentViewer.WelcomePage): self.hideStatusBar() if not RCI.instance().isAuthenticated(): WDocumentProperties.instance().setDisabled(True) return # test properties uneeded for test config, test adapter and library adapters # and welcome page if isinstance(wdocument, WDocumentViewer.WelcomePage): WDocumentProperties.instance().setDisabled(True) WDocumentProperties.instance().clear() elif isinstance(wdocument, TestConfig.WTestConfig) or isinstance(wdocument, TestAdapter.WTestAdapter) \ or isinstance(wdocument, TestTxt.WTestTxt) or isinstance(wdocument, TestLibrary.WTestLibrary) \ or isinstance(wdocument, TestPng.WTestPng) : WDocumentProperties.instance().setDisabled(True) WDocumentProperties.instance().clear() else: WDocumentProperties.instance().setDocument(wdoc=wdocument) WDocumentProperties.instance().setDisabled(False) WDocumentProperties.instance().addDescriptions(wdoc=wdocument) WDocumentProperties.instance().addParameters(wdoc=wdocument) if not isinstance(wdocument, TestData.WTestData): WDocumentProperties.instance().addParametersOutput( wdoc=wdocument) WDocumentProperties.instance().addProbes(wdoc=wdocument) WDocumentProperties.instance().addAgents(wdoc=wdocument) WDocumentViewer.instance().updateActions(wdocument=wdocument) if isinstance(wdocument, TestData.WTestData): WDocumentProperties.instance().disableOutputParameters() WDocumentProperties.instance().disableAgents() WDocumentProperties.instance().disableProbes() else: WDocumentProperties.instance().enableOutputParameters() WDocumentProperties.instance().enableProbes() WDocumentProperties.instance().enableAgents() if not isinstance(wdocument, TestAbstract.WTestAbstract): WDocumentProperties.instance().disableSteps() WDocumentProperties.instance().disableAdapters() WDocumentProperties.instance().disableLibraries() else: WDocumentProperties.instance().addSteps(wdoc=wdocument) WDocumentProperties.instance().enableSteps() WDocumentProperties.instance().addAdapters(wdoc=wdocument) WDocumentProperties.instance().enableAdapters() WDocumentProperties.instance().addLibraries(wdoc=wdocument) WDocumentProperties.instance().enableLibraries() if isinstance(wdocument, TestUnit.WTestUnit) or isinstance( wdocument, TestSuite.WTestSuite): WDocumentProperties.instance().enableMarkUnused() else: WDocumentProperties.instance().disableMarkUnused() # disable/enable status bar if isinstance(wdocument, TestConfig.WTestConfig) \ or isinstance(wdocument, TestPlan.WTestPlan) \ or isinstance(wdocument, TestPng.WTestPng) \ or isinstance(wdocument, TestAbstract.WTestAbstract) \ or isinstance(wdocument, WDocumentViewer.WelcomePage) : self.hideStatusBar() else: self.showStatusBar() self.wCursorPosition.setNumberLines(nb=wdocument.editor().lines()) def propertiesChanged(self, properties, isRoot, testId): """ Called when document propertis changed @param properties: @param properties: dict @param isRoot: @type isRoot: """ if isRoot: WDocumentProperties.instance().addDescriptions(wdoc=properties) WDocumentProperties.instance().addParameters(wdoc=properties) WDocumentProperties.instance().addParametersOutput(wdoc=properties) WDocumentProperties.instance().addAgents(wdoc=properties) WDocumentProperties.instance().addProbes(wdoc=properties) WDocumentProperties.instance().probes.setEnabled(True) else: WDocumentProperties.instance().addParameters(wdoc=properties) WDocumentProperties.instance().addAgents(wdoc=properties) WDocumentProperties.instance().addParametersOutput(wdoc=properties) WDocumentProperties.instance().probes.clear() WDocumentProperties.instance().probes.setEnabled(False) # new in v19 WDocumentProperties.instance().updateCache(properties, isRoot, testId) def documentOpened(self, wdocument): """ Called when a document is opened @param wdocument: @type wdocument: """ WDocumentProperties.instance().setEnabled(True) self.currentDocumentChanged(wdocument=wdocument) def updateWindowTitle(self, windowTitle): """ Emit the signal "updateWindowTitle" to update the title of the application @param windowTitle: new window title @type windowTitle: string """ self.UpdateWindowTitle.emit(windowTitle) def recentFileUpdated(self, fileDescription): """ Emit the signal "recentFile" to update the title of the application @param windowTitle: file descr with the complete path and type @type windowTitle: string """ self.RecentFile.emit(fileDescription) def focusChanged(self, wdocument): """ Called when the focus of the WDocumentViewer is changed @param wdocument: @type wdocument: """ WDocumentViewer.instance().updateActions(wdocument=wdocument) self.wCursorPosition.setNumberLines(nb=wdocument.editor().lines()) def totalLinesChanged(self, nb): """ This function is automaticaly called when the cursor changed in both editors and enables to update the cursor's position in the widget WCursorPosition @param ln: line index @type ln: Integer @param col: column index @type col: Integer """ self.wCursorPosition.setNumberLines(nb=nb) def cursorPositionChanged(self, ln, col): """ This function is automaticaly called when the cursor changed in both editors and enables to update the cursor's position in the widget WCursorPosition @param ln: line index @type ln: Integer @param col: column index @type col: Integer """ self.wCursorPosition.cursorPositionChanged(ln, col) def showStatusBar(self): """ Show WCursorPosition widget """ self.wCursorPosition.show() def hideStatusBar(self): """ Hide WCursorPosition widget """ self.wCursorPosition.hide()