def test(): from qt import QWidget class W(QWidget): def __init__(self): QWidget.__init__(self) def create(): global _list s = SampleControl() s.load('/home/ajole/wav/trance.wav') s.slotStart() s.slotSetZone(0, True) _list.append(s) import pkaudio from qt import QApplication, QPushButton, QObject, SIGNAL pkaudio.connect_to_host(startserver=0) a = QApplication([]) w1 = SampleControl() w1.load('/home/ajole/wav/track.wav') w1.slotStart() w1.slotSetZone(0, True) b = QPushButton('create', None) QObject.connect(b, SIGNAL('clicked()'), create) b.show() a.setMainWidget(b) a.exec_loop()
class Window(QWidget): def __init__(self): QWidget.__init__(self) self.textBrowser = QTextBrowser(self) self.textBrowser.setTextFormat(QTextBrowser.LogText) self.lineEdit = QLineEdit(self) self.startButton = QPushButton(self.tr("Start"), self) self.stopButton = QPushButton(self.tr("Stop"), self) self.stopButton.setEnabled(False) self.connect(self.lineEdit, SIGNAL("returnPressed()"), self.startCommand) self.connect(self.startButton, SIGNAL("clicked()"), self.startCommand) self.connect(self.stopButton, SIGNAL("clicked()"), self.stopCommand) layout = QGridLayout(self, 2, 3) layout.setSpacing(8) layout.addMultiCellWidget(self.textBrowser, 0, 0, 0, 2) layout.addWidget(self.lineEdit, 1, 0) layout.addWidget(self.startButton, 1, 1) layout.addWidget(self.stopButton, 1, 2) self.process = QProcess() self.connect(self.process, SIGNAL("readyReadStdout()"), self.readOutput) self.connect(self.process, SIGNAL("readyReadStderr()"), self.readErrors) self.connect(self.process, SIGNAL("processExited()"), self.resetButtons) def startCommand(self): self.process.setArguments(QStringList.split(" ", self.lineEdit.text())) self.process.closeStdin() self.startButton.setEnabled(False) self.stopButton.setEnabled(True) self.textBrowser.clear() if not self.process.start(): self.textBrowser.setText( QString("*** Failed to run %1 ***").arg(self.lineEdit.text()) ) self.resetButtons() return def stopCommand(self): self.resetButtons() self.process.tryTerminate() QTimer.singleShot(5000, self.process, SLOT("kill()")) def readOutput(self): self.textBrowser.append(QString(self.process.readStdout())) def readErrors(self): self.textBrowser.append("error: " + QString(self.process.readLineStderr())) def resetButtons(self): self.startButton.setEnabled(True) self.stopButton.setEnabled(False)
def __init__(self): QWidget.__init__(self) self.textBrowser = QTextBrowser(self) self.textBrowser.setTextFormat(QTextBrowser.LogText) self.lineEdit = QLineEdit(self) self.startButton = QPushButton(self.tr("Start"), self) self.stopButton = QPushButton(self.tr("Stop"), self) self.stopButton.setEnabled(False) self.connect(self.lineEdit, SIGNAL("returnPressed()"), self.startCommand) self.connect(self.startButton, SIGNAL("clicked()"), self.startCommand) self.connect(self.stopButton, SIGNAL("clicked()"), self.stopCommand) layout = QGridLayout(self, 2, 3) layout.setSpacing(8) layout.addMultiCellWidget(self.textBrowser, 0, 0, 0, 2) layout.addWidget(self.lineEdit, 1, 0) layout.addWidget(self.startButton, 1, 1) layout.addWidget(self.stopButton, 1, 2) self.process = QProcess() self.connect(self.process, SIGNAL("readyReadStdout()"), self.readOutput) self.connect(self.process, SIGNAL("readyReadStderr()"), self.readErrors) self.connect(self.process, SIGNAL("processExited()"), self.resetButtons)
class ParamAdvancedWidget(QWidget): def __init__(self, phl_obj=None, parent=None): super(ParamAdvancedWidget, self).__init__() self.scrollable_widget = PhilWidget(phl_obj, parent=self) scrollArea = QScrollArea() scrollArea.setWidget(self.scrollable_widget) vbox = QVBoxLayout() search_label = QLabel("Search:") search_edit = QLineEdit() search_edit.setPlaceholderText("Type search here") search_edit.textChanged.connect(self.scrollable_widget.user_searching) self.search_next_button = QPushButton("Find next") self.search_next_button.setEnabled(False) hbox = QHBoxLayout() hbox.addWidget(search_label) hbox.addWidget(search_edit) hbox.addWidget(self.search_next_button) self.search_next_button.clicked.connect(self.scrollable_widget.find_next) vbox.addLayout(hbox) vbox.addWidget(scrollArea) self.setLayout(vbox)
def __init__(self, interfazdato, cajadisponible): """Caja disponible son los elementos que aparecen a la izquierda en el selector""" #VARIABLES PUBLICAS QWidget.__init__(self, None, "selector", 0) image1 = QPixmap(IMAGE1DATA) image2 = QPixmap(IMAGE2DATA) selectorsimplelayout = QHBoxLayout(self, 11, 6, "WSelectorSimpleLayout") layout2 = QVBoxLayout(None, 0, 6, "layout2") widgetstack1 = QWidgetStack(self, "staaack") widgetstack1.addWidget(cajadisponible) widgetstack1.raiseWidget(cajadisponible) widgetstack1.setSizePolicy(QSizePolicy(\ QSizePolicy.Expanding, QSizePolicy.Expanding, \ 0, 0, widgetstack1.sizePolicy().hasHeightForWidth())) self._cajadisponible = cajadisponible layout2.addWidget(widgetstack1) selectorsimplelayout.addLayout(layout2) layout1 = QVBoxLayout(None, 0, 6, "layout1") self.__pushbutton1 = QPushButton(self, "pushButton1") self.__pushbutton1.setMaximumSize(QSize(30, 30)) self.__pushbutton1.setPixmap(image1) layout1.addWidget(self.__pushbutton1) spacer1 = QSpacerItem(30, 122, QSizePolicy.Minimum, QSizePolicy.Expanding) layout1.addItem(spacer1) self.__pushbutton2 = QPushButton(self,"pushButton2") self.__pushbutton2.setMaximumSize(QSize(30, 30)) self.__pushbutton2.setPixmap(image2) self.__pushbutton2.setAccel("Del") layout1.addWidget(self.__pushbutton2) selectorsimplelayout.addLayout(layout1) layout3 = QVBoxLayout(None, 0, 6, "layout3") self._textlabel2 = QLabel(self, "textLabel2") layout3.addWidget(self._textlabel2) self._cajaseleccion = QListBox(self,"cajaseleccion") self._cajaseleccion.setMinimumSize(QSize(0, 60)) layout3.addWidget(self._cajaseleccion) selectorsimplelayout.addLayout(layout3) self._cajaseleccion.setSizePolicy(QSizePolicy(\ QSizePolicy.Expanding,QSizePolicy.Expanding, 0, 0, \ self._cajaseleccion.sizePolicy().hasHeightForWidth())) self.setCaption("Form1") self._textlabel2.setText(u"Selección") self.resize(QSize(294, 240).expandedTo(self.minimumSizeHint())) self.clearWState(Qt.WState_Polished) self.__conexiones() #Miembros !qt self.seleccion = [] self._dato = interfazdato
def __init__(self, parent=None): super(ImportPage, self).__init__(parent=None) main_v_box = QVBoxLayout() label_font = QFont() sys_font_point_size = label_font.pointSize() label_font.setPointSize(sys_font_point_size + 2) step_label = QLabel(str("Import")) step_label.setFont(label_font) self.simple_lin = QLineEdit(self) self.simple_lin.textChanged.connect(self.update_command) self.x_spn_bx = QSpinBox() self.x_spn_bx.setMaximum(99999) self.x_spn_bx.setSpecialValueText(" ") self.y_spn_bx = QSpinBox() self.y_spn_bx.setMaximum(99999) self.y_spn_bx.setSpecialValueText(" ") self.x_spn_bx.valueChanged.connect(self.x_beam_changed) self.y_spn_bx.valueChanged.connect(self.y_beam_changed) self.chk_invert = QCheckBox("Invert rotation axis") self.chk_invert.stateChanged.connect(self.inv_rota_changed) self.opn_fil_btn = QPushButton(" \n Select file(s) \n ") main_path = get_main_path() self.opn_fil_btn.setIcon(QIcon(main_path + "/resources/import.png")) self.opn_fil_btn.setIconSize(QSize(80, 48)) main_v_box.addWidget(step_label) main_v_box.addWidget(self.opn_fil_btn) main_v_box.addWidget(self.simple_lin) self.b_cetre_label = QLabel("\n\n Beam centre") main_v_box.addWidget(self.b_cetre_label) cent_hbox = QHBoxLayout() self.x_label = QLabel(" X: ") cent_hbox.addWidget(self.x_label) cent_hbox.addWidget(self.x_spn_bx) self.y_label = QLabel(" Y: ") cent_hbox.addWidget(self.y_label) cent_hbox.addWidget(self.y_spn_bx) # cent_hbox.addWidget(QLabel(" \n ")) cent_hbox.addStretch() main_v_box.addLayout(cent_hbox) main_v_box.addWidget(self.chk_invert) main_v_box.addStretch() self.opn_fil_btn.clicked.connect(self.open_files) self.defa_dir = str(os.getcwd()) self.setLayout(main_v_box) # self.show() self.reset_par()
def __init__(self, swappers): QMessageBox.__init__(self) decorateWindow(self, i18n("Swap Seats")) self.setText( i18n("By the rules, %1 and %2 should now exchange their seats. ", swappers[0].name, swappers[1].name)) self.yesAnswer = QPushButton(i18n("&Exchange")) self.addButton(self.yesAnswer, QMessageBox.YesRole) self.noAnswer = QPushButton(i18n("&Keep seat")) self.addButton(self.noAnswer, QMessageBox.NoRole)
def keyPressEvent(self, event): """forward horizintal arrows to the hand board""" key = Board.mapChar2Arrow(event) if key in [Qt.Key_Left, Qt.Key_Right]: game = self.client.game if game and game.activePlayer == game.myself: game.myself.handBoard.keyPressEvent(event) self.setFocus() return QPushButton.keyPressEvent(self, event)
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 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 __init__(self): super(OuterCaller, self).__init__() v_box = QVBoxLayout() recip_lat_but = QPushButton("\n Open Reciprocal Lattice Viewer \n") recip_lat_but.clicked.connect(self.run_recip_dialg) v_box.addWidget(recip_lat_but) img_but = QPushButton("\n Open Image Viewer \n") img_but.clicked.connect(self.run_img_dialg) v_box.addWidget(img_but) self.diag = ExternalProcDialog(parent=self.window()) self.setLayout(v_box)
def setupUi(self): """layout the window""" decorateWindow(self, m18n('Customize rulesets')) self.setObjectName('Rulesets') hlayout = QHBoxLayout(self) v1layout = QVBoxLayout() self.v1widget = QWidget() v1layout = QVBoxLayout(self.v1widget) v2layout = QVBoxLayout() hlayout.addWidget(self.v1widget) hlayout.addLayout(v2layout) for widget in [self.v1widget, hlayout, v1layout, v2layout]: widget.setContentsMargins(0, 0, 0, 0) hlayout.setStretchFactor(self.v1widget, 10) self.btnCopy = QPushButton() self.btnRemove = QPushButton() self.btnCompare = QPushButton() self.btnClose = QPushButton() self.rulesetView = RuleTreeView( m18nc('kajongg', 'Rule'), self.btnCopy, self.btnRemove, self.btnCompare) v1layout.addWidget(self.rulesetView) self.rulesetView.setWordWrap(True) self.rulesetView.setMouseTracking(True) spacerItem = QSpacerItem( 20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) v2layout.addWidget(self.btnCopy) v2layout.addWidget(self.btnRemove) v2layout.addWidget(self.btnCompare) self.btnCopy.clicked.connect(self.rulesetView.copyRow) self.btnRemove.clicked.connect(self.rulesetView.removeRow) self.btnCompare.clicked.connect(self.rulesetView.compareRow) self.btnClose.clicked.connect(self.hide) v2layout.addItem(spacerItem) v2layout.addWidget(self.btnClose) self.retranslateUi() StateSaver(self) self.show()
def __init__(self, scene): QWidget.__init__(self) self.scene = scene decorateWindow(self, i18n('Scoring for this Hand')) self.nameLabels = [None] * 4 self.spValues = [None] * 4 self.windLabels = [None] * 4 self.wonBoxes = [None] * 4 self.detailsLayout = [None] * 4 self.details = [None] * 4 self.__tilePixMaps = [] self.__meldPixMaps = [] grid = QGridLayout(self) pGrid = QGridLayout() grid.addLayout(pGrid, 0, 0, 2, 1) pGrid.addWidget(QLabel(i18nc('kajongg', "Player")), 0, 0) pGrid.addWidget(QLabel(i18nc('kajongg', "Wind")), 0, 1) pGrid.addWidget(QLabel(i18nc('kajongg', 'Score')), 0, 2) pGrid.addWidget(QLabel(i18n("Winner")), 0, 3) self.detailTabs = QTabWidget() self.detailTabs.setDocumentMode(True) pGrid.addWidget(self.detailTabs, 0, 4, 8, 1) for idx in range(4): self.setupUiForPlayer(pGrid, idx) self.draw = QCheckBox(i18nc('kajongg', 'Draw')) self.draw.clicked.connect(self.wonChanged) btnPenalties = QPushButton(i18n("&Penalties")) btnPenalties.clicked.connect(self.penalty) self.btnSave = QPushButton(i18n('&Save Hand')) self.btnSave.clicked.connect(self.game.nextScoringHand) self.btnSave.setEnabled(False) self.setupUILastTileMeld(pGrid) pGrid.setRowStretch(87, 10) pGrid.addWidget(self.draw, 7, 3) self.cbLastTile.currentIndexChanged.connect(self.slotLastTile) self.cbLastMeld.currentIndexChanged.connect(self.slotInputChanged) btnBox = QHBoxLayout() btnBox.addWidget(btnPenalties) btnBox.addWidget(self.btnSave) pGrid.addLayout(btnBox, 8, 4) StateSaver(self) self.refresh()
def set_ref(self, in_json_path, lin_num): my_box = QVBoxLayout() self.my_inner_table = ReindexTable(self) cwd_path = os.path.join(sys_arg.directory, "dui_files") full_json_path = os.path.join(cwd_path, in_json_path) self.my_inner_table.add_opts_lst(json_path=full_json_path) if self.my_inner_table.rec_col is not None: my_solu = self.my_inner_table.find_best_solu() self.my_inner_table.opt_clicked(my_solu, 0) recomd_str = "Select a bravais lattice to enforce: \n" try: recomd_str += "(best guess solution = row {})".format( self.my_inner_table.tmp_sel + 1) except BaseException as e: # Since we don't know exactly what this was supposed to be # - AttributeError? We don't know how to cleanly catch logger.error("Unknown exception catch caught. Was: %s", e) recomd_str += "(no best solution could be automatically determined)" bot_box = QHBoxLayout() bot_box.addWidget(QLabel(recomd_str)) bot_box.addStretch() ok_but = QPushButton(" OK ") ok_but.clicked.connect(self.my_inner_table.ok_clicked) bot_box.addWidget(ok_but) heather_text, v_heather_size = heather_text_from_lin( lin_num, full_json_path) my_box.addWidget(QLabel(heather_text)) my_box.addWidget(self.my_inner_table) my_box.addLayout(bot_box) self.setLayout(my_box) n_col = self.my_inner_table.columnCount() tot_width = 80 for col in range(n_col): loc_width = self.my_inner_table.columnWidth(col) tot_width += loc_width n_row = self.my_inner_table.rowCount() row_height = self.my_inner_table.rowHeight(1) tot_heght = int((float(n_row)) * float(row_height)) tot_heght += int( (float(v_heather_size + 2)) * float(row_height * 0.62)) self.resize(tot_width, tot_heght) # self.adjustSize() self.show()
def SimpleButton(parent, title, handler, page=None, image=None): tabpage = parent.getPage(page) button = QPushButton(tabpage) if image: bi = QPixmap() bi.loadFromData(image, "PNG") button.setIconSet(QIconSet(bi)) w = bi.width() + 3 h = bi.height() + 3 if w < 32: w = 32 if h < 32: h = 32 button.setMaximumSize(QSize(w, h)) else: button.setText(title) QToolTip.add(button, title) parent.connect(button, SIGNAL("clicked()"), handler) button.show() p = ToolbarPlugin(parent) p.getWidget = lambda: button
def setupFrameControlFrame(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupFrameControlFrame( self) self.frameCopySelector = slicer.qMRMLNodeComboBox() self.frameCopySelector.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) self.frameCopySelector.nodeTypes = ['vtkMRMLScalarVolumeNode'] self.frameCopySelector.setMRMLScene(slicer.mrmlScene) self.frameCopySelector.addEnabled = 1 self.frameCopySelector.enabled = 0 # do not show "children" of vtkMRMLScalarVolumeNode self.frameCopySelector.hideChildNodeTypes = [ "vtkMRMLDiffusionWeightedVolumeNode", "vtkMRMLDiffusionTensorVolumeNode", "vtkMRMLVectorVolumeNode" ] self.extractFrameCopy = False self.extractFrameCheckBox = QCheckBox('Enable copying while sliding') hbox = QHBoxLayout() hbox.addWidget(QLabel('Current frame copy')) hbox.addWidget(self.frameCopySelector) hbox.addWidget(self.extractFrameCheckBox) self.inputFrameLayout.addRow(hbox) self.currentFrameCopySelector = slicer.qMRMLNodeComboBox() self.currentFrameCopySelector.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) self.currentFrameCopySelector.nodeTypes = ['vtkMRMLScalarVolumeNode'] self.currentFrameCopySelector.setMRMLScene(slicer.mrmlScene) self.currentFrameCopySelector.addEnabled = 0 self.currentFrameCopySelector.enabled = 0 self.currentFrameCopyButton = QPushButton('Copy frame') self.currentFrameCopyButton.toolTip = 'Copy currently selected frame' hbox2 = QHBoxLayout() hbox2.addWidget(QLabel('Current frame click-to-copy')) hbox2.addWidget(self.currentFrameCopySelector) hbox2.addWidget(self.currentFrameCopyButton) self.inputFrameLayout.addRow(hbox2)
def setup(self): showPlusServerWidget = True if _platform == "linux" or _platform == "linux2" or _platform == "darwin": #linux or linux or OS X message = "Attention: You are running Slicer on Linux or OS X. Do you have PlusServer installed on the current OS?" result = QMessageBox.question(slicer.util.mainWindow(), 'ProstateTRUSNav', message, QMessageBox.Yes | QMessageBox.No) showPlusServerWidget = result == QMessageBox.Yes if _platform == "win32" or showPlusServerWidget: # Windows... plusServerCollapsibleButton = ctkCollapsibleButton() plusServerCollapsibleButton.text = "PlusServer" self.layout.addWidget(plusServerCollapsibleButton) self.configurationFileChooserButton = QPushButton(self.configurationFile) self.configurationFileChooserButton.connect('clicked()', self.onConfigFileSelected) self.runPlusServerButton = QPushButton("Run PlusServer") self.runPlusServerButton.setCheckable(True) self.runPlusServerButton.connect('clicked()', self.onRunPlusServerButtonClicked) self.serverFormLayout = QFormLayout(plusServerCollapsibleButton) self.serverExecutableChooserButton = QPushButton(self.serverExecutable) self.serverExecutableChooserButton.connect('clicked()', self.onServerExecutableSelected) hbox = QHBoxLayout() hbox.addWidget(self.serverExecutableChooserButton) self.serverFormLayout.addRow(hbox) hbox = QHBoxLayout() hbox.addWidget(self.configurationFileChooserButton) hbox.addWidget(self.runPlusServerButton) self.serverFormLayout.addRow(hbox) GuideletWidget.setup(self) # do specific setup here if _platform == "win32" or showPlusServerWidget: self.launchGuideletButton.setEnabled(False) self.checkExecutableAndArgument()
def SimpleButton(parent, title, handler, page=None, image=None): tabpage = parent.getPage(page) button = QPushButton(tabpage) if image : bi = QPixmap() bi.loadFromData(image, "PNG") button.setIconSet(QIconSet(bi)) w = bi.width()+3 h = bi.height()+3 if w < 32: w = 32 if h < 32: h = 32 button.setMaximumSize(QSize(w, h)) else: button.setText(title) QToolTip.add(button, title) parent.connect(button, SIGNAL("clicked()"), handler) button.show() p = ToolbarPlugin(parent) p.getWidget = lambda: button
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.btn1 = QPushButton("Click me", self) vbox = QVBoxLayout() vbox.addWidget(QLabel("A1")) vbox.addWidget(self.btn1) vbox.addWidget(QLabel("B2")) self.btn1.clicked.connect(self.doit) self.my_pop = None self.main_widget = QWidget(self) self.main_widget.setLayout(vbox) self.setCentralWidget(self.main_widget)
def setupUi(self): """layout the window""" decorateWindow(self, i18n('Customize rulesets')) self.setObjectName('Rulesets') hlayout = QHBoxLayout(self) v1layout = QVBoxLayout() self.v1widget = QWidget() v1layout = QVBoxLayout(self.v1widget) v2layout = QVBoxLayout() hlayout.addWidget(self.v1widget) hlayout.addLayout(v2layout) for widget in [self.v1widget, hlayout, v1layout, v2layout]: widget.setContentsMargins(0, 0, 0, 0) hlayout.setStretchFactor(self.v1widget, 10) self.btnCopy = QPushButton() self.btnRemove = QPushButton() self.btnCompare = QPushButton() self.btnClose = QPushButton() self.rulesetView = RuleTreeView( i18ncE('kajongg', 'Rule'), self.btnCopy, self.btnRemove, self.btnCompare) v1layout.addWidget(self.rulesetView) self.rulesetView.setWordWrap(True) self.rulesetView.setMouseTracking(True) spacerItem = QSpacerItem( 20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) v2layout.addWidget(self.btnCopy) v2layout.addWidget(self.btnRemove) v2layout.addWidget(self.btnCompare) self.btnCopy.clicked.connect(self.rulesetView.copyRow) self.btnRemove.clicked.connect(self.rulesetView.removeRow) self.btnCompare.clicked.connect(self.rulesetView.compareRow) self.btnClose.clicked.connect(self.hide) v2layout.addItem(spacerItem) v2layout.addWidget(self.btnClose) self.retranslateUi() StateSaver(self) self.show()
def __init__(self, scene): QWidget.__init__(self) self.scene = scene decorateWindow(self, m18n("Scoring for this Hand")) self.nameLabels = [None] * 4 self.spValues = [None] * 4 self.windLabels = [None] * 4 self.wonBoxes = [None] * 4 self.detailsLayout = [None] * 4 self.details = [None] * 4 self.__tilePixMaps = [] self.__meldPixMaps = [] grid = QGridLayout(self) pGrid = QGridLayout() grid.addLayout(pGrid, 0, 0, 2, 1) pGrid.addWidget(QLabel(m18nc("kajongg", "Player")), 0, 0) pGrid.addWidget(QLabel(m18nc("kajongg", "Wind")), 0, 1) pGrid.addWidget(QLabel(m18nc("kajongg", "Score")), 0, 2) pGrid.addWidget(QLabel(m18n("Winner")), 0, 3) self.detailTabs = QTabWidget() self.detailTabs.setDocumentMode(True) pGrid.addWidget(self.detailTabs, 0, 4, 8, 1) for idx in range(4): self.setupUiForPlayer(pGrid, idx) self.draw = QCheckBox(m18nc("kajongg", "Draw")) self.draw.clicked.connect(self.wonChanged) btnPenalties = QPushButton(m18n("&Penalties")) btnPenalties.clicked.connect(self.penalty) self.btnSave = QPushButton(m18n("&Save Hand")) self.btnSave.clicked.connect(self.game.nextScoringHand) self.btnSave.setEnabled(False) self.setupUILastTileMeld(pGrid) pGrid.setRowStretch(87, 10) pGrid.addWidget(self.draw, 7, 3) self.cbLastTile.currentIndexChanged.connect(self.slotLastTile) self.cbLastMeld.currentIndexChanged.connect(self.slotInputChanged) btnBox = QHBoxLayout() btnBox.addWidget(btnPenalties) btnBox.addWidget(self.btnSave) pGrid.addLayout(btnBox, 8, 4) StateSaver(self) self.refresh()
def __init__(self, parent=None): super(ExternalProcDialog, self).__init__(parent) vbox = QVBoxLayout() label = QLabel(("Running a pop-up viewer ...\n\n" "remember to close the viewer before\n" "performing any other task")) label.setAlignment(Qt.AlignCenter) vbox.addWidget(label) kl_but = QPushButton("Close pop-up viewer") kl_but.clicked.connect(self.kill_my_proc) vbox.addWidget(kl_but) self.setLayout(vbox) self.setFixedSize(self.sizeHint()) self.setModal(True) self.setWindowTitle("External Tool") self.my_process = None
def __init__(self, parent=None): super(StopRunRetry, self).__init__() main_path = get_main_path() ctrl_box = QHBoxLayout() self.repeat_btn = QPushButton("\n Retry \n", self) re_try_icon_path = str(main_path + "/resources/re_try.png") re_try_grayed_path = str(main_path + "/resources/re_try_grayed.png") tmp_ico = QIcon() tmp_ico.addFile(re_try_icon_path, mode=QIcon.Normal) tmp_ico.addFile(re_try_grayed_path, mode=QIcon.Disabled) self.repeat_btn.setIcon(tmp_ico) self.repeat_btn.setIconSize(QSize(50, 38)) ctrl_box.addWidget(self.repeat_btn) self.run_btn = QPushButton("\n Run \n", self) self.dials_logo_path = str( main_path + "/resources/DIALS_Logo_smaller_centred.png" ) dials_grayed_path = str( main_path + "/resources/DIALS_Logo_smaller_centred_grayed.png" ) tmp_ico = QIcon() tmp_ico.addFile(self.dials_logo_path, mode=QIcon.Normal) tmp_ico.addFile(dials_grayed_path, mode=QIcon.Disabled) self.run_btn.setIcon(tmp_ico) self.run_btn.setIconSize(QSize(50, 50)) ctrl_box.addWidget(self.run_btn) self.stop_btn = QPushButton("\n Stop \n", self) stop_logo_path = str(main_path + "/resources/stop.png") stop_grayed_path = str(main_path + "/resources/stop_grayed.png") tmp_ico = QIcon() tmp_ico.addFile(stop_logo_path, mode=QIcon.Normal) tmp_ico.addFile(stop_grayed_path, mode=QIcon.Disabled) self.stop_btn.setIcon(tmp_ico) self.stop_btn.setIconSize(QSize(50, 38)) ctrl_box.addWidget(self.stop_btn) self.setLayout(ctrl_box)
def setup(self): showPlusServerWidget = True if _platform == "linux" or _platform == "linux2" or _platform == "darwin": #linux or linux or OS X message = "Attention: You are running Slicer on Linux or OS X. Do you have PlusServer installed on the current OS?" result = QMessageBox.question(slicer.util.mainWindow(), 'ProstateTRUSNav', message, QMessageBox.Yes | QMessageBox.No) showPlusServerWidget = result == QMessageBox.Yes if _platform == "win32" or showPlusServerWidget: # Windows... plusServerCollapsibleButton = ctkCollapsibleButton() plusServerCollapsibleButton.text = "PlusServer" self.layout.addWidget(plusServerCollapsibleButton) self.configurationFileChooserButton = QPushButton( self.configurationFile) self.configurationFileChooserButton.connect( 'clicked()', self.onConfigFileSelected) self.runPlusServerButton = QPushButton("Run PlusServer") self.runPlusServerButton.setCheckable(True) self.runPlusServerButton.connect('clicked()', self.onRunPlusServerButtonClicked) self.serverFormLayout = QFormLayout(plusServerCollapsibleButton) self.serverExecutableChooserButton = QPushButton( self.serverExecutable) self.serverExecutableChooserButton.connect( 'clicked()', self.onServerExecutableSelected) hbox = QHBoxLayout() hbox.addWidget(self.serverExecutableChooserButton) self.serverFormLayout.addRow(hbox) hbox = QHBoxLayout() hbox.addWidget(self.configurationFileChooserButton) hbox.addWidget(self.runPlusServerButton) self.serverFormLayout.addRow(hbox) GuideletWidget.setup(self) # do specific setup here if _platform == "win32" or showPlusServerWidget: self.launchGuideletButton.setEnabled(False) self.checkExecutableAndArgument()
def setupFrameControlFrame(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupFrameControlFrame(self) self.frameCopySelector = slicer.qMRMLNodeComboBox() self.frameCopySelector.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) self.frameCopySelector.nodeTypes = ['vtkMRMLScalarVolumeNode'] self.frameCopySelector.setMRMLScene(slicer.mrmlScene) self.frameCopySelector.addEnabled = 1 self.frameCopySelector.enabled = 0 # do not show "children" of vtkMRMLScalarVolumeNode self.frameCopySelector.hideChildNodeTypes = ["vtkMRMLDiffusionWeightedVolumeNode", "vtkMRMLDiffusionTensorVolumeNode", "vtkMRMLVectorVolumeNode"] self.extractFrameCopy = False self.extractFrameCheckBox = QCheckBox('Enable copying while sliding') hbox = QHBoxLayout() hbox.addWidget(QLabel('Current frame copy')) hbox.addWidget(self.frameCopySelector) hbox.addWidget(self.extractFrameCheckBox) self.inputFrameLayout.addRow(hbox) self.currentFrameCopySelector = slicer.qMRMLNodeComboBox() self.currentFrameCopySelector.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) self.currentFrameCopySelector.nodeTypes = ['vtkMRMLScalarVolumeNode'] self.currentFrameCopySelector.setMRMLScene(slicer.mrmlScene) self.currentFrameCopySelector.addEnabled = 0 self.currentFrameCopySelector.enabled = 0 self.currentFrameCopyButton = QPushButton('Copy frame') self.currentFrameCopyButton.toolTip = 'Copy currently selected frame' hbox2 = QHBoxLayout() hbox2.addWidget(QLabel('Current frame click-to-copy')) hbox2.addWidget(self.currentFrameCopySelector) hbox2.addWidget(self.currentFrameCopyButton) self.inputFrameLayout.addRow(hbox2)
class RulesetSelector(QWidget): """presents all available rulesets with previews""" def __init__(self, parent=None): super(RulesetSelector, self).__init__(parent) self.setContentsMargins(0, 0, 0, 0) self.setupUi() def setupUi(self): """layout the window""" decorateWindow(self, i18n('Customize rulesets')) self.setObjectName('Rulesets') hlayout = QHBoxLayout(self) v1layout = QVBoxLayout() self.v1widget = QWidget() v1layout = QVBoxLayout(self.v1widget) v2layout = QVBoxLayout() hlayout.addWidget(self.v1widget) hlayout.addLayout(v2layout) for widget in [self.v1widget, hlayout, v1layout, v2layout]: widget.setContentsMargins(0, 0, 0, 0) hlayout.setStretchFactor(self.v1widget, 10) self.btnCopy = QPushButton() self.btnRemove = QPushButton() self.btnCompare = QPushButton() self.btnClose = QPushButton() self.rulesetView = RuleTreeView( i18ncE('kajongg', 'Rule'), self.btnCopy, self.btnRemove, self.btnCompare) v1layout.addWidget(self.rulesetView) self.rulesetView.setWordWrap(True) self.rulesetView.setMouseTracking(True) spacerItem = QSpacerItem( 20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) v2layout.addWidget(self.btnCopy) v2layout.addWidget(self.btnRemove) v2layout.addWidget(self.btnCompare) self.btnCopy.clicked.connect(self.rulesetView.copyRow) self.btnRemove.clicked.connect(self.rulesetView.removeRow) self.btnCompare.clicked.connect(self.rulesetView.compareRow) self.btnClose.clicked.connect(self.hide) v2layout.addItem(spacerItem) v2layout.addWidget(self.btnClose) self.retranslateUi() StateSaver(self) self.show() def sizeHint(self): """we never want a horizontal scrollbar for player names, we always want to see them in full""" result = QWidget.sizeHint(self) available = Internal.app.desktop().availableGeometry() height = max(result.height(), available.height() * 2 // 3) width = max(result.width(), available.width() // 2) return QSize(width, height) def minimumSizeHint(self): """we never want a horizontal scrollbar for player names, we always want to see them in full""" return self.sizeHint() def showEvent(self, dummyEvent): """reload the rulesets""" self.refresh() def refresh(self): """retranslate and reload rulesets""" self.retranslateUi() self.rulesetView.rulesets = Ruleset.availableRulesets() def hideEvent(self, event): """close all differ dialogs""" for differ in self.rulesetView.differs: differ.hide() del differ QWidget.hideEvent(self, event) def retranslateUi(self): """translate to current language""" self.btnCopy.setText(i18n("C&opy")) self.btnCompare.setText(i18nc('Kajongg ruleset comparer', 'Co&mpare')) self.btnRemove.setText(i18n('&Remove')) self.btnClose.setText(i18n('&Close'))
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 ImportPage(QWidget): update_command_lst_low_level = Signal(list) """ This stacked widget basically helps the user to browse the input images path, there is no auto-generated GUI form Phil parameters in use withing this widget. """ def __init__(self, parent=None): super(ImportPage, self).__init__(parent=None) main_v_box = QVBoxLayout() label_font = QFont() sys_font_point_size = label_font.pointSize() label_font.setPointSize(sys_font_point_size + 2) step_label = QLabel(str("Import")) step_label.setFont(label_font) self.simple_lin = QLineEdit(self) self.simple_lin.textChanged.connect(self.update_command) self.x_spn_bx = QSpinBox() self.x_spn_bx.setMaximum(99999) self.x_spn_bx.setSpecialValueText(" ") self.y_spn_bx = QSpinBox() self.y_spn_bx.setMaximum(99999) self.y_spn_bx.setSpecialValueText(" ") self.x_spn_bx.valueChanged.connect(self.x_beam_changed) self.y_spn_bx.valueChanged.connect(self.y_beam_changed) self.chk_invert = QCheckBox("Invert rotation axis") self.chk_invert.stateChanged.connect(self.inv_rota_changed) self.opn_fil_btn = QPushButton(" \n Select file(s) \n ") main_path = get_main_path() self.opn_fil_btn.setIcon(QIcon(main_path + "/resources/import.png")) self.opn_fil_btn.setIconSize(QSize(80, 48)) main_v_box.addWidget(step_label) main_v_box.addWidget(self.opn_fil_btn) main_v_box.addWidget(self.simple_lin) self.b_cetre_label = QLabel("\n\n Beam centre") main_v_box.addWidget(self.b_cetre_label) cent_hbox = QHBoxLayout() self.x_label = QLabel(" X: ") cent_hbox.addWidget(self.x_label) cent_hbox.addWidget(self.x_spn_bx) self.y_label = QLabel(" Y: ") cent_hbox.addWidget(self.y_label) cent_hbox.addWidget(self.y_spn_bx) # cent_hbox.addWidget(QLabel(" \n ")) cent_hbox.addStretch() main_v_box.addLayout(cent_hbox) main_v_box.addWidget(self.chk_invert) main_v_box.addStretch() self.opn_fil_btn.clicked.connect(self.open_files) self.defa_dir = str(os.getcwd()) self.setLayout(main_v_box) # self.show() self.reset_par() def reset_par(self): logger.info("reset_par(ImportPage)") self.cmd_list = [] self.simple_lin.setText(" ? ") self.x_spn_bx.setValue(0.0) self.y_spn_bx.setValue(0.0) self.chk_invert.setChecked(False) self.x_beam, self.y_beam = 0.0, 0.0 self.path_file_str = "" self.second_half = "" self.third_half = "" def update_param_w_lst(self, lst_in): self.reset_par() logger.info("update_param_w_lst(ImportPage) \n lst: \n", lst_in) for singl_com in lst_in: if singl_com[0:1] == "/": self.path_file_str = str(singl_com) self.put_str_lin() if singl_com[0:12] == "image_range=": self.path_file_str += " " self.path_file_str += str(singl_com) self.put_str_lin() if singl_com == "invert_rotation_axis=True": self.chk_invert.setChecked(True) if singl_com[0:22] == "slow_fast_beam_centre=": yb_xb_str = singl_com[22:] yb_str, xb_str = yb_xb_str.split(",") yb = float(yb_str) xb = float(xb_str) self.y_spn_bx.setValue(yb) self.x_spn_bx.setValue(xb) def inv_rota_changed(self): if self.chk_invert.checkState(): self.third_half = "invert_rotation_axis=True" else: self.third_half = "" self.put_str_lin() def x_beam_changed(self, value): self.x_beam = value self.build_second_half() def y_beam_changed(self, value): self.y_beam = value self.build_second_half() def build_second_half(self): if self.x_beam != 0.0 and self.y_beam != 0.0: self.second_half = ( "slow_fast_beam_centre=" + str(self.y_beam) + "," + str(self.x_beam) ) else: self.second_half = "" self.put_str_lin() def open_files(self): lst_file_path = QFileDialog.getOpenFileNames( self, "Open File(s)", self.defa_dir, "All Files (*.*)" ) if len(lst_file_path) > 0: new_dir, new_command = get_import_run_string(lst_file_path) # logger.info("\n new_dir=", new_dir, ">>") # logger.info("\n new_command =", new_command, ">>") self.path_file_str = new_command self.defa_dir = new_dir self.put_str_lin() def put_str_lin(self): # logger.info("self.path_file_str =", self.path_file_str, ">>") self.cmd_list = [ self.path_file_str, self.second_half.lstrip(), self.third_half.lstrip(), ] txt_lin = " ".join(self.cmd_list).rstrip() while " " in txt_lin: txt_lin = txt_lin.replace(" ", " ") self.simple_lin.setText(txt_lin) def set_arg_obj(self, sys_arg_in): """Pass the system argument object to handle launch arguments.""" if sys_arg_in.template is not None: str_arg = str(sys_arg_in.template) self.simple_lin.setText(str_arg) def update_command(self): self.command_lst = [["import"]] param_com = str(self.simple_lin.text()) cmd_lst = param_com.split(" ") for single_com in cmd_lst: self.command_lst[0].append(single_com) self.update_command_lst_low_level.emit(self.command_lst[0]) def gray_me_out(self): self.simple_lin.setEnabled(False) self.opn_fil_btn.setEnabled(False) self.x_spn_bx.setEnabled(False) self.y_spn_bx.setEnabled(False) self.x_label.setEnabled(False) self.y_label.setEnabled(False) self.b_cetre_label.setEnabled(False) self.chk_invert.setEnabled(False) def activate_me(self, cur_nod=None): self.simple_lin.setEnabled(True) self.opn_fil_btn.setEnabled(True) self.y_spn_bx.setEnabled(True) self.x_spn_bx.setEnabled(True) self.x_label.setEnabled(True) self.y_label.setEnabled(True) self.b_cetre_label.setEnabled(True) self.chk_invert.setEnabled(True)
def setupPlotSettingsFrame(self): self.plotSettingsFrame = ctk.ctkCollapsibleButton() self.plotSettingsFrame.text = "Plotting Settings" self.plotSettingsFrame.collapsed = 1 plotSettingsFrameLayout = QFormLayout(self.plotSettingsFrame) self.layout.addWidget(self.plotSettingsFrame) # label map for probing self.labelMapSelector = slicer.qMRMLNodeComboBox() self.labelMapSelector.nodeTypes = ['vtkMRMLLabelMapVolumeNode'] self.labelMapSelector.toolTip = 'Label map to be probed' self.labelMapSelector.setMRMLScene(slicer.mrmlScene) self.labelMapSelector.addEnabled = 0 self.chartButton = QPushButton('Chart') self.chartButton.setEnabled(False) hbox = QHBoxLayout() hbox.addWidget(QLabel('Probed label volume')) hbox.addWidget(self.labelMapSelector) hbox.addWidget(self.chartButton) plotSettingsFrameLayout.addRow(hbox) self.iCharting = QCheckBox('Interactive charting') self.iCharting.setChecked(True) plotSettingsFrameLayout.addRow(self.iCharting) self.iChartingMode = QButtonGroup() self.iChartingIntensity = QRadioButton('Signal intensity') self.iChartingIntensityFixedAxes = QRadioButton('Fixed range intensity') self.iChartingPercent = QRadioButton('Percentage change') self.iChartingIntensity.setChecked(1) self.iChartingMode.addButton(self.iChartingIntensity) self.iChartingMode.addButton(self.iChartingIntensityFixedAxes) self.iChartingMode.addButton(self.iChartingPercent) hbox = QHBoxLayout() self.plottingModeGroupBox = QGroupBox('Plotting mode:') plottingModeLayout = QVBoxLayout() self.plottingModeGroupBox.setLayout(plottingModeLayout) plottingModeLayout.addWidget(self.iChartingIntensity) plottingModeLayout.addWidget(self.iChartingIntensityFixedAxes) plottingModeLayout.addWidget(self.iChartingPercent) hbox.addWidget(self.plottingModeGroupBox) self.showLegendCheckBox = QCheckBox('Display legend') self.showLegendCheckBox.setChecked(0) self.xLogScaleCheckBox = QCheckBox('Use log scale for X axis') self.xLogScaleCheckBox.setChecked(0) self.yLogScaleCheckBox = QCheckBox('Use log scale for Y axis') self.yLogScaleCheckBox.setChecked(0) self.plotGeneralSettingsGroupBox = QGroupBox('General Plot options:') plotGeneralSettingsLayout = QVBoxLayout() self.plotGeneralSettingsGroupBox.setLayout(plotGeneralSettingsLayout) plotGeneralSettingsLayout.addWidget(self.showLegendCheckBox) plotGeneralSettingsLayout.addWidget(self.xLogScaleCheckBox) plotGeneralSettingsLayout.addWidget(self.yLogScaleCheckBox) hbox.addWidget(self.plotGeneralSettingsGroupBox) plotSettingsFrameLayout.addRow(hbox) self.nFramesBaselineCalculation = QSpinBox() self.nFramesBaselineCalculation.minimum = 1 hbox = QHBoxLayout() hbox.addWidget(QLabel('Frame count(baseline calculation):')) hbox.addWidget(self.nFramesBaselineCalculation) plotSettingsFrameLayout.addRow(hbox)
# -*- coding: utf-8 -*- import sys from qt import QApplication, QPushButton app=QApplication(sys.argv) button=QPushButton(None) button.setText(unicode("Merhaba Dünya")) app.setMainWidget(button) button.show() app.exec_loop()
def __init__(self, message, parent): QPushButton.__init__(self, parent) self.message = message self.client = parent.client self.setMinimumHeight(25) self.setText(message.buttonCaption())
class qSlicerMultiVolumeExplorerModuleWidget(qSlicerMultiVolumeExplorerSimplifiedModuleWidget): def __init__(self, parent=None): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.__init__(self, parent) def setupAdditionalFrames(self): self.setupPlotSettingsFrame() def setupInputFrame(self, parent=None): self.inputFrame = ctk.ctkCollapsibleButton() self.inputFrame.text = "Input" self.inputFrame.collapsed = 0 inputFrameCollapsibleLayout = QFormLayout(self.inputFrame) qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupInputFrame(self, parent=inputFrameCollapsibleLayout) self.layout.addWidget(self.inputFrame) self.fgMultiVolumeSelector = slicer.qMRMLNodeComboBox() self.fgMultiVolumeSelector.nodeTypes = ['vtkMRMLMultiVolumeNode'] self.fgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene) self.fgMultiVolumeSelector.addEnabled = 0 self.fgMultiVolumeSelector.noneEnabled = 1 self.fgMultiVolumeSelector.toolTip = "Secondary multivolume will be used for the secondary \ plot in interactive charting. As an example, this can be used to overlay the \ curve obtained by fitting a model to the data" self.inputFrameLayout.addRow(QLabel('Input secondary multivolume'), self.fgMultiVolumeSelector) def setupFrameControlFrame(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupFrameControlFrame(self) self.frameCopySelector = slicer.qMRMLNodeComboBox() self.frameCopySelector.nodeTypes = ['vtkMRMLScalarVolumeNode'] self.frameCopySelector.setMRMLScene(slicer.mrmlScene) self.frameCopySelector.addEnabled = 1 self.frameCopySelector.enabled = 0 # do not show "children" of vtkMRMLScalarVolumeNode self.frameCopySelector.hideChildNodeTypes = ["vtkMRMLDiffusionWeightedVolumeNode", "vtkMRMLDiffusionTensorVolumeNode", "vtkMRMLVectorVolumeNode"] self.extractFrameCopy = False self.extractFrameCheckBox = QCheckBox('Enable copying') hbox = QHBoxLayout() hbox.addWidget(QLabel('Current frame copy')) hbox.addWidget(self.frameCopySelector) hbox.addWidget(self.extractFrameCheckBox) self.inputFrameLayout.addRow(hbox) def setupPlotSettingsFrame(self): self.plotSettingsFrame = ctk.ctkCollapsibleButton() self.plotSettingsFrame.text = "Plotting Settings" self.plotSettingsFrame.collapsed = 1 plotSettingsFrameLayout = QFormLayout(self.plotSettingsFrame) self.layout.addWidget(self.plotSettingsFrame) # label map for probing self.labelMapSelector = slicer.qMRMLNodeComboBox() self.labelMapSelector.nodeTypes = ['vtkMRMLLabelMapVolumeNode'] self.labelMapSelector.toolTip = 'Label map to be probed' self.labelMapSelector.setMRMLScene(slicer.mrmlScene) self.labelMapSelector.addEnabled = 0 self.chartButton = QPushButton('Chart') self.chartButton.setEnabled(False) hbox = QHBoxLayout() hbox.addWidget(QLabel('Probed label volume')) hbox.addWidget(self.labelMapSelector) hbox.addWidget(self.chartButton) plotSettingsFrameLayout.addRow(hbox) self.iCharting = QCheckBox('Interactive charting') self.iCharting.setChecked(True) plotSettingsFrameLayout.addRow(self.iCharting) self.iChartingMode = QButtonGroup() self.iChartingIntensity = QRadioButton('Signal intensity') self.iChartingIntensityFixedAxes = QRadioButton('Fixed range intensity') self.iChartingPercent = QRadioButton('Percentage change') self.iChartingIntensity.setChecked(1) self.iChartingMode.addButton(self.iChartingIntensity) self.iChartingMode.addButton(self.iChartingIntensityFixedAxes) self.iChartingMode.addButton(self.iChartingPercent) hbox = QHBoxLayout() self.plottingModeGroupBox = QGroupBox('Plotting mode:') plottingModeLayout = QVBoxLayout() self.plottingModeGroupBox.setLayout(plottingModeLayout) plottingModeLayout.addWidget(self.iChartingIntensity) plottingModeLayout.addWidget(self.iChartingIntensityFixedAxes) plottingModeLayout.addWidget(self.iChartingPercent) hbox.addWidget(self.plottingModeGroupBox) self.showLegendCheckBox = QCheckBox('Display legend') self.showLegendCheckBox.setChecked(0) self.xLogScaleCheckBox = QCheckBox('Use log scale for X axis') self.xLogScaleCheckBox.setChecked(0) self.yLogScaleCheckBox = QCheckBox('Use log scale for Y axis') self.yLogScaleCheckBox.setChecked(0) self.plotGeneralSettingsGroupBox = QGroupBox('General Plot options:') plotGeneralSettingsLayout = QVBoxLayout() self.plotGeneralSettingsGroupBox.setLayout(plotGeneralSettingsLayout) plotGeneralSettingsLayout.addWidget(self.showLegendCheckBox) plotGeneralSettingsLayout.addWidget(self.xLogScaleCheckBox) plotGeneralSettingsLayout.addWidget(self.yLogScaleCheckBox) hbox.addWidget(self.plotGeneralSettingsGroupBox) plotSettingsFrameLayout.addRow(hbox) self.nFramesBaselineCalculation = QSpinBox() self.nFramesBaselineCalculation.minimum = 1 hbox = QHBoxLayout() hbox.addWidget(QLabel('Frame count(baseline calculation):')) hbox.addWidget(self.nFramesBaselineCalculation) plotSettingsFrameLayout.addRow(hbox) def setupPlottingFrame(self, parent=None): self.plotFrame = ctk.ctkCollapsibleButton() self.plotFrame.text = "Plotting" self.plotFrame.collapsed = 0 plotFrameLayout = QGridLayout(self.plotFrame) self.layout.addWidget(self.plotFrame) qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupPlottingFrame(self, parent=plotFrameLayout) def onDockChartViewToggled(self, checked): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.onDockChartViewToggled(self, checked) if checked: self.layout.removeWidget(self.plotFrame) self.plotFrame.hide() def dockChartView(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.dockChartView(self) self.layout.addWidget(self.plotFrame) self.plotFrame.show() def setFramesEnabled(self, enabled): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setFramesEnabled(self, enabled) self.plotSettingsFrame.setEnabled(enabled) self.plotFrame.setEnabled(enabled) self.plotFrame.collapsed = 0 if enabled else 1 def setupConnections(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupConnections(self) self.labelMapSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onLabelNodeChanged) self.chartButton.connect('clicked()', self.onLabeledChartRequested) self.xLogScaleCheckBox.connect('stateChanged(int)', self.onXLogScaleRequested) self.yLogScaleCheckBox.connect('stateChanged(int)', self.onYLogScaleRequested) self.nFramesBaselineCalculation.valueChanged.connect(self.onFrameCountBaselineCalculationChanged) self.iChartingMode.buttonClicked.connect(self.onChartingModeChanged) self.showLegendCheckBox.connect('stateChanged(int)', self.onShowLegendChanged) self.fgMultiVolumeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onForegroundInputChanged) self.extractFrameCheckBox.connect('stateChanged(int)', self.onExtractFrameChanged) self.frameCopySelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVFMRMLSceneChanged) def onFrameCountBaselineCalculationChanged(self, value): self._multiVolumeIntensityChart.nFramesForBaselineCalculation = value def onChartingModeChanged(self, button): if button is self.iChartingIntensity: self._multiVolumeIntensityChart.activateSignalIntensityMode() elif button is self.iChartingIntensityFixedAxes: self._multiVolumeIntensityChart.activateFixedRangeIntensityMode() elif button is self.iChartingPercent: self._multiVolumeIntensityChart.activatePercentageChangeMode() def onShowLegendChanged(self, checked): self._multiVolumeIntensityChart.showLegend = True if checked == 2 else False def onXLogScaleRequested(self, checked): self._multiVolumeIntensityChart.showXLogScale = True if checked == 2 else False def onYLogScaleRequested(self, checked): self._multiVolumeIntensityChart.showYLogScale = True if checked == 2 else False def onLVMRMLSceneChanged(self, mrmlScene): self.labelMapSelector.setMRMLScene(slicer.mrmlScene) def onVFMRMLSceneChanged(self, mrmlScene): self.frameCopySelector.setMRMLScene(slicer.mrmlScene) def onLabelNodeChanged(self): labelNode = self.labelMapSelector.currentNode() self.chartButton.setEnabled(labelNode is not None and self._bgMultiVolumeNode is not None) def onForegroundInputChanged(self): logging.info("qSlicerMultiVolumeExplorerModuleWidget:ForegroundInputChanged") self._fgMultiVolumeNode = self.fgMultiVolumeSelector.currentNode() self._multiVolumeIntensityChart.fgMultiVolumeNode = self.fgMultiVolumeSelector.currentNode() self.refreshGUIForNewBackgroundImage() def onBackgroundInputChanged(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.onBackgroundInputChanged(self) if self._bgMultiVolumeNode is not None: self.frameCopySelector.setCurrentNode(None) self.nFramesBaselineCalculation.maximum = self._bgMultiVolumeNode.GetNumberOfFrames() self.onLabelNodeChanged() ''' If extract button is checked, will copy the current frame to the selected volume node on each event from frame slider ''' def onExtractFrameChanged(self, checked): if checked: self.extractFrameCopy = True self.onSliderChanged(self.frameSlider.value) else: self.extractFrameCopy = False def onSliderChanged(self, frameId): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.onSliderChanged(self, frameId) frameId = int(frameId) if self.extractFrameCopy: frameVolume = self.frameCopySelector.currentNode() frameVolumeCopy = Helper.extractFrame(frameVolume, self._bgMultiVolumeNode, frameId) if not frameVolume: self.frameCopySelector.setCurrentNode(frameVolumeCopy) frameName = '%s frame %d' % (self._bgMultiVolumeNode.GetName(), frameId) frameVolumeCopy.SetName(frameName) def onLabeledChartRequested(self): labelNode = self.labelMapSelector.currentNode() mvNode = self._bgMultiVolumeNode mvLabels = MultiVolumeIntensityChartView.getMultiVolumeLabels(self._bgMultiVolumeNode) chartViewNode = LabeledImageChartView(labelNode=labelNode, multiVolumeNode=mvNode, multiVolumeLabels=mvLabels, baselineFrames=self.nFramesBaselineCalculation, displayPercentageChange=self.iChartingPercent.checked) chartViewNode.requestChartCreation() def processEvent(self, observee, event): if not self.iCharting.checked: return qSlicerMultiVolumeExplorerSimplifiedModuleWidget.processEvent(self, observee, event)
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
class SelectorElementosEstudio(QWidget): """Clase padre de los selectores. Los selectores permiten elegir una o más variables, o una variable y un valor de esa variable, etc Las clases hijas deben suministrar cajadisponible,addelemento SelectorElementosEstudios tiene siempre una caja donde aparecen los resultados a la derecha, y provee los botones de adicion y sustracción de elementos """ def __init__(self, interfazdato, cajadisponible): """Caja disponible son los elementos que aparecen a la izquierda en el selector""" #VARIABLES PUBLICAS QWidget.__init__(self, None, "selector", 0) image1 = QPixmap(IMAGE1DATA) image2 = QPixmap(IMAGE2DATA) selectorsimplelayout = QHBoxLayout(self, 11, 6, "WSelectorSimpleLayout") layout2 = QVBoxLayout(None, 0, 6, "layout2") widgetstack1 = QWidgetStack(self, "staaack") widgetstack1.addWidget(cajadisponible) widgetstack1.raiseWidget(cajadisponible) widgetstack1.setSizePolicy(QSizePolicy(\ QSizePolicy.Expanding, QSizePolicy.Expanding, \ 0, 0, widgetstack1.sizePolicy().hasHeightForWidth())) self._cajadisponible = cajadisponible layout2.addWidget(widgetstack1) selectorsimplelayout.addLayout(layout2) layout1 = QVBoxLayout(None, 0, 6, "layout1") self.__pushbutton1 = QPushButton(self, "pushButton1") self.__pushbutton1.setMaximumSize(QSize(30, 30)) self.__pushbutton1.setPixmap(image1) layout1.addWidget(self.__pushbutton1) spacer1 = QSpacerItem(30, 122, QSizePolicy.Minimum, QSizePolicy.Expanding) layout1.addItem(spacer1) self.__pushbutton2 = QPushButton(self,"pushButton2") self.__pushbutton2.setMaximumSize(QSize(30, 30)) self.__pushbutton2.setPixmap(image2) self.__pushbutton2.setAccel("Del") layout1.addWidget(self.__pushbutton2) selectorsimplelayout.addLayout(layout1) layout3 = QVBoxLayout(None, 0, 6, "layout3") self._textlabel2 = QLabel(self, "textLabel2") layout3.addWidget(self._textlabel2) self._cajaseleccion = QListBox(self,"cajaseleccion") self._cajaseleccion.setMinimumSize(QSize(0, 60)) layout3.addWidget(self._cajaseleccion) selectorsimplelayout.addLayout(layout3) self._cajaseleccion.setSizePolicy(QSizePolicy(\ QSizePolicy.Expanding,QSizePolicy.Expanding, 0, 0, \ self._cajaseleccion.sizePolicy().hasHeightForWidth())) self.setCaption("Form1") self._textlabel2.setText(u"Selección") self.resize(QSize(294, 240).expandedTo(self.minimumSizeHint())) self.clearWState(Qt.WState_Polished) self.__conexiones() #Miembros !qt self.seleccion = [] self._dato = interfazdato def showEvent(self, event): """Redefinicion showEvent""" self._actualizar_cajas() QWidget.showEvent(self, event) def _actualizar_cajas(self): """Actualiza el contenido de las cajas""" self._cajaseleccion.clear() for valor in self.seleccion: self._cajaseleccion.insertItem(str(valor)) self._actualizar_caja_disponible() def __conexiones(self): """Establece las conexiones entre elementos""" self.connect(self.__pushbutton1, SIGNAL("clicked()"), self._anadir_elemento) self.connect(self.__pushbutton2, SIGNAL("clicked()"), self.__borrar_elemento) def __borrar_elemento(self): """Borra el elemento seleccionado en lacaja de seleccion""" if self._cajaseleccion.currentText(): del self.seleccion[self._cajaseleccion.currentItem()] self._actualizar_cajas()
def setupPlotSettingsFrame(self): self.plotSettingsFrame = ctk.ctkCollapsibleButton() self.plotSettingsFrame.text = "Plotting Settings" self.plotSettingsFrame.collapsed = 1 plotSettingsFrameLayout = QFormLayout(self.plotSettingsFrame) self.layout.addWidget(self.plotSettingsFrame) # label map for probing self.labelMapSelector = slicer.qMRMLNodeComboBox() self.labelMapSelector.nodeTypes = ['vtkMRMLLabelMapVolumeNode'] self.labelMapSelector.toolTip = 'Label map to be probed' self.labelMapSelector.setMRMLScene(slicer.mrmlScene) self.labelMapSelector.addEnabled = 0 self.chartButton = QPushButton('Chart') self.chartButton.setEnabled(False) hbox = QHBoxLayout() hbox.addWidget(QLabel('Probed label volume')) hbox.addWidget(self.labelMapSelector) hbox.addWidget(self.chartButton) plotSettingsFrameLayout.addRow(hbox) self.iCharting = QCheckBox('Interactive charting') self.iCharting.setChecked(True) plotSettingsFrameLayout.addRow(self.iCharting) self.iChartingMode = QButtonGroup() self.iChartingIntensity = QRadioButton('Signal intensity') self.iChartingIntensityFixedAxes = QRadioButton( 'Fixed range intensity') self.iChartingPercent = QRadioButton('Percentage change') self.iChartingIntensity.setChecked(1) self.iChartingMode.addButton(self.iChartingIntensity) self.iChartingMode.addButton(self.iChartingIntensityFixedAxes) self.iChartingMode.addButton(self.iChartingPercent) hbox = QHBoxLayout() self.plottingModeGroupBox = QGroupBox('Plotting mode:') plottingModeLayout = QVBoxLayout() self.plottingModeGroupBox.setLayout(plottingModeLayout) plottingModeLayout.addWidget(self.iChartingIntensity) plottingModeLayout.addWidget(self.iChartingIntensityFixedAxes) plottingModeLayout.addWidget(self.iChartingPercent) hbox.addWidget(self.plottingModeGroupBox) self.showLegendCheckBox = QCheckBox('Display legend') self.showLegendCheckBox.setChecked(0) self.xLogScaleCheckBox = QCheckBox('Use log scale for X axis') self.xLogScaleCheckBox.setChecked(0) self.yLogScaleCheckBox = QCheckBox('Use log scale for Y axis') self.yLogScaleCheckBox.setChecked(0) self.plotGeneralSettingsGroupBox = QGroupBox('General Plot options:') plotGeneralSettingsLayout = QVBoxLayout() self.plotGeneralSettingsGroupBox.setLayout(plotGeneralSettingsLayout) plotGeneralSettingsLayout.addWidget(self.showLegendCheckBox) plotGeneralSettingsLayout.addWidget(self.xLogScaleCheckBox) plotGeneralSettingsLayout.addWidget(self.yLogScaleCheckBox) hbox.addWidget(self.plotGeneralSettingsGroupBox) plotSettingsFrameLayout.addRow(hbox) self.nFramesBaselineCalculation = QSpinBox() self.nFramesBaselineCalculation.minimum = 1 hbox = QHBoxLayout() hbox.addWidget(QLabel('Frame count(baseline calculation):')) hbox.addWidget(self.nFramesBaselineCalculation) plotSettingsFrameLayout.addRow(hbox)
class ProstateTRUSNavWidget(GuideletWidget): DEFAULT_PLUSSERVER_CHOOSER_TEXT = "Choose PlusServer.exe" DEFAULT_CONFIGURATION_CHOOSER_TEXT = "Select Configuration" def __init__(self, parent = None): GuideletWidget.__init__(self, parent) self.plusServerProcess = None self.configurationFile = self.getSetting('ConfigurationFile', self.DEFAULT_CONFIGURATION_CHOOSER_TEXT) self.serverExecutable = self.getSetting('PlusServer', self.DEFAULT_PLUSSERVER_CHOOSER_TEXT) def cleanup(self): GuideletWidget.cleanup(self) if self.plusServerProcess: self.plusServerProcess.terminate() def setup(self): showPlusServerWidget = True if _platform == "linux" or _platform == "linux2" or _platform == "darwin": #linux or linux or OS X message = "Attention: You are running Slicer on Linux or OS X. Do you have PlusServer installed on the current OS?" result = QMessageBox.question(slicer.util.mainWindow(), 'ProstateTRUSNav', message, QMessageBox.Yes | QMessageBox.No) showPlusServerWidget = result == QMessageBox.Yes if _platform == "win32" or showPlusServerWidget: # Windows... plusServerCollapsibleButton = ctkCollapsibleButton() plusServerCollapsibleButton.text = "PlusServer" self.layout.addWidget(plusServerCollapsibleButton) self.configurationFileChooserButton = QPushButton(self.configurationFile) self.configurationFileChooserButton.connect('clicked()', self.onConfigFileSelected) self.runPlusServerButton = QPushButton("Run PlusServer") self.runPlusServerButton.setCheckable(True) self.runPlusServerButton.connect('clicked()', self.onRunPlusServerButtonClicked) self.serverFormLayout = QFormLayout(plusServerCollapsibleButton) self.serverExecutableChooserButton = QPushButton(self.serverExecutable) self.serverExecutableChooserButton.connect('clicked()', self.onServerExecutableSelected) hbox = QHBoxLayout() hbox.addWidget(self.serverExecutableChooserButton) self.serverFormLayout.addRow(hbox) hbox = QHBoxLayout() hbox.addWidget(self.configurationFileChooserButton) hbox.addWidget(self.runPlusServerButton) self.serverFormLayout.addRow(hbox) GuideletWidget.setup(self) # do specific setup here if _platform == "win32" or showPlusServerWidget: self.launchGuideletButton.setEnabled(False) self.checkExecutableAndArgument() def checkExecutableAndArgument(self): if os.path.exists(self.serverExecutable) and os.path.exists(self.configurationFile): self.runPlusServerButton.setEnabled(True) else: self.runPlusServerButton.setEnabled(False) def getSetting(self, settingName, defaultValue=""): settings = QSettings() value = settings.value(self.moduleName + '/' + settingName, defaultValue) return value if value is not None and value != "" else defaultValue def setSetting(self, settingName, value): settings = QSettings() settings.setValue(self.moduleName + '/'+ settingName, value) def addLauncherWidgets(self): GuideletWidget.addLauncherWidgets(self) # add launcher widget here def onServerExecutableSelected(self): executable = QFileDialog.getOpenFileName(self.parent, "PlusServer Executable", self.serverExecutable, "*.exe") if executable != "" and executable.find("PlusServer.exe"): self.serverExecutable = executable self.serverExecutableChooserButton.setText(executable) self.setSetting("PlusServer", executable) self.checkExecutableAndArgument() def onConfigFileSelected(self): self.configurationFile = QFileDialog.getOpenFileName(self.parent, "Choose Configuration File", self.configurationFile, "*.xml") if self.configurationFile != "": self.configurationFileChooserButton.setText(os.path.split(self.configurationFile)[1]) self.setSetting("ConfigurationFile", self.configurationFile) self.checkExecutableAndArgument() def onRunPlusServerButtonClicked(self): if self.runPlusServerButton.isChecked(): command = [self.serverExecutable, "--config-file="+self.configurationFile] logging.info("Executing %s %s" % tuple(command)) self.plusServerProcess = Popen([self.serverExecutable, "--config-file="+self.configurationFile]) if self.plusServerProcess: self.runPlusServerButton.setText("Quit Plus Server") self.launchGuideletButton.setEnabled(True) else: if self.plusServerProcess: self.plusServerProcess.terminate() self.runPlusServerButton.setText("Run PlusServer") self.launchGuideletButton.setEnabled(False) def collectParameterList(self): parameterList = GuideletWidget.collectParameterList(self) if not parameterList: parameterList = dict() parameterList['OfflineVolumeToReconstruct'] = 0, return parameterList def createGuideletInstance(self, parameterList = None): return ProstateTRUSNavGuidelet(None, self.guideletLogic, parameterList) def createGuideletLogic(self): return ProstateTRUSNavLogic()
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())
def __init__(self, message, parent): QPushButton.__init__(self, parent) self.message = message self.client = parent.client self.setText(message.buttonCaption())
class ScoringDialog(QWidget): """a dialog for entering the scores""" # pylint: disable=too-many-instance-attributes def __init__(self, scene): QWidget.__init__(self) self.scene = scene decorateWindow(self, m18n("Scoring for this Hand")) self.nameLabels = [None] * 4 self.spValues = [None] * 4 self.windLabels = [None] * 4 self.wonBoxes = [None] * 4 self.detailsLayout = [None] * 4 self.details = [None] * 4 self.__tilePixMaps = [] self.__meldPixMaps = [] grid = QGridLayout(self) pGrid = QGridLayout() grid.addLayout(pGrid, 0, 0, 2, 1) pGrid.addWidget(QLabel(m18nc("kajongg", "Player")), 0, 0) pGrid.addWidget(QLabel(m18nc("kajongg", "Wind")), 0, 1) pGrid.addWidget(QLabel(m18nc("kajongg", "Score")), 0, 2) pGrid.addWidget(QLabel(m18n("Winner")), 0, 3) self.detailTabs = QTabWidget() self.detailTabs.setDocumentMode(True) pGrid.addWidget(self.detailTabs, 0, 4, 8, 1) for idx in range(4): self.setupUiForPlayer(pGrid, idx) self.draw = QCheckBox(m18nc("kajongg", "Draw")) self.draw.clicked.connect(self.wonChanged) btnPenalties = QPushButton(m18n("&Penalties")) btnPenalties.clicked.connect(self.penalty) self.btnSave = QPushButton(m18n("&Save Hand")) self.btnSave.clicked.connect(self.game.nextScoringHand) self.btnSave.setEnabled(False) self.setupUILastTileMeld(pGrid) pGrid.setRowStretch(87, 10) pGrid.addWidget(self.draw, 7, 3) self.cbLastTile.currentIndexChanged.connect(self.slotLastTile) self.cbLastMeld.currentIndexChanged.connect(self.slotInputChanged) btnBox = QHBoxLayout() btnBox.addWidget(btnPenalties) btnBox.addWidget(self.btnSave) pGrid.addLayout(btnBox, 8, 4) StateSaver(self) self.refresh() @property def game(self): """proxy""" return self.scene.game def setupUILastTileMeld(self, pGrid): """setup UI elements for last tile and last meld""" self.lblLastTile = QLabel(m18n("&Last Tile:")) self.cbLastTile = QComboBox() self.cbLastTile.setMinimumContentsLength(1) vpol = QSizePolicy() vpol.setHorizontalPolicy(QSizePolicy.Fixed) self.cbLastTile.setSizePolicy(vpol) self.cbLastTile.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLengthWithIcon) self.lblLastTile.setBuddy(self.cbLastTile) self.lblLastMeld = QLabel(m18n("L&ast Meld:")) self.prevLastTile = None self.cbLastMeld = QComboBox() self.cbLastMeld.setMinimumContentsLength(1) self.cbLastMeld.setSizePolicy(vpol) self.cbLastMeld.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLengthWithIcon) self.lblLastMeld.setBuddy(self.cbLastMeld) self.comboTilePairs = set() pGrid.setRowStretch(6, 5) pGrid.addWidget(self.lblLastTile, 7, 0, 1, 2) pGrid.addWidget(self.cbLastTile, 7, 2, 1, 1) pGrid.addWidget(self.lblLastMeld, 8, 0, 1, 2) pGrid.addWidget(self.cbLastMeld, 8, 2, 1, 2) def setupUiForPlayer(self, pGrid, idx): """setup UI elements for a player""" self.spValues[idx] = QSpinBox() self.nameLabels[idx] = QLabel() self.nameLabels[idx].setBuddy(self.spValues[idx]) self.windLabels[idx] = WindLabel() pGrid.addWidget(self.nameLabels[idx], idx + 2, 0) pGrid.addWidget(self.windLabels[idx], idx + 2, 1) pGrid.addWidget(self.spValues[idx], idx + 2, 2) self.wonBoxes[idx] = QCheckBox("") pGrid.addWidget(self.wonBoxes[idx], idx + 2, 3) self.wonBoxes[idx].clicked.connect(self.wonChanged) self.spValues[idx].valueChanged.connect(self.slotInputChanged) detailTab = QWidget() self.detailTabs.addTab(detailTab, "") self.details[idx] = QWidget() detailTabLayout = QVBoxLayout(detailTab) detailTabLayout.addWidget(self.details[idx]) detailTabLayout.addStretch() self.detailsLayout[idx] = QVBoxLayout(self.details[idx]) def refresh(self): """reload game""" self.clear() game = self.game self.setVisible(game is not None and not game.finished()) if game: for idx, player in enumerate(game.players): for child in self.details[idx].children(): if isinstance(child, RuleBox): child.hide() self.detailsLayout[idx].removeWidget(child) del child if game: self.spValues[idx].setRange(0, game.ruleset.limit or 99999) self.nameLabels[idx].setText(player.localName) self.windLabels[idx].wind = player.wind self.windLabels[idx].roundsFinished = game.roundsFinished self.detailTabs.setTabText(idx, player.localName) player.manualRuleBoxes = [RuleBox(x) for x in game.ruleset.allRules if x.hasSelectable] for ruleBox in player.manualRuleBoxes: self.detailsLayout[idx].addWidget(ruleBox) ruleBox.clicked.connect(self.slotInputChanged) player.refreshManualRules() def show(self): """only now compute content""" if self.game and not self.game.finished(): self.slotInputChanged() QWidget.show(self) def penalty(self): """penalty button clicked""" dlg = PenaltyDialog(self.game) dlg.exec_() def slotLastTile(self): """called when the last tile changes""" newLastTile = self.computeLastTile() if not newLastTile: return if self.prevLastTile and self.prevLastTile.isExposed != newLastTile.isExposed: # state of last tile (concealed/exposed) changed: # for all checked boxes check if they still are applicable winner = self.game.winner if winner: for box in winner.manualRuleBoxes: if box.isChecked(): box.setChecked(False) if winner.hand.manualRuleMayApply(box.rule): box.setChecked(True) self.prevLastTile = newLastTile self.fillLastMeldCombo() self.slotInputChanged() def computeLastTile(self): """returns the currently selected last tile""" idx = self.cbLastTile.currentIndex() if idx >= 0: return variantValue(self.cbLastTile.itemData(idx)) def clickedPlayerIdx(self, checkbox): """the player whose box has been clicked""" for idx in range(4): if checkbox == self.wonBoxes[idx]: return idx assert False def wonChanged(self): """if a new winner has been defined, uncheck any previous winner""" newWinner = None if self.sender() != self.draw: clicked = self.clickedPlayerIdx(self.sender()) if self.wonBoxes[clicked].isChecked(): newWinner = self.game.players[clicked] else: newWinner = None self.game.winner = newWinner for idx in range(4): if newWinner != self.game.players[idx]: self.wonBoxes[idx].setChecked(False) if newWinner: self.draw.setChecked(False) self.fillLastTileCombo() self.slotInputChanged() def updateManualRules(self): """enable/disable them""" # if an exclusive rule has been activated, deactivate it for # all other players ruleBox = self.sender() if isinstance(ruleBox, RuleBox) and ruleBox.isChecked() and ruleBox.rule.exclusive(): for idx, player in enumerate(self.game.players): if ruleBox.parentWidget() != self.details[idx]: for pBox in player.manualRuleBoxes: if pBox.rule.name == ruleBox.rule.name: pBox.setChecked(False) try: newState = bool(self.game.winner.handBoard.uiTiles) except AttributeError: newState = False self.lblLastTile.setEnabled(newState) self.cbLastTile.setEnabled(newState) self.lblLastMeld.setEnabled(newState) self.cbLastMeld.setEnabled(newState) if self.game: for player in self.game.players: player.refreshManualRules(self.sender()) def clear(self): """prepare for next hand""" if self.game: for idx, player in enumerate(self.game.players): self.spValues[idx].clear() self.spValues[idx].setValue(0) self.wonBoxes[idx].setChecked(False) player.payment = 0 player.invalidateHand() for box in self.wonBoxes: box.setVisible(False) self.draw.setChecked(False) self.updateManualRules() if self.game is None: self.hide() else: for idx, player in enumerate(self.game.players): self.windLabels[idx].setPixmap(WINDPIXMAPS[(player.wind, player.wind == self.game.roundWind)]) self.computeScores() self.spValues[0].setFocus() self.spValues[0].selectAll() def computeScores(self): """if tiles have been selected, compute their value""" # pylint: disable=too-many-branches # too many branches if not self.game: return if self.game.finished(): self.hide() return for nameLabel, wonBox, spValue, player in zip(self.nameLabels, self.wonBoxes, self.spValues, self.game.players): with BlockSignals([spValue, wonBox]): # we do not want that change to call computeScores again if player.handBoard and player.handBoard.uiTiles: spValue.setEnabled(False) nameLabel.setBuddy(wonBox) for _ in range(10): prevTotal = player.handTotal player.invalidateHand() wonBox.setVisible(player.hand.won) if not wonBox.isVisibleTo(self) and wonBox.isChecked(): wonBox.setChecked(False) self.game.winner = None elif prevTotal == player.handTotal: break player.refreshManualRules() spValue.setValue(player.handTotal) else: if not spValue.isEnabled(): spValue.clear() spValue.setValue(0) spValue.setEnabled(True) nameLabel.setBuddy(spValue) wonBox.setVisible(player.handTotal >= self.game.ruleset.minMJTotal()) if not wonBox.isVisibleTo(self) and wonBox.isChecked(): wonBox.setChecked(False) if not wonBox.isVisibleTo(self) and player is self.game.winner: self.game.winner = None if Internal.scene.explainView: Internal.scene.explainView.refresh() def __lastMeldContent(self): """prepare content for lastmeld combo""" lastTiles = set() winnerTiles = [] if self.game.winner and self.game.winner.handBoard: winnerTiles = self.game.winner.handBoard.uiTiles pairs = [] for meld in self.game.winner.hand.melds: if len(meld) < 4: pairs.extend(meld) for tile in winnerTiles: if tile.tile in pairs and not tile.isBonus: lastTiles.add(tile.tile) return lastTiles, winnerTiles def __fillLastTileComboWith(self, lastTiles, winnerTiles): """fill last meld combo with prepared content""" self.comboTilePairs = lastTiles idx = self.cbLastTile.currentIndex() if idx < 0: idx = 0 indexedTile = variantValue(self.cbLastTile.itemData(idx)) restoredIdx = None self.cbLastTile.clear() if not winnerTiles: return pmSize = winnerTiles[0].board.tileset.faceSize pmSize = QSize(pmSize.width() * 0.5, pmSize.height() * 0.5) self.cbLastTile.setIconSize(pmSize) QPixmapCache.clear() self.__tilePixMaps = [] shownTiles = set() for tile in winnerTiles: if tile.tile in lastTiles and tile.tile not in shownTiles: shownTiles.add(tile.tile) self.cbLastTile.addItem(QIcon(tile.pixmapFromSvg(pmSize, withBorders=False)), "", toQVariant(tile.tile)) if indexedTile is tile.tile: restoredIdx = self.cbLastTile.count() - 1 if not restoredIdx and indexedTile: # try again, maybe the tile changed between concealed and exposed indexedTile = indexedTile.exposed for idx in range(self.cbLastTile.count()): if indexedTile is variantValue(self.cbLastTile.itemData(idx)).exposed: restoredIdx = idx break if not restoredIdx: restoredIdx = 0 self.cbLastTile.setCurrentIndex(restoredIdx) self.prevLastTile = self.computeLastTile() def clearLastTileCombo(self): """as the name says""" self.comboTilePairs = None self.cbLastTile.clear() def fillLastTileCombo(self): """fill the drop down list with all possible tiles. If the drop down had content before try to preserve the current index. Even if the tile changed state meanwhile.""" if self.game is None: return lastTiles, winnerTiles = self.__lastMeldContent() if self.comboTilePairs == lastTiles: return with BlockSignals(self.cbLastTile): # we only want to emit the changed signal once self.__fillLastTileComboWith(lastTiles, winnerTiles) self.cbLastTile.currentIndexChanged.emit(0) def __fillLastMeldComboWith(self, winnerMelds, indexedMeld, lastTile): """fill last meld combo with prepared content""" winner = self.game.winner faceWidth = winner.handBoard.tileset.faceSize.width() * 0.5 faceHeight = winner.handBoard.tileset.faceSize.height() * 0.5 restoredIdx = None for meld in winnerMelds: pixMap = QPixmap(faceWidth * len(meld), faceHeight) pixMap.fill(Qt.transparent) self.__meldPixMaps.append(pixMap) painter = QPainter(pixMap) for element in meld: painter.drawPixmap( 0, 0, winner.handBoard.tilesByElement(element)[0].pixmapFromSvg( QSize(faceWidth, faceHeight), withBorders=False ), ) painter.translate(QPointF(faceWidth, 0.0)) self.cbLastMeld.addItem(QIcon(pixMap), "", toQVariant(str(meld))) if indexedMeld == str(meld): restoredIdx = self.cbLastMeld.count() - 1 if not restoredIdx and indexedMeld: # try again, maybe the meld changed between concealed and exposed indexedMeld = indexedMeld.lower() for idx in range(self.cbLastMeld.count()): meldContent = str(variantValue(self.cbLastMeld.itemData(idx))) if indexedMeld == meldContent.lower(): restoredIdx = idx if lastTile not in meldContent: lastTile = lastTile.swapped assert lastTile in meldContent with BlockSignals(self.cbLastTile): # we want to continue right here idx = self.cbLastTile.findData(toQVariant(lastTile)) self.cbLastTile.setCurrentIndex(idx) break if not restoredIdx: restoredIdx = 0 self.cbLastMeld.setCurrentIndex(restoredIdx) self.cbLastMeld.setIconSize(QSize(faceWidth * 3, faceHeight)) def fillLastMeldCombo(self): """fill the drop down list with all possible melds. If the drop down had content before try to preserve the current index. Even if the meld changed state meanwhile.""" with BlockSignals(self.cbLastMeld): # we only want to emit the changed signal once showCombo = False idx = self.cbLastMeld.currentIndex() if idx < 0: idx = 0 indexedMeld = str(variantValue(self.cbLastMeld.itemData(idx))) self.cbLastMeld.clear() self.__meldPixMaps = [] if not self.game.winner: return if self.cbLastTile.count() == 0: return lastTile = Internal.scene.computeLastTile() winnerMelds = [m for m in self.game.winner.hand.melds if len(m) < 4 and lastTile in m] assert len(winnerMelds), "lastTile %s missing in %s" % (lastTile, self.game.winner.hand.melds) if len(winnerMelds) == 1: self.cbLastMeld.addItem(QIcon(), "", toQVariant(str(winnerMelds[0]))) self.cbLastMeld.setCurrentIndex(0) return showCombo = True self.__fillLastMeldComboWith(winnerMelds, indexedMeld, lastTile) self.lblLastMeld.setVisible(showCombo) self.cbLastMeld.setVisible(showCombo) self.cbLastMeld.currentIndexChanged.emit(0) def slotInputChanged(self): """some input fields changed: update""" for player in self.game.players: player.invalidateHand() self.updateManualRules() self.computeScores() self.validate() for player in self.game.players: self.game.wall.decoratePlayer(player) Internal.mainWindow.updateGUI() def validate(self): """update the status of the OK button""" game = self.game if game: valid = True if game.winner and game.winner.handTotal < game.ruleset.minMJTotal(): valid = False elif not game.winner and not self.draw.isChecked(): valid = False self.btnSave.setEnabled(valid)
class ScoringDialog(QWidget): """a dialog for entering the scores""" # pylint: disable=too-many-instance-attributes def __init__(self, scene): QWidget.__init__(self) self.scene = scene decorateWindow(self, i18n('Scoring for this Hand')) self.nameLabels = [None] * 4 self.spValues = [None] * 4 self.windLabels = [None] * 4 self.wonBoxes = [None] * 4 self.detailsLayout = [None] * 4 self.details = [None] * 4 self.__tilePixMaps = [] self.__meldPixMaps = [] grid = QGridLayout(self) pGrid = QGridLayout() grid.addLayout(pGrid, 0, 0, 2, 1) pGrid.addWidget(QLabel(i18nc('kajongg', "Player")), 0, 0) pGrid.addWidget(QLabel(i18nc('kajongg', "Wind")), 0, 1) pGrid.addWidget(QLabel(i18nc('kajongg', 'Score')), 0, 2) pGrid.addWidget(QLabel(i18n("Winner")), 0, 3) self.detailTabs = QTabWidget() self.detailTabs.setDocumentMode(True) pGrid.addWidget(self.detailTabs, 0, 4, 8, 1) for idx in range(4): self.setupUiForPlayer(pGrid, idx) self.draw = QCheckBox(i18nc('kajongg', 'Draw')) self.draw.clicked.connect(self.wonChanged) btnPenalties = QPushButton(i18n("&Penalties")) btnPenalties.clicked.connect(self.penalty) self.btnSave = QPushButton(i18n('&Save Hand')) self.btnSave.clicked.connect(self.game.nextScoringHand) self.btnSave.setEnabled(False) self.setupUILastTileMeld(pGrid) pGrid.setRowStretch(87, 10) pGrid.addWidget(self.draw, 7, 3) self.cbLastTile.currentIndexChanged.connect(self.slotLastTile) self.cbLastMeld.currentIndexChanged.connect(self.slotInputChanged) btnBox = QHBoxLayout() btnBox.addWidget(btnPenalties) btnBox.addWidget(self.btnSave) pGrid.addLayout(btnBox, 8, 4) StateSaver(self) self.refresh() @property def game(self): """proxy""" return self.scene.game def setupUILastTileMeld(self, pGrid): """setup UI elements for last tile and last meld""" self.lblLastTile = QLabel(i18n('&Last Tile:')) self.cbLastTile = QComboBox() self.cbLastTile.setMinimumContentsLength(1) vpol = QSizePolicy() vpol.setHorizontalPolicy(QSizePolicy.Fixed) self.cbLastTile.setSizePolicy(vpol) self.cbLastTile.setSizeAdjustPolicy( QComboBox.AdjustToMinimumContentsLengthWithIcon) self.lblLastTile.setBuddy(self.cbLastTile) self.lblLastMeld = QLabel(i18n('L&ast Meld:')) self.prevLastTile = None self.cbLastMeld = QComboBox() self.cbLastMeld.setMinimumContentsLength(1) self.cbLastMeld.setSizePolicy(vpol) self.cbLastMeld.setSizeAdjustPolicy( QComboBox.AdjustToMinimumContentsLengthWithIcon) self.lblLastMeld.setBuddy(self.cbLastMeld) self.comboTilePairs = set() pGrid.setRowStretch(6, 5) pGrid.addWidget(self.lblLastTile, 7, 0, 1, 2) pGrid.addWidget(self.cbLastTile, 7, 2, 1, 1) pGrid.addWidget(self.lblLastMeld, 8, 0, 1, 2) pGrid.addWidget(self.cbLastMeld, 8, 2, 1, 2) def setupUiForPlayer(self, pGrid, idx): """setup UI elements for a player""" self.spValues[idx] = QSpinBox() self.nameLabels[idx] = QLabel() self.nameLabels[idx].setBuddy(self.spValues[idx]) self.windLabels[idx] = WindLabel() pGrid.addWidget(self.nameLabels[idx], idx + 2, 0) pGrid.addWidget(self.windLabels[idx], idx + 2, 1) pGrid.addWidget(self.spValues[idx], idx + 2, 2) self.wonBoxes[idx] = QCheckBox("") pGrid.addWidget(self.wonBoxes[idx], idx + 2, 3) self.wonBoxes[idx].clicked.connect(self.wonChanged) self.spValues[idx].valueChanged.connect(self.slotInputChanged) detailTab = QWidget() self.detailTabs.addTab(detailTab, '') self.details[idx] = QWidget() detailTabLayout = QVBoxLayout(detailTab) detailTabLayout.addWidget(self.details[idx]) detailTabLayout.addStretch() self.detailsLayout[idx] = QVBoxLayout(self.details[idx]) def refresh(self): """reload game""" self.clear() game = self.game self.setVisible(game is not None and not game.finished()) if game: for idx, player in enumerate(game.players): for child in self.details[idx].children(): if isinstance(child, RuleBox): child.hide() self.detailsLayout[idx].removeWidget(child) del child if game: self.spValues[idx].setRange(0, game.ruleset.limit or 99999) self.nameLabels[idx].setText(player.localName) self.refreshWindLabels() self.detailTabs.setTabText(idx, player.localName) player.manualRuleBoxes = [ RuleBox(x) for x in game.ruleset.allRules if x.hasSelectable ] for ruleBox in player.manualRuleBoxes: self.detailsLayout[idx].addWidget(ruleBox) ruleBox.clicked.connect(self.slotInputChanged) player.refreshManualRules() def show(self): """only now compute content""" if self.game and not self.game.finished(): self.slotInputChanged() QWidget.show(self) def penalty(self): """penalty button clicked""" dlg = PenaltyDialog(self.game) dlg.exec_() def slotLastTile(self): """called when the last tile changes""" newLastTile = self.computeLastTile() if not newLastTile: return if self.prevLastTile and self.prevLastTile.isExposed != newLastTile.isExposed: # state of last tile (concealed/exposed) changed: # for all checked boxes check if they still are applicable winner = self.game.winner if winner: for box in winner.manualRuleBoxes: if box.isChecked(): box.setChecked(False) if winner.hand.manualRuleMayApply(box.rule): box.setChecked(True) self.prevLastTile = newLastTile self.fillLastMeldCombo() self.slotInputChanged() def computeLastTile(self): """returns the currently selected last tile""" idx = self.cbLastTile.currentIndex() if idx >= 0: return self.cbLastTile.itemData(idx) def clickedPlayerIdx(self, checkbox): """the player whose box has been clicked""" for idx in range(4): if checkbox == self.wonBoxes[idx]: return idx assert False def wonChanged(self): """if a new winner has been defined, uncheck any previous winner""" newWinner = None if self.sender() != self.draw: clicked = self.clickedPlayerIdx(self.sender()) if self.wonBoxes[clicked].isChecked(): newWinner = self.game.players[clicked] else: newWinner = None self.game.winner = newWinner for idx in range(4): if newWinner != self.game.players[idx]: self.wonBoxes[idx].setChecked(False) if newWinner: self.draw.setChecked(False) self.fillLastTileCombo() self.slotInputChanged() def updateManualRules(self): """enable/disable them""" # if an exclusive rule has been activated, deactivate it for # all other players ruleBox = self.sender() if isinstance( ruleBox, RuleBox) and ruleBox.isChecked() and ruleBox.rule.exclusive(): for idx, player in enumerate(self.game.players): if ruleBox.parentWidget() != self.details[idx]: for pBox in player.manualRuleBoxes: if pBox.rule.name == ruleBox.rule.name: pBox.setChecked(False) try: newState = bool(self.game.winner.handBoard.uiTiles) except AttributeError: newState = False self.lblLastTile.setEnabled(newState) self.cbLastTile.setEnabled(newState) self.lblLastMeld.setEnabled(newState) self.cbLastMeld.setEnabled(newState) if self.game: for player in self.game.players: player.refreshManualRules(self.sender()) def clear(self): """prepare for next hand""" if self.game: for idx, player in enumerate(self.game.players): self.spValues[idx].clear() self.spValues[idx].setValue(0) self.wonBoxes[idx].setChecked(False) player.payment = 0 player.invalidateHand() for box in self.wonBoxes: box.setVisible(False) self.draw.setChecked(False) self.updateManualRules() if self.game is None: self.hide() else: self.refreshWindLabels() self.computeScores() self.spValues[0].setFocus() self.spValues[0].selectAll() def refreshWindLabels(self): """update their wind and prevailing""" for idx, player in enumerate(self.game.players): self.windLabels[idx].wind = player.wind self.windLabels[idx].roundsFinished = self.game.roundsFinished def computeScores(self): """if tiles have been selected, compute their value""" # pylint: disable=too-many-branches # too many branches if not self.game: return if self.game.finished(): self.hide() return for nameLabel, wonBox, spValue, player in zip(self.nameLabels, self.wonBoxes, self.spValues, self.game.players): with BlockSignals([spValue, wonBox]): # we do not want that change to call computeScores again if player.handBoard and player.handBoard.uiTiles: spValue.setEnabled(False) nameLabel.setBuddy(wonBox) for _ in range(10): prevTotal = player.handTotal player.invalidateHand() wonBox.setVisible(player.hand.won) if not wonBox.isVisibleTo(self) and wonBox.isChecked(): wonBox.setChecked(False) self.game.winner = None elif prevTotal == player.handTotal: break player.refreshManualRules() spValue.setValue(player.handTotal) else: if not spValue.isEnabled(): spValue.clear() spValue.setValue(0) spValue.setEnabled(True) nameLabel.setBuddy(spValue) wonBox.setVisible( player.handTotal >= self.game.ruleset.minMJTotal()) if not wonBox.isVisibleTo(self) and wonBox.isChecked(): wonBox.setChecked(False) if not wonBox.isVisibleTo(self) and player is self.game.winner: self.game.winner = None if Internal.scene.explainView: Internal.scene.explainView.refresh() def __lastMeldContent(self): """prepare content for lastmeld combo""" lastTiles = set() winnerTiles = [] if self.game.winner and self.game.winner.handBoard: winnerTiles = self.game.winner.handBoard.uiTiles pairs = [] for meld in self.game.winner.hand.melds: if len(meld) < 4: pairs.extend(meld) for tile in winnerTiles: if tile.tile in pairs and not tile.isBonus: lastTiles.add(tile.tile) return lastTiles, winnerTiles def __fillLastTileComboWith(self, lastTiles, winnerTiles): """fill last meld combo with prepared content""" self.comboTilePairs = lastTiles idx = self.cbLastTile.currentIndex() if idx < 0: idx = 0 indexedTile = self.cbLastTile.itemData(idx) restoredIdx = None self.cbLastTile.clear() if not winnerTiles: return pmSize = winnerTiles[0].board.tileset.faceSize pmSize = QSize(pmSize.width() * 0.5, pmSize.height() * 0.5) self.cbLastTile.setIconSize(pmSize) QPixmapCache.clear() self.__tilePixMaps = [] shownTiles = set() for tile in winnerTiles: if tile.tile in lastTiles and tile.tile not in shownTiles: shownTiles.add(tile.tile) self.cbLastTile.addItem( QIcon(tile.pixmapFromSvg(pmSize, withBorders=False)), '', tile.tile) if indexedTile is tile.tile: restoredIdx = self.cbLastTile.count() - 1 if not restoredIdx and indexedTile: # try again, maybe the tile changed between concealed and exposed indexedTile = indexedTile.exposed for idx in range(self.cbLastTile.count()): if indexedTile is self.cbLastTile.itemData(idx).exposed: restoredIdx = idx break if not restoredIdx: restoredIdx = 0 self.cbLastTile.setCurrentIndex(restoredIdx) self.prevLastTile = self.computeLastTile() def clearLastTileCombo(self): """as the name says""" self.comboTilePairs = None self.cbLastTile.clear() def fillLastTileCombo(self): """fill the drop down list with all possible tiles. If the drop down had content before try to preserve the current index. Even if the tile changed state meanwhile.""" if self.game is None: return lastTiles, winnerTiles = self.__lastMeldContent() if self.comboTilePairs == lastTiles: return with BlockSignals(self.cbLastTile): # we only want to emit the changed signal once self.__fillLastTileComboWith(lastTiles, winnerTiles) self.cbLastTile.currentIndexChanged.emit(0) def __fillLastMeldComboWith(self, winnerMelds, indexedMeld, lastTile): """fill last meld combo with prepared content""" winner = self.game.winner faceWidth = winner.handBoard.tileset.faceSize.width() * 0.5 faceHeight = winner.handBoard.tileset.faceSize.height() * 0.5 restoredIdx = None for meld in winnerMelds: pixMap = QPixmap(faceWidth * len(meld), faceHeight) pixMap.fill(Qt.transparent) self.__meldPixMaps.append(pixMap) painter = QPainter(pixMap) for element in meld: painter.drawPixmap( 0, 0, winner.handBoard.tilesByElement(element)[0].pixmapFromSvg( QSize(faceWidth, faceHeight), withBorders=False)) painter.translate(QPointF(faceWidth, 0.0)) self.cbLastMeld.addItem(QIcon(pixMap), '', str(meld)) if indexedMeld == str(meld): restoredIdx = self.cbLastMeld.count() - 1 if not restoredIdx and indexedMeld: # try again, maybe the meld changed between concealed and exposed indexedMeld = indexedMeld.lower() for idx in range(self.cbLastMeld.count()): meldContent = str(self.cbLastMeld.itemData(idx)) if indexedMeld == meldContent.lower(): restoredIdx = idx if lastTile not in meldContent: lastTile = lastTile.swapped assert lastTile in meldContent with BlockSignals(self.cbLastTile ): # we want to continue right here idx = self.cbLastTile.findData(lastTile) self.cbLastTile.setCurrentIndex(idx) break if not restoredIdx: restoredIdx = 0 self.cbLastMeld.setCurrentIndex(restoredIdx) self.cbLastMeld.setIconSize(QSize(faceWidth * 3, faceHeight)) def fillLastMeldCombo(self): """fill the drop down list with all possible melds. If the drop down had content before try to preserve the current index. Even if the meld changed state meanwhile.""" with BlockSignals(self.cbLastMeld ): # we only want to emit the changed signal once showCombo = False idx = self.cbLastMeld.currentIndex() if idx < 0: idx = 0 indexedMeld = str(self.cbLastMeld.itemData(idx)) self.cbLastMeld.clear() self.__meldPixMaps = [] if not self.game.winner: return if self.cbLastTile.count() == 0: return lastTile = Internal.scene.computeLastTile() winnerMelds = [ m for m in self.game.winner.hand.melds if len(m) < 4 and lastTile in m ] assert len(winnerMelds), 'lastTile %s missing in %s' % ( lastTile, self.game.winner.hand.melds) if len(winnerMelds) == 1: self.cbLastMeld.addItem(QIcon(), '', str(winnerMelds[0])) self.cbLastMeld.setCurrentIndex(0) return showCombo = True self.__fillLastMeldComboWith(winnerMelds, indexedMeld, lastTile) self.lblLastMeld.setVisible(showCombo) self.cbLastMeld.setVisible(showCombo) self.cbLastMeld.currentIndexChanged.emit(0) def slotInputChanged(self): """some input fields changed: update""" for player in self.game.players: player.invalidateHand() self.updateManualRules() self.computeScores() self.validate() for player in self.game.players: player.showInfo() Internal.mainWindow.updateGUI() def validate(self): """update the status of the OK button""" game = self.game if game: valid = True if game.winner and game.winner.handTotal < game.ruleset.minMJTotal( ): valid = False elif not game.winner and not self.draw.isChecked(): valid = False self.btnSave.setEnabled(valid)
class RulesetSelector(QWidget): """presents all available rulesets with previews""" def __init__(self, parent=None): super(RulesetSelector, self).__init__(parent) self.setContentsMargins(0, 0, 0, 0) self.setupUi() def setupUi(self): """layout the window""" decorateWindow(self, m18n('Customize rulesets')) self.setObjectName('Rulesets') hlayout = QHBoxLayout(self) v1layout = QVBoxLayout() self.v1widget = QWidget() v1layout = QVBoxLayout(self.v1widget) v2layout = QVBoxLayout() hlayout.addWidget(self.v1widget) hlayout.addLayout(v2layout) for widget in [self.v1widget, hlayout, v1layout, v2layout]: widget.setContentsMargins(0, 0, 0, 0) hlayout.setStretchFactor(self.v1widget, 10) self.btnCopy = QPushButton() self.btnRemove = QPushButton() self.btnCompare = QPushButton() self.btnClose = QPushButton() self.rulesetView = RuleTreeView( m18nc('kajongg', 'Rule'), self.btnCopy, self.btnRemove, self.btnCompare) v1layout.addWidget(self.rulesetView) self.rulesetView.setWordWrap(True) self.rulesetView.setMouseTracking(True) spacerItem = QSpacerItem( 20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) v2layout.addWidget(self.btnCopy) v2layout.addWidget(self.btnRemove) v2layout.addWidget(self.btnCompare) self.btnCopy.clicked.connect(self.rulesetView.copyRow) self.btnRemove.clicked.connect(self.rulesetView.removeRow) self.btnCompare.clicked.connect(self.rulesetView.compareRow) self.btnClose.clicked.connect(self.hide) v2layout.addItem(spacerItem) v2layout.addWidget(self.btnClose) self.retranslateUi() StateSaver(self) self.show() def sizeHint(self): """we never want a horizontal scrollbar for player names, we always want to see them in full""" result = QWidget.sizeHint(self) available = KApplication.kApplication().desktop().availableGeometry() height = max(result.height(), available.height() * 2 // 3) width = max(result.width(), available.width() // 2) return QSize(width, height) def minimumSizeHint(self): """we never want a horizontal scrollbar for player names, we always want to see them in full""" return self.sizeHint() def showEvent(self, dummyEvent): """reload the rulesets""" self.refresh() def refresh(self): """retranslate and reload rulesets""" self.retranslateUi() self.rulesetView.rulesets = Ruleset.availableRulesets() def hideEvent(self, event): """close all differ dialogs""" for differ in self.rulesetView.differs: differ.hide() del differ QWidget.hideEvent(self, event) def retranslateUi(self): """translate to current language""" self.btnCopy.setText(m18n("Copy")) self.btnCompare.setText(m18nc('Kajongg ruleset comparer', 'Compare')) self.btnRemove.setText(m18n("Remove")) self.btnClose.setText(m18n('Close'))
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
class ProstateTRUSNavWidget(GuideletWidget): DEFAULT_PLUSSERVER_CHOOSER_TEXT = "Choose PlusServer.exe" DEFAULT_CONFIGURATION_CHOOSER_TEXT = "Select Configuration" def __init__(self, parent=None): GuideletWidget.__init__(self, parent) self.plusServerProcess = None self.configurationFile = self.getSetting( 'ConfigurationFile', self.DEFAULT_CONFIGURATION_CHOOSER_TEXT) self.serverExecutable = self.getSetting( 'PlusServer', self.DEFAULT_PLUSSERVER_CHOOSER_TEXT) def cleanup(self): GuideletWidget.cleanup(self) if self.plusServerProcess: self.plusServerProcess.terminate() def setup(self): showPlusServerWidget = True if _platform == "linux" or _platform == "linux2" or _platform == "darwin": #linux or linux or OS X message = "Attention: You are running Slicer on Linux or OS X. Do you have PlusServer installed on the current OS?" result = QMessageBox.question(slicer.util.mainWindow(), 'ProstateTRUSNav', message, QMessageBox.Yes | QMessageBox.No) showPlusServerWidget = result == QMessageBox.Yes if _platform == "win32" or showPlusServerWidget: # Windows... plusServerCollapsibleButton = ctkCollapsibleButton() plusServerCollapsibleButton.text = "PlusServer" self.layout.addWidget(plusServerCollapsibleButton) self.configurationFileChooserButton = QPushButton( self.configurationFile) self.configurationFileChooserButton.connect( 'clicked()', self.onConfigFileSelected) self.runPlusServerButton = QPushButton("Run PlusServer") self.runPlusServerButton.setCheckable(True) self.runPlusServerButton.connect('clicked()', self.onRunPlusServerButtonClicked) self.serverFormLayout = QFormLayout(plusServerCollapsibleButton) self.serverExecutableChooserButton = QPushButton( self.serverExecutable) self.serverExecutableChooserButton.connect( 'clicked()', self.onServerExecutableSelected) hbox = QHBoxLayout() hbox.addWidget(self.serverExecutableChooserButton) self.serverFormLayout.addRow(hbox) hbox = QHBoxLayout() hbox.addWidget(self.configurationFileChooserButton) hbox.addWidget(self.runPlusServerButton) self.serverFormLayout.addRow(hbox) GuideletWidget.setup(self) # do specific setup here if _platform == "win32" or showPlusServerWidget: self.launchGuideletButton.setEnabled(False) self.checkExecutableAndArgument() def checkExecutableAndArgument(self): if os.path.exists(self.serverExecutable) and os.path.exists( self.configurationFile): self.runPlusServerButton.setEnabled(True) else: self.runPlusServerButton.setEnabled(False) def getSetting(self, settingName, defaultValue=""): settings = QSettings() value = settings.value(self.moduleName + '/' + settingName, defaultValue) return value if value is not None and value != "" else defaultValue def setSetting(self, settingName, value): settings = QSettings() settings.setValue(self.moduleName + '/' + settingName, value) def addLauncherWidgets(self): GuideletWidget.addLauncherWidgets(self) # add launcher widget here def onServerExecutableSelected(self): executable = QFileDialog.getOpenFileName(self.parent, "PlusServer Executable", self.serverExecutable, "*.exe") if executable != "" and executable.find("PlusServer.exe"): self.serverExecutable = executable self.serverExecutableChooserButton.setText(executable) self.setSetting("PlusServer", executable) self.checkExecutableAndArgument() def onConfigFileSelected(self): self.configurationFile = QFileDialog.getOpenFileName( self.parent, "Choose Configuration File", self.configurationFile, "*.xml") if self.configurationFile != "": self.configurationFileChooserButton.setText( os.path.split(self.configurationFile)[1]) self.setSetting("ConfigurationFile", self.configurationFile) self.checkExecutableAndArgument() def onRunPlusServerButtonClicked(self): if self.runPlusServerButton.isChecked(): command = [ self.serverExecutable, "--config-file=" + self.configurationFile ] logging.info("Executing %s %s" % tuple(command)) self.plusServerProcess = Popen([ self.serverExecutable, "--config-file=" + self.configurationFile ]) if self.plusServerProcess: self.runPlusServerButton.setText("Quit Plus Server") self.launchGuideletButton.setEnabled(True) else: if self.plusServerProcess: self.plusServerProcess.terminate() self.runPlusServerButton.setText("Run PlusServer") self.launchGuideletButton.setEnabled(False) def collectParameterList(self): parameterList = GuideletWidget.collectParameterList(self) if not parameterList: parameterList = dict() parameterList['OfflineVolumeToReconstruct'] = 0, return parameterList def createGuideletInstance(self, parameterList=None): return ProstateTRUSNavGuidelet(None, self.guideletLogic, parameterList) def createGuideletLogic(self): return ProstateTRUSNavLogic()
class qSlicerMultiVolumeExplorerModuleWidget( qSlicerMultiVolumeExplorerSimplifiedModuleWidget): def __init__(self, parent=None): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.__init__(self, parent) def setupAdditionalFrames(self): self.setupPlotSettingsFrame() def setupInputFrame(self, parent=None): self.inputFrame = ctk.ctkCollapsibleButton() self.inputFrame.text = "Input" self.inputFrame.collapsed = 0 inputFrameCollapsibleLayout = QFormLayout(self.inputFrame) qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupInputFrame( self, parent=inputFrameCollapsibleLayout) self.layout.addWidget(self.inputFrame) self.fgMultiVolumeSelector = slicer.qMRMLNodeComboBox() self.fgMultiVolumeSelector.nodeTypes = ['vtkMRMLMultiVolumeNode'] self.fgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene) self.fgMultiVolumeSelector.addEnabled = 0 self.fgMultiVolumeSelector.noneEnabled = 1 self.fgMultiVolumeSelector.toolTip = "Secondary multivolume will be used for the secondary \ plot in interactive charting. As an example, this can be used to overlay the \ curve obtained by fitting a model to the data" self.inputFrameLayout.addRow(QLabel('Input secondary multivolume'), self.fgMultiVolumeSelector) def setupFrameControlFrame(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupFrameControlFrame( self) self.frameCopySelector = slicer.qMRMLNodeComboBox() self.frameCopySelector.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) self.frameCopySelector.nodeTypes = ['vtkMRMLScalarVolumeNode'] self.frameCopySelector.setMRMLScene(slicer.mrmlScene) self.frameCopySelector.addEnabled = 1 self.frameCopySelector.enabled = 0 # do not show "children" of vtkMRMLScalarVolumeNode self.frameCopySelector.hideChildNodeTypes = [ "vtkMRMLDiffusionWeightedVolumeNode", "vtkMRMLDiffusionTensorVolumeNode", "vtkMRMLVectorVolumeNode" ] self.extractFrameCopy = False self.extractFrameCheckBox = QCheckBox('Enable copying') hbox = QHBoxLayout() hbox.addWidget(QLabel('Current frame copy')) hbox.addWidget(self.frameCopySelector) hbox.addWidget(self.extractFrameCheckBox) self.inputFrameLayout.addRow(hbox) def setupPlotSettingsFrame(self): self.plotSettingsFrame = ctk.ctkCollapsibleButton() self.plotSettingsFrame.text = "Plotting Settings" self.plotSettingsFrame.collapsed = 1 plotSettingsFrameLayout = QFormLayout(self.plotSettingsFrame) self.layout.addWidget(self.plotSettingsFrame) # label map for probing self.labelMapSelector = slicer.qMRMLNodeComboBox() self.labelMapSelector.nodeTypes = ['vtkMRMLLabelMapVolumeNode'] self.labelMapSelector.toolTip = 'Label map to be probed' self.labelMapSelector.setMRMLScene(slicer.mrmlScene) self.labelMapSelector.addEnabled = 0 self.chartButton = QPushButton('Chart') self.chartButton.setEnabled(False) hbox = QHBoxLayout() hbox.addWidget(QLabel('Probed label volume')) hbox.addWidget(self.labelMapSelector) hbox.addWidget(self.chartButton) plotSettingsFrameLayout.addRow(hbox) self.iCharting = QCheckBox('Interactive charting') self.iCharting.setChecked(True) plotSettingsFrameLayout.addRow(self.iCharting) self.iChartingMode = QButtonGroup() self.iChartingIntensity = QRadioButton('Signal intensity') self.iChartingIntensityFixedAxes = QRadioButton( 'Fixed range intensity') self.iChartingPercent = QRadioButton('Percentage change') self.iChartingIntensity.setChecked(1) self.iChartingMode.addButton(self.iChartingIntensity) self.iChartingMode.addButton(self.iChartingIntensityFixedAxes) self.iChartingMode.addButton(self.iChartingPercent) hbox = QHBoxLayout() self.plottingModeGroupBox = QGroupBox('Plotting mode:') plottingModeLayout = QVBoxLayout() self.plottingModeGroupBox.setLayout(plottingModeLayout) plottingModeLayout.addWidget(self.iChartingIntensity) plottingModeLayout.addWidget(self.iChartingIntensityFixedAxes) plottingModeLayout.addWidget(self.iChartingPercent) hbox.addWidget(self.plottingModeGroupBox) self.showLegendCheckBox = QCheckBox('Display legend') self.showLegendCheckBox.setChecked(0) self.xLogScaleCheckBox = QCheckBox('Use log scale for X axis') self.xLogScaleCheckBox.setChecked(0) self.yLogScaleCheckBox = QCheckBox('Use log scale for Y axis') self.yLogScaleCheckBox.setChecked(0) self.plotGeneralSettingsGroupBox = QGroupBox('General Plot options:') plotGeneralSettingsLayout = QVBoxLayout() self.plotGeneralSettingsGroupBox.setLayout(plotGeneralSettingsLayout) plotGeneralSettingsLayout.addWidget(self.showLegendCheckBox) plotGeneralSettingsLayout.addWidget(self.xLogScaleCheckBox) plotGeneralSettingsLayout.addWidget(self.yLogScaleCheckBox) hbox.addWidget(self.plotGeneralSettingsGroupBox) plotSettingsFrameLayout.addRow(hbox) self.nFramesBaselineCalculation = QSpinBox() self.nFramesBaselineCalculation.minimum = 1 hbox = QHBoxLayout() hbox.addWidget(QLabel('Frame count(baseline calculation):')) hbox.addWidget(self.nFramesBaselineCalculation) plotSettingsFrameLayout.addRow(hbox) def setupPlottingFrame(self, parent=None): self.plotFrame = ctk.ctkCollapsibleButton() self.plotFrame.text = "Plotting" self.plotFrame.collapsed = 0 plotFrameLayout = QGridLayout(self.plotFrame) self.layout.addWidget(self.plotFrame) qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupPlottingFrame( self, parent=plotFrameLayout) def onDockChartViewToggled(self, checked): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.onDockChartViewToggled( self, checked) if checked: self.layout.removeWidget(self.plotFrame) self.plotFrame.hide() def dockChartView(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.dockChartView(self) self.layout.addWidget(self.plotFrame) self.plotFrame.show() def setFramesEnabled(self, enabled): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setFramesEnabled( self, enabled) self.plotSettingsFrame.setEnabled(enabled) self.plotFrame.setEnabled(enabled) self.plotFrame.collapsed = 0 if enabled else 1 def setupConnections(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.setupConnections(self) self.labelMapSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onLabelNodeChanged) self.chartButton.connect('clicked()', self.onLabeledChartRequested) self.xLogScaleCheckBox.connect('stateChanged(int)', self.onXLogScaleRequested) self.yLogScaleCheckBox.connect('stateChanged(int)', self.onYLogScaleRequested) self.nFramesBaselineCalculation.valueChanged.connect( self.onFrameCountBaselineCalculationChanged) self.iChartingMode.buttonClicked.connect(self.onChartingModeChanged) self.showLegendCheckBox.connect('stateChanged(int)', self.onShowLegendChanged) self.fgMultiVolumeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onForegroundInputChanged) self.extractFrameCheckBox.connect('stateChanged(int)', self.onExtractFrameChanged) self.frameCopySelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVFMRMLSceneChanged) def onFrameCountBaselineCalculationChanged(self, value): self._multiVolumeIntensityChart.nFramesForBaselineCalculation = value def onChartingModeChanged(self, button): if button is self.iChartingIntensity: self._multiVolumeIntensityChart.activateSignalIntensityMode() elif button is self.iChartingIntensityFixedAxes: self._multiVolumeIntensityChart.activateFixedRangeIntensityMode() elif button is self.iChartingPercent: self._multiVolumeIntensityChart.activatePercentageChangeMode() def onShowLegendChanged(self, checked): self._multiVolumeIntensityChart.showLegend = True if checked == 2 else False def onXLogScaleRequested(self, checked): self._multiVolumeIntensityChart.showXLogScale = True if checked == 2 else False def onYLogScaleRequested(self, checked): self._multiVolumeIntensityChart.showYLogScale = True if checked == 2 else False def onLVMRMLSceneChanged(self, mrmlScene): self.labelMapSelector.setMRMLScene(slicer.mrmlScene) def onVFMRMLSceneChanged(self, mrmlScene): self.frameCopySelector.setMRMLScene(slicer.mrmlScene) def onLabelNodeChanged(self): labelNode = self.labelMapSelector.currentNode() self.chartButton.setEnabled(labelNode is not None and self._bgMultiVolumeNode is not None) def onForegroundInputChanged(self): logging.info( "qSlicerMultiVolumeExplorerModuleWidget:ForegroundInputChanged") self._fgMultiVolumeNode = self.fgMultiVolumeSelector.currentNode() self._multiVolumeIntensityChart.fgMultiVolumeNode = self.fgMultiVolumeSelector.currentNode( ) self.refreshGUIForNewBackgroundImage() def onBackgroundInputChanged(self): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.onBackgroundInputChanged( self) if self._bgMultiVolumeNode is not None: self.frameCopySelector.setCurrentNode(None) self.nFramesBaselineCalculation.maximum = self._bgMultiVolumeNode.GetNumberOfFrames( ) self.onLabelNodeChanged() ''' If extract button is checked, will copy the current frame to the selected volume node on each event from frame slider ''' def onExtractFrameChanged(self, checked): if checked: self.extractFrameCopy = True self.onSliderChanged(self.frameSlider.value) else: self.extractFrameCopy = False def onSliderChanged(self, frameId): qSlicerMultiVolumeExplorerSimplifiedModuleWidget.onSliderChanged( self, frameId) frameId = int(frameId) if self.extractFrameCopy: frameVolume = self.frameCopySelector.currentNode() frameVolumeCopy = Helper.extractFrame(frameVolume, self._bgMultiVolumeNode, frameId) if not frameVolume: self.frameCopySelector.setCurrentNode(frameVolumeCopy) frameName = '%s frame %d' % (self._bgMultiVolumeNode.GetName(), frameId) frameVolumeCopy.SetName(frameName) def onLabeledChartRequested(self): labelNode = self.labelMapSelector.currentNode() mvNode = self._bgMultiVolumeNode mvLabels = MultiVolumeIntensityChartView.getMultiVolumeLabels( self._bgMultiVolumeNode) chartViewNode = LabeledImageChartView( labelNode=labelNode, multiVolumeNode=mvNode, multiVolumeLabels=mvLabels, baselineFrames=self.nFramesBaselineCalculation, displayPercentageChange=self.iChartingPercent.checked) chartViewNode.requestChartCreation() def processEvent(self, observee, event): if not self.iCharting.checked: return qSlicerMultiVolumeExplorerSimplifiedModuleWidget.processEvent( self, observee, event)
import sys from qt import QApplication, QPushButton app=QApplication(sys.argv) button=QPushButton(None) button.setText("Hello World") app.setMainWidget(button) button.show() app.exec_loop()
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 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())