def drawLines(self, qp): pen = qt.QPen(qt.Qt.green, 2, qt.Qt.SolidLine) if self.state == 0: pen.setColor(qt.Qt.black) qp.setPen(pen) qp.setFont(qt.QFont("Arial", 30)) qp.drawText(qt.QPointF(325, 60), self.LT_Text) elif self.state == 1: pen.setColor(qt.Qt.black) qp.setPen(pen) qp.setFont(qt.QFont("Arial", 30)) qp.drawText(qt.QPointF(325, 60), self.RT_Text) elif self.state == 2: pen.setColor(qt.Qt.black) qp.setPen(pen) qp.setFont(qt.QFont("Arial", 30)) qp.drawText(qt.QPointF(325, 60), self.LB_Text) elif self.state == 3: pen.setColor(qt.Qt.black) qp.setPen(pen) qp.setFont(qt.QFont("Arial", 30)) qp.drawText(qt.QPointF(325, 60), self.RB_Text) elif self.state == 4: pen.setColor(qt.Qt.black) qp.setPen(pen) qp.setFont(qt.QFont("Arial", 30)) qp.drawText(qt.QPointF(325, 60), self.Quit_Text)
class XnatSlicerGlobals(object): """ XnatSlicerGlobals contains static properites relevant to the XnatSlicer module. """ LIB_URI = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) ROOT_URI = os.path.dirname(LIB_URI) CACHE_URI = os.path.join(ROOT_URI, 'Cache') RESOURCES_URI = os.path.join(ROOT_URI, 'Resources') LOCAL_URIS = { "home": ROOT_URI, "settings": os.path.join(ROOT_URI, "Settings"), "projects": os.path.join(CACHE_URI, "projects"), "downloads": os.path.join(CACHE_URI, "downloads"), "uploads": os.path.join(CACHE_URI, "uploads"), "icons": os.path.join(RESOURCES_URI, "Icons"), } DICOM_EXTENSIONS = [".dcm", ".ima", ".dicom"] ANALYZE_EXTENSIONS = [".hdr", ".img"] MISC_LOADABLE_EXTENSIONS = [ ".nii", ".nrrd", ".img", ".nhdr", ".dc", ".raw.gz", ".gz", ".vtk", ".stl", ".acsv" ] DECOMPRESSIBLE_EXTENSIONS = [".gz", ".zip", ".tar"] MRML_EXTENSIONS = [".mrml"] ALL_LOADABLE_EXTENSIONS = DICOM_EXTENSIONS + ANALYZE_EXTENSIONS + \ MISC_LOADABLE_EXTENSIONS BUTTON_SIZE_MED = qt.QSize(45, 45) BUTTON_SIZE_SMALL = qt.QSize(28, 28) FONT_NAME = "Arial" FONT_SIZE = 10 LABEL_FONT = qt.QFont(FONT_NAME, FONT_SIZE, 10, False) LABEL_FONT_LARGE = qt.QFont(FONT_NAME, FONT_SIZE + 2, 10, False) LABEL_FONT_BOLD = qt.QFont(FONT_NAME, FONT_SIZE, 100, False) LABEL_FONT_ITALIC = qt.QFont(FONT_NAME, FONT_SIZE, 10, True) LABEL_FONT_ITALIC_LARGE = qt.QFont(FONT_NAME, FONT_SIZE + 2, 10, True) CUSTOM_METADATA_SETTINGS_PREFIX = 'customMetadataTags_' SLICER_FOLDER_NAME = "Slicer" REQUIRED_SLICER_FOLDERS = [SLICER_FOLDER_NAME] DEFAULT_XNAT_SAVE_LEVEL = "experiments" DEFAULT_SLICER_EXTENSION = ".mrb" SLICER_PACKAGE_EXTENSIONS = [".zip", ".mrb"] DEFAULT_SCENE_NAME = "SlicerScene_"
class Settings_View(FontSetting, MetadataEditorSetting, CheckBoxSetting, Settings): """ Settings_View is the Settings pertaining to the 'View_Tree' class. """ LABEL_FONT = qt.QFont('Arial', 10, 10, False) LABEL_FONT_SIZE = 'Font Size' LABEL_METADATA = 'Info. Metadata' DEFAULT_METADATA = Xnat.metadata.DEFAULT_TAGS_LITE CHECKBOXES = OrderedDict([('lastAccessed', { 'tag': 'showLastAccessedOnly', 'desc': 'Show only accessed projects.', 'checked': False, 'event': 'FILTERTOGGLED' })]) def setup(self): """ As stated. """ self.addSection('Filters') self.createCheckBoxes() self.addSpacing() self.addSpacing() self.createFontSizeDropdown(Settings_View.LABEL_FONT_SIZE) self.addSpacing() self.createMetadataEditorSets(Settings_View.LABEL_METADATA, itemType='checkbox', editVisible=True, customEditVisible=False)
def createFilePanel(self): '''''' filePanel, fLayout = self.createWin((100, 50, 400, 600), 'File List', qt.QVBoxLayout(), maxW=400, minW=300) tree = qt.QTreeWidget () headerItem = qt.QTreeWidgetItem() item = qt.QTreeWidgetItem() treeItems = [] for label in ['Volumes', 'Transforms']: parent = qt.QTreeWidgetItem(tree) parent.setText(0, label) parent.setFlags(parent.flags() | qt.Qt.ItemIsTristate | qt.Qt.ItemIsUserCheckable) parent.setExpanded(True) treeItems.append(parent) tree.setHeaderLabels(['File Path']) tree.setWindowTitle('File Panel') # Font settings font = qt.QFont() font.setPointSize(8) font.setBold(True) [i.setFont(0, font) for i in treeItems] # Add widget fLayout.addWidget(tree) self.createBtn('Load to Scene', self.loadSelectedFiles, fLayout, 'Load selected data') self.createBtn('Clear Scene', self.clearScene, fLayout, 'Clean everything in the current scene') return (filePanel, *treeItems)
def generateButton(self, iconOrLabel="", toolTip="", font = qt.QFont('Arial', 10, 10, False), size = None, enabled=False): """ Creates a qt.QPushButton(), with the arguments. Sets text, font, toolTip, icon, size, and enabled state. """ button = qt.QPushButton() #-------------------- # Set either Icon or label, depending on # whehter the icon file exists. #-------------------- iconPath = os.path.join(self.MODULE.GLOBALS.LOCAL_URIS['icons'], iconOrLabel) if os.path.exists(iconPath): button.setIcon(qt.QIcon(iconPath)) else: button.setText(iconOrLabel) button.setToolTip(toolTip) button.setFont(font) if size: button.setFixedHeight(size.height()) button.setFixedWidth(size.width()) button.setEnabled(enabled) return button
def createUserInterface(self): font = qt.QFont("Sans Serif", 12, qt.QFont.Bold) self.__layout = qt.QFormLayout(self) self.botonRegistro = qt.QPushButton('Realizar Registro') self.botonRegistro.connect('clicked(bool)', self.onApplyRegistro) self.__layout.addRow(self.botonRegistro)
def createUserInterface(self): font = qt.QFont("Sans Serif", 12, qt.QFont.Bold) self.__layout = qt.QFormLayout(self) self.labelInstruccionesDeUsoBienvenido = qt.QLabel( "Historia Clinica: \n\nEl paciente presenta ...") self.labelInstruccionesDeUsoBienvenido.setFont(font) self.__layout.addRow(self.labelInstruccionesDeUsoBienvenido)
def __createErrorLines(self, level): """ As stated. @param level: The level to make the widget for. @type level: str """ self.__errorLines[level] = qt.QLabel(self) self.__errorLines[level].setTextFormat(1) self.__errorLines[level].setFixedHeight(12) self.__errorLines[level].setFont( qt.QFont(self.FONT_NAME, self.FONT_SIZE, 10, False))
def generateButton(iconOrLabel="", toolTip="", font=qt.QFont('Arial', 10, 10, False), size=None, enabled=False): """ Creates a qt.QPushButton(), with the arguments. Sets text, font, toolTip, icon, size, and enabled state. @param iconOrLabel: Either the icon uri or the label of the button. Defaults to ''. @type iconOrLabel: string @param toolTip: The tool tip of the button. Defaults to ''. @type toolTip: string @param font: The font of the button. Defaults to 'Arial, 10, plain.' @type font: qt.QFont @param size: The size of the button. Defaults QT presets. @type size: qt.QSize @param enabled: The enabled state of the button. Defaults to 'False'. @type enabled: boolean @return: The constructed button to return. @rtype: qt.QPushButton """ button = qt.QPushButton() #-------------------- # Set either Icon or label, depending on # whehter the icon file exists. #-------------------- iconPath = os.path.join(XnatSlicerGlobals.LOCAL_URIS['icons'], iconOrLabel) if os.path.exists(iconPath): button.setIcon(qt.QIcon(iconPath)) else: button.setText(iconOrLabel) button.setToolTip(toolTip) button.setFont(font) if size: button.setFixedHeight(size.height()) button.setFixedWidth(size.width()) button.setEnabled(enabled) return button
def __init__(self, parent=None): super(CheckableTabsWidget, self).__init__(parent) self.featureClassFeatureWidgets = collections.OrderedDict() # hack ( QTabWidget.setTabBar() and tabBar() are protected ) self.tab_bar = self.findChildren(qt.QTabBar)[0] # Bold font style self.boldFont = qt.QFont() self.boldFont.setBold(True) self.tab_bar.setFont(self.boldFont) self.tab_bar.setContextMenuPolicy(3) self.tab_bar.installEventFilter(self)
def createUserInterface(self): font =qt.QFont("Sans Serif", 12, qt.QFont.Bold) self.__layout = qt.QFormLayout( self ) self.__layout.addRow(" ",qt.QWidget()) self.nombreRegistro = qt.QLabel("Nombre: ") self.nombreRegistroTextEdit = qt.QLineEdit() self.nombreRegistroTextEdit.setFixedWidth(200) self.nombreRegistroTextEdit.textChanged.connect(self.textchanged1) self.__layout.addRow(self.nombreRegistro,self.nombreRegistroTextEdit) self.contrasenaRegistro = qt.QLabel("Contrasena: ") self.contrasenaRegistroTextEdit = qt.QLineEdit() self.contrasenaRegistroTextEdit.setFixedWidth(200) self.contrasenaRegistroTextEdit.setEchoMode(qt.QLineEdit.Password) self.contrasenaRegistroTextEdit.textChanged.connect(self.textchanged2) self.__layout.addRow(self.contrasenaRegistro,self.contrasenaRegistroTextEdit) self.contrasenaRegistro1 = qt.QLabel("Repetir contrasena: ") self.contrasenaRegistro1TextEdit = qt.QLineEdit() self.contrasenaRegistro1TextEdit.setFixedWidth(200) self.contrasenaRegistro1TextEdit.setEchoMode(qt.QLineEdit.Password) self.contrasenaRegistro1TextEdit.textChanged.connect(self.textchanged3) self.__layout.addRow(self.contrasenaRegistro1,self.contrasenaRegistro1TextEdit) self.vinculoRegistro = qt.QLabel("Tipo de vinculo: ") self.vinculoComboBox = qt.QComboBox() self.vinculoComboBox.addItem('Estudiante') self.vinculoComboBox.addItem('Profesor') self.__layout.addRow(self.vinculoRegistro,self.vinculoComboBox) self.cursoRegistro = qt.QLabel('Curso al que pertenece') self.cursoRegistroComboBox = qt.QComboBox() self.mypath="C:\Users\Camilo_Q\Documents\GitHub\workFlows\Cursos" #Se crea path para busqueda de cursos self.onlyfiles = [f for f in listdir(self.mypath) if isfile(join(self.mypath, f))] #Lista los archivos que estan dentro del path for curso in self.onlyfiles: #Muestra en el comboBox de cursos los archivos que estan presentes en el path self.cursoRegistroComboBox.addItem(curso) self.__layout.addRow(self.cursoRegistro,self.cursoRegistroComboBox) self.__layout.addRow(" ",qt.QWidget()) self.botonRegistro = qt.QPushButton('Realizar Registro') self.botonRegistro.connect('clicked(bool)',self.onApplyRegistro) self.botonReiniciarRegistro = qt.QPushButton('Reiniciar Registro') self.botonReiniciarRegistro.connect('clicked(bool)',self.onApplyReiniciarRegistro) self.__layout.addRow(self.botonRegistro) self.__layout.addRow(self.botonReiniciarRegistro)
def createUserInterface(self): font = qt.QFont("Sans Serif", 12, qt.QFont.Bold) self.__layout = qt.QFormLayout(self) self.trayectoriaLibreButton = qt.QRadioButton('Trayectoria libre') self.trayectoriaProgramadaButton = qt.QRadioButton( 'Trayectoria programada') self.__layout.addRow("", qt.QWidget()) self.__layout.addRow("", qt.QWidget()) self.__layout.addRow("", qt.QWidget()) self.trayectoriaLibreButton.setFont(font) self.trayectoriaProgramadaButton.setFont(font) self.__layout.addRow(self.trayectoriaLibreButton) self.__layout.addRow(self.trayectoriaProgramadaButton)
def createUserInterface(self): font =qt.QFont("Sans Serif", 12, qt.QFont.Bold) self.__layout = qt.QFormLayout( self ) self.anadirTrayectoriaButton = qt.QRadioButton('Anadir trayectoria') self.calificarButton = qt.QRadioButton('Calificar trayectoria de alumnos') self.verActividadButton = qt.QRadioButton('Ver actividad de alumnos') self.__layout.addRow("",qt.QWidget()) self.__layout.addRow("",qt.QWidget()) self.__layout.addRow("",qt.QWidget()) self.anadirTrayectoriaButton.setFont(font) self.calificarButton.setFont(font) self.verActividadButton.setFont(font) self.__layout.addRow(self.anadirTrayectoriaButton) self.__layout.addRow(self.calificarButton) self.__layout.addRow(self.verActividadButton)
def createUserInterface(self): font = qt.QFont("Sans Serif", 12, qt.QFont.Bold) self.__layout = self.__parent.createUserInterface() self.__layout = qt.QFormLayout(self) loader = qt.QUiLoader() path = 'C:\Users\Camilo_Q\Documents\GitHub\simuladorTornillosPediculares\Interfaz Grafica\MenuProfesor.ui' moduleName = 'simuladorTornillosPediculares' scriptedModulesPath = eval( 'slicer.modules.%s.path' % moduleName.lower()) # devuelve la ruta del .py scriptedModulesPath = os.path.dirname( scriptedModulesPath) # lleva a la carpeta del modulo path = os.path.join(scriptedModulesPath, 'Interfaz Grafica', '%s.ui' % self.stepid) qfile = qt.QFile(path) qfile.open(qt.QFile.ReadOnly) widget = loader.load(qfile) self.widget = widget self.__layout.addWidget(widget) self.widget.setMRMLScene(slicer.mrmlScene) self.seleccionDeEstudianteComboBox = self.findWidget( self.widget, 'seleccionDeEstudianteComboBox') self.cargarPushButton = self.findWidget(self.widget, 'cargarPushButton') self.cargarPushButton.connect('clicked(bool)', self.onApplyCargar) con = mysql.connector.connect(user="******", password="******", host="127.0.0.1", database="basedatos_simulador_ttp") cursor = con.cursor() estudiantes = [] cursor.execute("SELECT * FROM estudiantes") rows = cursor.fetchall() for row in rows: estudiantes.append(row) for i in range(0, len(estudiantes)): self.seleccionDeEstudianteComboBox.addItem(estudiantes[i][1])
def dialogBoxFunction(self): self.deleteAllMsgBox = qt.QDialog(slicer.util.mainWindow()) #self.deleteAllMsgBox.setWindowTitle("Delete All Fiducials?") self.deleteAllMsgBox.setFixedSize(200, 100) self.deleteAllMsgBox.show() self.deleteAllMsgBox.setLayout(qt.QVBoxLayout()) messageLabel = qt.QLabel("Delete All Fiducials?") font = qt.QFont() font.setPointSize(10) messageLabel.setFont(font) self.deleteAllMsgBox.layout().addWidget(messageLabel, 0, 4) yesNoBox = qt.QFrame() yesNoBox.setLayout(qt.QHBoxLayout()) self.deleteAllMsgBox.layout().addWidget(yesNoBox, 0, 4) # # OK button # okButton = qt.QPushButton() okButton.setText("YES") okButton.enabled = True okIcon = qt.QIcon(":/Icons/AnnotationOkDone.png") okButton.setIcon(okIcon) yesNoBox.layout().addWidget(okButton) # # NO button # noButton = qt.QPushButton() noButton.setText("NO") noButton.enabled = True noIcon = qt.QIcon(":/Icons/AnnotationCancel.png") noButton.setIcon(noIcon) yesNoBox.layout().addWidget(noButton) # Connections okButton.connect("clicked()", self.onDeleteAllButton) noButton.connect("clicked()", self.deleteAllMsgBox.hide)
def createUserInterface(self): font = qt.QFont("Sans Serif", 12, qt.QFont.Bold) self.__layout = qt.QFormLayout(self) self.__layout.addRow(" ", qt.QWidget()) self.__layout.addRow(" ", qt.QWidget()) self.nombreBienvenida = qt.QLabel("Quien eres?") self.nombreBienvenida.setFont(font) self.__layout.addRow(self.nombreBienvenida) self.__layout.addRow(" ", qt.QWidget()) self.__layout.addRow(" ", qt.QWidget()) self.EstudianteButton = qt.QRadioButton('Soy estudiante') self.EstudianteButton.setFont(font) self.ProfesorButton = qt.QRadioButton('Soy profesor') self.ProfesorButton.setFont(font) self.soyNuevoButton = qt.QRadioButton('Soy nuevo') self.soyNuevoButton.setFont(font) self.__layout.addRow(self.EstudianteButton) self.__layout.addRow(" ", qt.QWidget()) self.__layout.addRow(self.ProfesorButton) self.__layout.addRow(" ", qt.QWidget()) self.__layout.addRow(self.soyNuevoButton)
def createUserInterface(self): font = qt.QFont("Sans Serif", 12, qt.QFont.Bold) self.__layout = self.__parent.createUserInterface() self.__layout = qt.QFormLayout(self) moduleName = 'simuladorTornillosPediculares' scriptedModulesPath = eval( 'slicer.modules.%s.path' % moduleName.lower()) # devuelve la ruta del .py scriptedModulesPath = os.path.dirname( scriptedModulesPath) # lleva a la carpeta del modulo path = os.path.join(scriptedModulesPath, 'Interfaz Grafica', '%s.ui' % self.stepid) loader = qt.QUiLoader() #path1='C:\Users\Camilo_Q\Documents\GitHub\simuladorTornillosPediculares\Interfaz Grafica\Inicio.ui' qfile = qt.QFile(path) qfile.open(qt.QFile.ReadOnly) widget = loader.load(qfile) self.widget = widget self.__layout.addWidget(widget) self.widget.setMRMLScene(slicer.mrmlScene) self.nombreEditText = self.findWidget(self.widget, 'nombreEditText') self.contrasenaEditText = self.findWidget(self.widget, 'contrasenaEditText') self.profesorCheckBox = self.findWidget(self.widget, 'profesorCheckBox') self.estudianteCheckBox = self.findWidget(self.widget, 'estudianteCheckBox') self.eresNuevoCheckBox = self.findWidget(self.widget, 'eresNuevoCheckBox') self.nombreEditText.textChanged.connect(self.textchanged1) self.contrasenaEditText.textChanged.connect(self.textchanged2)
def getBoldFont( self ): ''' ''' boldFont = qt.QFont( "Sans Serif", 12, qt.QFont.Bold ) return boldFont
def createUserInterface(self): font = qt.QFont("Sans Serif", 12, qt.QFont.Bold) self.__layout = qt.QFormLayout(self)
def setup(self): self.PathRecorderModuleDirectoryPath = slicer.modules.pathrecorder.path.replace( "PathRecorder.py", "") # Instantiate and connect widgets ... # # Reload and Test area # reloadCollapsibleButton = ctk.ctkCollapsibleButton() reloadCollapsibleButton.text = "Reload && Test" self.layout.addWidget(reloadCollapsibleButton) reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton) # reload button # (use this during development, but remove it when delivering # your module to users) self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "PathRecorder Reload" reloadFormLayout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # reload and test button # (use this during development, but remove it when delivering # your module to users) self.reloadAndTestButton = qt.QPushButton("Reload and Test") self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests." reloadFormLayout.addWidget(self.reloadAndTestButton) self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest) # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) # # Input fiducial node selector # self.inputFiducialsNodeSelector = slicer.qMRMLNodeComboBox() self.inputFiducialsNodeSelector.nodeTypes = [ 'vtkMRMLMarkupsFiducialNode' ] self.inputFiducialsNodeSelector.selectNodeUponCreation = True self.inputFiducialsNodeSelector.addEnabled = True self.inputFiducialsNodeSelector.removeEnabled = False self.inputFiducialsNodeSelector.noneEnabled = True self.inputFiducialsNodeSelector.showHidden = False self.inputFiducialsNodeSelector.showChildNodeTypes = False self.inputFiducialsNodeSelector.setMRMLScene(slicer.mrmlScene) self.inputFiducialsNodeSelector.objectName = 'inputFiducialsNodeSelector' self.inputFiducialsNodeSelector.toolTip = "Select storage node for the recorded points (Markup-Fiducial-Node)." #inputFiducialsNodeSelector.connect('currentNodeChanged(bool)', self.enableOrDisableCreateButton) parametersFormLayout.addRow("Storage Node:", self.inputFiducialsNodeSelector) #self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', inputFiducialsNodeSelector, 'setMRMLScene(vtkMRMLScene*)') # Input Tracker node selector # self.inputTrackerNodeSelector = slicer.qMRMLNodeComboBox() self.inputTrackerNodeSelector.nodeTypes = [ 'vtkMRMLLinearTransformNode' ] self.inputTrackerNodeSelector.selectNodeUponCreation = True self.inputTrackerNodeSelector.addEnabled = False self.inputTrackerNodeSelector.removeEnabled = False self.inputTrackerNodeSelector.noneEnabled = True self.inputTrackerNodeSelector.showHidden = False self.inputTrackerNodeSelector.showChildNodeTypes = False self.inputTrackerNodeSelector.setMRMLScene(slicer.mrmlScene) self.inputTrackerNodeSelector.objectName = 'inputTrackerNodeSelector' self.inputTrackerNodeSelector.toolTip = "Select the tracker linear transform node." #inputTrackerNodeSelector.connect('currentNodeChanged(bool)', self.enableOrDisableCreateButton) parametersFormLayout.addRow("Tracker Transform:", self.inputTrackerNodeSelector) #self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', inputTrackerNodeSelector, 'setMRMLScene(vtkMRMLScene*)') # # Status Area # statusCollapsibleButton = ctk.ctkCollapsibleButton() statusCollapsibleButton.text = "Tracker Status" self.layout.addWidget(statusCollapsibleButton) # Layout within the status collapsible button statusFormLayout = qt.QFormLayout(statusCollapsibleButton) # # Status Button # self.statusRedIcon = qt.QIcon(self.PathRecorderModuleDirectoryPath + '/Resources/Icons/icon_DotRed.png') self.statusGreenIcon = qt.QIcon(self.PathRecorderModuleDirectoryPath + '/Resources/Icons/icon_DotGreen.png') self.statusButton = qt.QPushButton("") #self.statusButton.toolTip = "Tracker Status" self.statusButton.enabled = False self.statusButton.setIcon(self.statusRedIcon) self.statusButton.setMaximumWidth(25) # Bold and large font for needle label largeFont = qt.QFont() largeFont.setPixelSize(14) # # Label for showing the tracker position # self.currentCoordinatesLabel = qt.QLabel('[ NaN , NaN , NaN ]') self.currentCoordinatesLabel.setToolTip("Tracker Position") statusFormLayout.addRow(self.statusButton, self.currentCoordinatesLabel) # # Collect Area # collectCollapsibleButton = ctk.ctkCollapsibleButton() collectCollapsibleButton.text = "Acquire Points" self.layout.addWidget(collectCollapsibleButton) # Layout within the collect collapsible button collectFormLayout = qt.QFormLayout(collectCollapsibleButton) # # Name base line-edit # self.nameBaseLineEdit = qt.QLineEdit() self.nameBaseLineEdit.setToolTip("Fiducials Name Base") collectFormLayout.addRow("Fiducials Name Base:", self.nameBaseLineEdit) # # Single Acquire Button # self.singleAcquireButton = qt.QPushButton("Single Point") self.singleAcquireButton.toolTip = "Acquire a single point at the current position." self.singleAcquireButton.enabled = True collectFormLayout.addRow(self.singleAcquireButton) # # Continuous Acquire Button # self.recordButtonIcon = qt.QIcon(self.PathRecorderModuleDirectoryPath + '/Resources/Icons/icon_Record.png') self.stopButtonIcon = qt.QIcon(self.PathRecorderModuleDirectoryPath + '/Resources/Icons/icon_Stop.png') self.acquireButton = qt.QPushButton("Continuous") self.acquireButton.toolTip = "Start acquiring points continiously." self.acquireButton.enabled = True self.acquireButton.checkable = True self.acquireButton.setIcon(self.recordButtonIcon) #self.acquireButton.setMinimumWidth(80) #self.acquireButton.setMaximumWidth(80) collectFormLayout.addRow(self.acquireButton) # # Distance-based Radio Button # self.distanceBasedButton = qt.QRadioButton("Minimum Distance:") self.distanceBasedButton.setChecked(1) #collectFormLayout.addRow() # Distance slider distanceSlider = ctk.ctkSliderWidget() #distanceSlider.decimals = 0 distanceSlider.minimum = 0.1 distanceSlider.maximum = 100 distanceSlider.suffix = " mm" distanceSlider.value = 1 distanceSlider.toolTip = "Set minimum distance between recorded points" self.distanceSlider = distanceSlider collectFormLayout.addRow("Minimum Distance:", distanceSlider) # # Delete Button # self.deleteButton = qt.QPushButton("Delete") self.deleteButton.toolTip = "Delete all the points." self.deleteButton.enabled = True collectFormLayout.addRow(self.deleteButton) # # Export Area # exportCollapsibleButton = ctk.ctkCollapsibleButton() exportCollapsibleButton.text = "Export Points" self.layout.addWidget(exportCollapsibleButton) # Layout within the dummy collapsible button exportFormLayout = qt.QFormLayout(exportCollapsibleButton) # # Load Button # self.exportDirectoryButton = ctk.ctkDirectoryButton() exportFormLayout.addRow(self.exportDirectoryButton) # # Name base line-edit # self.fileNameBaseLineEdit = qt.QLineEdit() self.fileNameBaseLineEdit.setToolTip("File name base") self.fileNameBaseLineEdit.text = 'PathRecorder' exportFormLayout.addRow("File Name Base:", self.fileNameBaseLineEdit) # # Save Button # saveButtonIcon = qt.QIcon(self.PathRecorderModuleDirectoryPath + '/Resources/Icons/icon_Save.png') self.exportButton = qt.QPushButton() self.exportButton.setIcon(saveButtonIcon) self.exportButton.toolTip = "Save points." self.exportButton.enabled = True exportFormLayout.addRow(self.exportButton) # connections self.inputFiducialsNodeSelector.connect( 'currentNodeChanged(vtkMRMLNode*)', self.setAnnotationHierarchyNode) self.inputTrackerNodeSelector.connect( 'currentNodeChanged(vtkMRMLNode*)', self.setTransformNode) self.distanceBasedButton.connect('toggled(bool)', self.distanceBasedSelected) self.acquireButton.connect('toggled(bool)', self.onAcquireButtonToggled) self.singleAcquireButton.connect('clicked()', self.onSingleAcButtonClicked) self.deleteButton.connect('clicked()', self.onDeleteButtonClicked) self.exportButton.connect('clicked()', self.onExportButtonClicked) #self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) #self.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) # Add vertical spacer self.layout.addStretch(1)
def LABEL_FONT_ITALIC_LARGE(self): return qt.QFont(self.FONT_NAME, self.FONT_SIZE + 2, 10, True)
def LABEL_FONT_ITALIC(self): return qt.QFont(self.FONT_NAME, self.FONT_SIZE, 10, True)
def LABEL_FONT_BOLD(self): return qt.QFont(self.FONT_NAME, self.FONT_SIZE, 100, False)
def setup(self): frame = qt.QFrame() frameLayout = qt.QFormLayout() frame.setLayout(frameLayout) self.parent.layout().addWidget(frame) # Choose directory button to choose the folder for saving the registered image self.directoryButton = qt.QPushButton( "Choose folder with the segmented images") self.directoryButton.setFont(qt.QFont(self.font_type, self.font_size)) self.directoryButton.toolTip = "Choose a folder of .nii or .img/.hdr images of the segmented bones." frameLayout.addWidget(self.directoryButton) self.directoryButton.connect('clicked()', self.onDirectoryButtonClick) frameLayout.addRow(self.directoryButton) # Choose the Output folder button to choose the folder for saving the registered image self.outputDirectoryButton = qt.QPushButton( "Choose folder to save the output training data to") self.outputDirectoryButton.setFont( qt.QFont(self.font_type, self.font_size)) self.outputDirectoryButton.toolTip = "Choose a folder to save the output" frameLayout.addWidget(self.outputDirectoryButton) self.outputDirectoryButton.connect('clicked()', self.onOutputDirectoryButtonClick) frameLayout.addRow(self.outputDirectoryButton) # ICP Registration Collapse button self.ICPCollapsibleButton = ctk.ctkCollapsibleButton() self.ICPCollapsibleButton.setFont( qt.QFont(self.font_type, self.font_size)) self.ICPCollapsibleButton.text = "Iterative Closest Point Registration" self.ICPCollapsibleButton.collapsed = True # Default is to not show frameLayout.addWidget(self.ICPCollapsibleButton) # Layout within the ICP collapsible button self.ICPFormLayout = qt.QFormLayout(self.ICPCollapsibleButton) # Slider for Maximum Iteration Number for ICP registration self.label = qt.QLabel() self.label.setFont(qt.QFont(self.font_type, self.font_size)) self.label.setText("Maximum Iteration Number: ") self.label.setToolTip( "Select the maximum iteration number for the ICP registration.") self.IterationSlider = ctk.ctkSliderWidget() self.IterationSlider.setToolTip( "Select the maximum iteration number for the ICP registration.") self.IterationSlider.minimum = 1 self.IterationSlider.maximum = 200 self.IterationSlider.value = 100 self.IterationSlider.singleStep = 5 self.IterationSlider.tickInterval = 1 self.IterationSlider.decimals = 0 self.IterationSlider.connect('valueChanged(double)', self.onIterationSliderChange) self.ICPFormLayout.addRow(self.label, self.IterationSlider) self.IterationNumber = self.IterationSlider.value # Set default value # Slider for Number of Landmarks for ICP self.label = qt.QLabel() self.label.setFont(qt.QFont(self.font_type, self.font_size)) self.label.setText("ICP Landmark Number: ") self.label.setToolTip( "Select the number of landmarks per surface for the ICP registration." ) self.LandmarkSlider = ctk.ctkSliderWidget() self.LandmarkSlider.setToolTip( "Select the number of landmarks per surface for the ICP registration." ) self.LandmarkSlider.minimum = 50 self.LandmarkSlider.maximum = 1000 self.LandmarkSlider.value = 500 self.LandmarkSlider.singleStep = 10 self.LandmarkSlider.tickInterval = 1 self.LandmarkSlider.decimals = 0 self.LandmarkSlider.connect('valueChanged(double)', self.onLandmarkSliderChange) self.ICPFormLayout.addRow(self.label, self.LandmarkSlider) self.LandmarkNumber = self.LandmarkSlider.value # Set default value # Slider for Maximum RMS Error for ICP self.label = qt.QLabel() self.label.setFont(qt.QFont(self.font_type, self.font_size)) self.label.setText("ICP Maximum RMS Error: ") self.label.setToolTip( "Select the maximum root mean square (RMS) error for determining the ICP registration convergence." ) self.RMS_Slider = ctk.ctkSliderWidget() self.RMS_Slider.setToolTip( "Select the maximum root mean square (RMS) error for determining the ICP registration convergence." ) self.RMS_Slider.minimum = 0.0001 self.RMS_Slider.maximum = 0.05 self.RMS_Slider.value = 0.01 self.RMS_Slider.singleStep = 0.01 self.RMS_Slider.tickInterval = 0.001 self.RMS_Slider.decimals = 3 self.RMS_Slider.connect('valueChanged(double)', self.onRMS_SliderChange) self.ICPFormLayout.addRow(self.label, self.RMS_Slider) self.RMS_Number = self.RMS_Slider.value # Set default value # Slider for choosing the reference bone self.label = qt.QLabel() self.label.setFont(qt.QFont(self.font_type, self.font_size)) self.label.setText("Reference Bone Label: ") self.label.setToolTip( "Select the label of the bone to keep static. This bone will be registered among all the volunteers. Note: Please choose the folder with the segmented images first." ) self.Ref_Bone_Slider = ctk.ctkSliderWidget() self.Ref_Bone_Slider.setToolTip( "Select the label of the bone to keep static. This bone will be registered among all the volunteers. Note: Please choose the folder with the segmented images first." ) self.Ref_Bone_Slider.minimum = 0 self.Ref_Bone_Slider.maximum = 0 self.Ref_Bone_Slider.value = 0 self.Ref_Bone_Slider.singleStep = 1 self.Ref_Bone_Slider.tickInterval = 1 self.Ref_Bone_Slider.decimals = 0 self.Ref_Bone_Slider.connect('valueChanged(double)', self.onRef_Bone_SliderChange) self.ICPFormLayout.addRow(self.label, self.Ref_Bone_Slider) self.ref_label = int(self.Ref_Bone_Slider.value) # Set default value # Radial buttons for the ICP parameters self.radial_button_1 = qt.QRadioButton("Similarity") self.radial_button_1.setFont(qt.QFont(self.font_type, self.font_size)) self.radial_button_1.toggled.connect(self.onICPModeSelect_1) self.ICPFormLayout.addWidget(self.radial_button_1) self.radial_button_2 = qt.QRadioButton("Rigid") self.radial_button_2.setFont(qt.QFont(self.font_type, self.font_size)) self.radial_button_2.setChecked(True) self.radial_button_2.toggled.connect(self.onICPModeSelect_2) self.ICPFormLayout.addWidget(self.radial_button_2) self.radial_button_3 = qt.QRadioButton("Affine") self.radial_button_3.toggled.connect(self.onICPModeSelect_3) self.ICPFormLayout.addWidget(self.radial_button_3) # Text input for choosing which image labels to use self.label = qt.QLabel() self.label.setFont(qt.QFont(self.font_type, self.font_size)) self.label.setText("Image Labels: ") self.label.setToolTip( "Choose several labels to use for creating the training data. Value of -1 uses the default 1 through 9. Otherwise, input should be similar to '1,2,3' to use labels one, two, and three. " ) self.lineedit = qt.QLineEdit() self.lineedit.setFont(qt.QFont(self.font_type, self.font_size)) self.lineedit.setToolTip( "Choose several labels to use for creating the training data. Value of -1 uses the default 1 through 9. Otherwise, input should be similar to '1,2,3' to use labels one, two, and three. " ) self.ICPFormLayout.addRow(self.label, self.lineedit) self.lineedit.setText("-1") # Bone Smoothing Parameters Collapse Button self.SmoothCollapsibleButton = ctk.ctkCollapsibleButton() self.SmoothCollapsibleButton.setFont( qt.QFont(self.font_type, self.font_size)) self.SmoothCollapsibleButton.text = "Smoothing Options" self.SmoothCollapsibleButton.collapsed = True # Default is to not show frameLayout.addWidget(self.SmoothCollapsibleButton) # Layout within the smoothing options collapsible button self.SmoothFormLayout = qt.QFormLayout(self.SmoothCollapsibleButton) # Slider for choosing the number of iterations for bone smoothing self.label = qt.QLabel() self.label.setFont(qt.QFont(self.font_type, self.font_size)) self.label.setText("Smoothing Iterations: ") self.label.setToolTip( "Select the number of iterations for smoothing the bone surface. Higher iterations will smooth more. Lower iterations will have less smoothing." ) self.Bone_Smoothing_Its_Slider = ctk.ctkSliderWidget() self.Bone_Smoothing_Its_Slider.setToolTip( "Select the number of iterations for smoothing the bone surface. Higher iterations will smooth more. Lower iterations will have less smoothing." ) self.Bone_Smoothing_Its_Slider.minimum = 0 self.Bone_Smoothing_Its_Slider.maximum = 30 self.Bone_Smoothing_Its_Slider.value = 10 self.Bone_Smoothing_Its_Slider.singleStep = 1 self.Bone_Smoothing_Its_Slider.tickInterval = 1 self.Bone_Smoothing_Its_Slider.decimals = 0 self.Bone_Smoothing_Its_Slider.connect( 'valueChanged(double)', self.onBone_Smoothing_Its_SliderChange) self.SmoothFormLayout.addRow(self.label, self.Bone_Smoothing_Its_Slider) self.smoothing_iterations = self.Bone_Smoothing_Its_Slider.value # Set default value # Slider for choosing the smoothing relaxation factor self.label = qt.QLabel() self.label.setFont(qt.QFont(self.font_type, self.font_size)) self.label.setText("Relaxation Factor: ") self.label.setToolTip( "Select the relaxation factor for smoothing the bone surfaces. Higher relaxation will smooth the surface more while a lower factor will have less smoothing." ) self.Bone_Smoothing_Relaxation_Slider = ctk.ctkSliderWidget() self.Bone_Smoothing_Relaxation_Slider.setToolTip( "Select the relaxation factor for smoothing the bone surfaces. Higher relaxation will smooth the surface more while a lower factor will have less smoothing." ) self.Bone_Smoothing_Relaxation_Slider.minimum = 0 self.Bone_Smoothing_Relaxation_Slider.maximum = 1 self.Bone_Smoothing_Relaxation_Slider.value = 0.4 self.Bone_Smoothing_Relaxation_Slider.singleStep = 0.1 self.Bone_Smoothing_Relaxation_Slider.tickInterval = 0.1 self.Bone_Smoothing_Relaxation_Slider.decimals = 2 self.Bone_Smoothing_Relaxation_Slider.connect( 'valueChanged(double)', self.onBone_Smoothing_Relaxation_SliderChange) self.SmoothFormLayout.addRow(self.label, self.Bone_Smoothing_Relaxation_Slider) self.relaxation_factor = self.Bone_Smoothing_Relaxation_Slider.value # Set default value # Slider for choosing the percentage of bone surface decimation self.label = qt.QLabel() self.label.setFont(qt.QFont(self.font_type, self.font_size)) self.label.setText("Surface Decimation: ") self.label.setToolTip( "Select the ratio of verticies to remove from the bone surface. This results in a smoother surface and less points for faster computation. Too much could cause surface artifacts. For example, 0.1 removes 10 percent while 0.9 removes 90 percent of points." ) self.Bone_Decimate_Slider = ctk.ctkSliderWidget() self.Bone_Decimate_Slider.setToolTip( "Select the ratio of verticies to remove from the bone surface. This results in a smoother surface and less points for faster computation. Too much could cause surface artifacts. For example, 0.1 removes 10 percent while 0.9 removes 90 percent of points." ) self.Bone_Decimate_Slider.minimum = 0 self.Bone_Decimate_Slider.maximum = 0.9 self.Bone_Decimate_Slider.value = 0 self.Bone_Decimate_Slider.singleStep = 0.05 self.Bone_Decimate_Slider.tickInterval = 0.05 self.Bone_Decimate_Slider.decimals = 2 self.Bone_Decimate_Slider.connect('valueChanged(double)', self.onBone_Decimate_SliderChange) self.SmoothFormLayout.addRow(self.label, self.Bone_Decimate_Slider) self.decimate_surface = self.Bone_Decimate_Slider.value # Set default value # Debugging Collapse button self.RenderingCollapsibleButton = ctk.ctkCollapsibleButton() self.RenderingCollapsibleButton.setFont( qt.QFont(self.font_type, self.font_size)) self.RenderingCollapsibleButton.text = "Visualization" self.RenderingCollapsibleButton.collapsed = True # Default is to not show frameLayout.addWidget(self.RenderingCollapsibleButton) # Layout within the debug collapsible button self.CollapseFormLayout = qt.QFormLayout( self.RenderingCollapsibleButton) # Show the registered shapes toggle button self.show_registered_shapes = qt.QCheckBox("Show Registered Shapes") self.show_registered_shapes.setFont( qt.QFont(self.font_type, self.font_size)) self.show_registered_shapes.toolTip = "When checked, show each registered bone. Useful for debugging any ICP registration based errors." self.show_registered_shapes.checked = False self.CollapseFormLayout.addWidget(self.show_registered_shapes) # Show the registered shapes toggle button self.show_extracted_shapes = qt.QCheckBox("Show Extracted Shapes") self.show_extracted_shapes.setFont( qt.QFont(self.font_type, self.font_size)) self.show_extracted_shapes.toolTip = "When checked, show the initial surfaces from the images. Useful for debugging errors based on deriving surfaces from the MR images." self.show_extracted_shapes.checked = False self.CollapseFormLayout.addWidget(self.show_extracted_shapes) # Show the loaded images toggle button self.debug_show_images = qt.QCheckBox("Show Loaded Images") self.debug_show_images.setFont(qt.QFont(self.font_type, self.font_size)) self.debug_show_images.toolTip = "When checked, show the loaded images. Useful for debugging if the images are flipped or loading incorrectly." self.debug_show_images.checked = False self.CollapseFormLayout.addWidget(self.debug_show_images) # Debugging Collapse button self.DebugCollapsibleButton = ctk.ctkCollapsibleButton() self.DebugCollapsibleButton.setFont( qt.QFont(self.font_type, self.font_size)) self.DebugCollapsibleButton.text = "Debugging" self.DebugCollapsibleButton.collapsed = True # Default is to not show frameLayout.addWidget(self.DebugCollapsibleButton) # Layout within the debug collapsible button self.CollapseFormLayout = qt.QFormLayout(self.DebugCollapsibleButton) # Show the flip image vertically toggle button self.flip_image_vertically = qt.QCheckBox("Flip Vertically") self.flip_image_vertically.setFont( qt.QFont(self.font_type, self.font_size)) self.flip_image_vertically.toolTip = "When checked, flip the images vertically after loading them." self.flip_image_vertically.checked = False self.CollapseFormLayout.addWidget(self.flip_image_vertically) # Show the flip image horizontally toggle button self.flip_image_horizontally = qt.QCheckBox("Flip Horizontally") self.flip_image_horizontally.setFont( qt.QFont(self.font_type, self.font_size)) self.flip_image_horizontally.toolTip = "When checked, flip the images horizontally after loading them." self.flip_image_horizontally.checked = False self.CollapseFormLayout.addWidget(self.flip_image_horizontally) # Show the save bones separately toggle button self.Save_Extracted_Bones_Separately = qt.QCheckBox( "Save Extracted Bones Separately") self.Save_Extracted_Bones_Separately.setFont( qt.QFont(self.font_type, self.font_size)) self.Save_Extracted_Bones_Separately.toolTip = "When checked, save each bone surface separately after smoothing and before any registration." self.Save_Extracted_Bones_Separately.checked = False self.CollapseFormLayout.addWidget(self.Save_Extracted_Bones_Separately) # Show the save bones separately toggle button self.Save_Registered_Bones_Separately = qt.QCheckBox( "Save Registered Bones Separately") self.Save_Registered_Bones_Separately.setFont( qt.QFont(self.font_type, self.font_size)) self.Save_Registered_Bones_Separately.toolTip = "When checked, save each bone surface separately after smoothing and registration (instead of combining all the bones for each volunteer/position together)." self.Save_Registered_Bones_Separately.checked = False self.CollapseFormLayout.addWidget( self.Save_Registered_Bones_Separately) # Skip the registration self.Skip_Registration = qt.QCheckBox("Skip Registration Steps") self.Skip_Registration.setFont(qt.QFont(self.font_type, self.font_size)) self.Skip_Registration.toolTip = "When checked, extract each bone surface from the image and smooth the surface (this is useful if the user only wishes to extract the bones from the images and smooth them.) Consider using along with the save extracted bones setting." self.Skip_Registration.checked = False self.CollapseFormLayout.addWidget(self.Skip_Registration) # Don't save the reference bone toggle button self.Remove_Ref_Bone = qt.QCheckBox("Remove the reference bone") self.Remove_Ref_Bone.setFont(qt.QFont(self.font_type, self.font_size)) self.Remove_Ref_Bone.toolTip = "When checked, don't save the refernce bone when saving the PLY file. For example, this is useful if using the radius as a reference bone, but if you don't want it to appear in the final model." self.Remove_Ref_Bone.checked = False self.CollapseFormLayout.addWidget(self.Remove_Ref_Bone) # Choose the number of files to load from the given folder self.label = qt.QLabel() self.label.setFont(qt.QFont(self.font_type, self.font_size)) self.label.setText("Number of images: ") self.label.setToolTip( "Select how many images to use from the given folder. (Select the folder first). This is useful if want want to use just the first few images to make sure everything runs correctly." ) self.NumFileSlider = ctk.ctkSliderWidget() self.NumFileSlider.setToolTip( "Select how many images to use from the given folder. (Select the folder first). This is useful if want want to use just the first few images to make sure everything runs correctly." ) self.NumFileSlider.minimum = -1 self.NumFileSlider.maximum = 1 self.NumFileSlider.value = -1 self.NumFileSlider.singleStep = 1 self.NumFileSlider.tickInterval = 1 self.NumFileSlider.decimals = 0 self.NumFileSlider.connect('valueChanged(double)', self.onNumSliderChange) self.CollapseFormLayout.addRow(self.label, self.NumFileSlider) self.num_files = self.NumFileSlider.value # Set default value # Compute button self.computeButton = qt.QPushButton("Create The Training Data") self.computeButton.setFont(qt.QFont(self.font_type, self.font_size)) self.computeButton.toolTip = "Run the module and create the training data for the PCA bone displacement model." frameLayout.addWidget(self.computeButton) self.computeButton.connect('clicked()', self.onCompute) self.computeButton.enabled = False # Progress Bar (so the user knows how much longer it will take) self.progressBar = qt.QProgressBar() self.progressBar.setFont(qt.QFont(self.font_type, self.font_size)) self.progressBar.setValue(0) frameLayout.addWidget(self.progressBar) self.progressBar.hide()
def __init__(self, parent, *args, **kwargs): """ Init function. """ super(FingerTabWidget, self).__init__(parent) #-------------------- # Define sizing parameters. #-------------------- self.marginVal = 5 self.currentIndex = 0 self.tabWidth = 120 #-------------------- # Make and style 'tabColumn', which is a qFrame. #-------------------- self.tabColumn = qt.QFrame(self) self.tabColumn.setFixedWidth(self.tabWidth) self.tabColumn.setObjectName('tabColumn') self.tabColumn.setStyleSheet('#tabColumn {background:#E8E8E8 ; height: 4000px;' + 'border-right-width: 1px; border-right-color: gray;' + 'border-right-style: solid; margin-top: 5px;' + 'margin-left: 5px; margin-bottom: 5px}') #-------------------- # Define the layout of the 'tabColumn' qFrame, # set the layout to the 'tabColumn' qFrame. #-------------------- self.tabColumnLayout = qt.QVBoxLayout() self.tabColumnLayout.setContentsMargins(0,0,0,0) self.tabColumnLayout.setSpacing(0) self.tabColumnLayout.addStretch() self.tabColumn.setLayout(self.tabColumnLayout) #-------------------- # Define the 'innerWindowLayout'. #-------------------- self.innerWindowLayout = qt.QStackedLayout() self.innerWindowLayout.setStackingMode(1) self.innerWindowLayout.setSpacing(0) self.innerWindowLayout.setContentsMargins(0,0,0,0) #-------------------- # Define the 'widgetStack' object, which takes # the whole span of the window. #-------------------- self.widgetStack = qt.QWidget(self) self.widgetStack.setObjectName("widgetStack") self.widgetStack.setStyleSheet("#widgetStack{ border: none; background: transparent}") #-------------------- # The layout for the 'widgetStack' is # 'widgetStackLayout', which is an HBoxLayout. We set # a left spacing the length of the tabs-1 to accomodate for the border # and tabs of the widget. #-------------------- self.widgetStackLayout = qt.QHBoxLayout() self.widgetStackLayout.setContentsMargins(0,self.marginVal,self.marginVal,self.marginVal) self.widgetStackLayout.addSpacing(self.tabWidth - 1) self.widgetStack.setLayout(self.widgetStackLayout) #-------------------- # Define the 'tabPageStack', add to the widgetStackLayout. # # NOTE: The 'tabPageStack' is the stacked layout were all # of the tab pages reside. #-------------------- self.tabPageStack = qt.QStackedLayout() self.widgetStackLayout.addLayout(self.tabPageStack) #-------------------- # Define the tabButtons as part of a # button group, for easier event listening. # # Set their styles as well. #-------------------- self.buttonGroup = qt.QButtonGroup(self) self.buttonGroup.connect('buttonClicked(QAbstractButton*)', self.onTabClicked) self.tabButtons = [] self.tabWidgets = [] self.tabObjectName = 'fingerTab' self.tabToggledStyle = '#fingerTab {border: 1px solid gray; border-right-width: 1px; border-right-color: white; background-color: white;}' self.tabUntoggledStyle ='#fingerTab {border: 1px solid #D0D0D0; border-right-width: 1px; border-right-color: gray; background-color: #C0C0C0;}' self.tabToggledFont = qt.QFont('Arial', 12, 100, False) self.tabUntoggledFont = qt.QFont('Arial', 12, 25, False) #-------------------- # Add 'tabColumn' and 'widgetStack' to 'innerWindowLayout'. Set the current # index of the widgetStack (this will allow for the black # borders between the tabs and the windows to connect). #-------------------- self.innerWindowLayout.addWidget(self.tabColumn) self.innerWindowLayout.addWidget(self.widgetStack) self.innerWindowLayout.setCurrentIndex(1) #-------------------- # Set 'mainWidgetLayout' to hold the 'innerWindowLayout'. # The 'mainWidgetLayout' exists because subclasses of # 'FingerTabWidget' and others that use it can add # further rows to the window (such as 'Done' and 'Cancel' # buttons). #-------------------- self.mainWidgetLayout = qt.QVBoxLayout() self.mainWidgetLayout.setContentsMargins(5,5,5,5) self.mainWidgetLayout.addLayout(self.innerWindowLayout) #-------------------- # Set the primary layout to the 'mainWidgetLayout' #-------------------- self.setLayout(self.mainWidgetLayout)
class Settings_Hosts(Settings): """ Settings_Hosts is the Settings pertaining to tracking and saving the various XnatHosts, and also saving these settings to the XnatSlicerFile. All 'Settings' subclasses are to be displaed in the 'SettingsWindow' class. """ FONT_NAME = "Arial" FONT_SIZE = 10 FONT = qt.QFont(FONT_NAME, FONT_SIZE, 10, False) FONT_ITALIC = qt.QFont(FONT_NAME, FONT_SIZE, 10, True) PERMANENT_HOSTS = { 'Central': { 'url': 'https://central.xnat.org', 'username': '' } } DEFAULT_HOSTS = {'CNDA': {'url': 'https://cnda.wustl.edu', 'username': ''}} DEFAULT_HOSTS = dict(DEFAULT_HOSTS.items() + PERMANENT_HOSTS.items()) def setup(self): """ Creates the necessary widgets for the Setting. """ #-------------------- # Add section Label #-------------------- bLabel = qt.QLabel('Manage Hosts') self.masterLayout.addWidget(bLabel) self.masterLayout.addSpacing(8) #-------------------- # The currModal variable # tracks the various input modals related # to entering and deleting hosts. #-------------------- self.currModal = None #-------------------- # Add Host table (class below) #-------------------- self.hostTable = HostTable(clickCallback = \ self.__onHostRowClicked) #-------------------- # Shared popup objects. # The function that creates them # are outside of the scope of the class # and are made by a UI-making function below. #-------------------- self.lineEdits, \ self.errorLines, \ self.checkBoxes = makeSharedHostModalObjects(self) self.lineEdits['hostname'].connect('textChanged(const QString)', self.__onHostNameLineChanged) #-------------------- # Add Buttons and connect their events. # Like the variables above, they are created in a # separate UI function. #-------------------- self.addButton, self.editButton, self.deleteButton = makeButtons(self) self.addButton.connect('clicked()', self.__showAddHostModal) self.editButton.connect('clicked()', self.__showEditHostModal) self.deleteButton.connect('clicked()', self.__showDeleteHostModal) #-------------------- # Make frame for setup window #-------------------- self.__makeFrame() #-------------------- # Set layout for entire frame and # its aesthetics. #-------------------- self.frame.setLayout(self.masterLayout) self.setWidget(self.frame) self.frame.setMinimumWidth(600) self.frame.setMaximumWidth(10000) #-------------------- # Load hosts into host list #-------------------- self.__loadHosts() def __onHostRowClicked(self): """ Callback for when a user clicks on a given item within the host editor. """ try: self.__setButtonStates(self.hostTable.currentRowItems['name']) except: #print "No row items selected" return def __setButtonStates(self, hostName=None): """ Enables / Disables button based upon the editable quality of the host (provided by the 'hostName' argument). Some hosts cannot be modified. @param hostName: The name of the host to to apply the changes to. @type hostName: str """ self.deleteButton.setEnabled(not hostName in self.PERMANENT_HOSTS) self.editButton.setEnabled(True) def __loadHosts(self): """ Loads the hosts into the table widget. """ #MokaUtils.debug.lf("LOAD HOSTS") #-------------------- # Empty host table in the editor. #-------------------- self.hostTable.clear() #-------------------- # Get host dictionary from Settings #-------------------- hostDictionary = self.SettingsFile.getHostsDict() #-------------------- # Iterate through dictionary and apply text to the host table. #-------------------- for name in hostDictionary: # # Add name and URL to host table. # self.hostTable.addNameAndUrl(name, hostDictionary[name]) # # Get curr username # currName = self.SettingsFile.getCurrUsername(name) # # If there's a username, add it to the hostTable # if len(currName) > 0: self.hostTable.addUsername(currName) def __stylizeErrorString(self, string): """ Retruns a stylzed error string. @param string: The string to stylize. @type string: str @return: The stylized string. @rtype: str """ return '<font color=\"red\"><i>* %s</i></font>' % (string) def __onHostNameLineChanged(self, string): """ As stated. @param string: The string of the hostname line. @type string: str """ if not self.__validateHostName(): if hasattr(self, 'saveButtons'): for key, button in self.saveButtons.iteritems(): button.setEnabled(False) return if hasattr(self, 'saveButtons'): for key, button in self.saveButtons.iteritems(): button.setEnabled(True) def __validateHostName(self): """ As stated. @return: The whether the host name is valid. @rtype: bool """ nameLine = self.lineEdits['hostname'].text.strip("") if self.hostExists(nameLine): errorString = 'Host name \'%s\' is already taken.' % (nameLine) errorString = self.__stylizeErrorString(errorString) self.errorLines['hostname'].setText(errorString) return False self.errorLines['hostname'].setText('') return True def modifyHost(self): """ As stated. """ #MokaUtils.debug.lf() self.currModal.close() hostName = self.lineEdits['hostname'].text.strip() self.__setNonCriticalSettings() self.writeHost() self.Events.runEventCallbacks('SETTINGS_FILE_MODIFIED', self.__class__.__name__, 'HOST_MODIFIED', hostName) def __setNonCriticalSettings(self): """ """ #-------------------- # Set host to default if checkbox is checked. # 'Default' means it will be the host that is # selected automatically on loadup. #-------------------- if self.checkBoxes['setdefault'].isChecked(): self.SettingsFile.setDefault(self.lineEdits['hostname'].text) #-------------------- # Set hosts associated username accordingly. #-------------------- if len(self.lineEdits['username'].text.strip()) != 0: self.SettingsFile.setCurrUsername(self.lineEdits['hostname'].text, self.lineEdits['username'].text) def deleteHost(self): """ Removes the host from the settings file and then reloads the HostTable, which refers to the SettingsFile. """ #MokaUtils.debug.lf() #-------------------- # Delete the selected host by # removing it from the settings. #-------------------- hostStr = self.hostTable.currentRowItems deleted = self.SettingsFile.deleteHost(hostStr['name']) #-------------------- # Reload all hosts back into the table # from the SettingsFile. #-------------------- if deleted: self.__loadHosts() #-------------------- # Close popup #-------------------- self.currModal.close() self.currModal = None self.Events.runEventCallbacks('SETTINGS_FILE_MODIFIED', self.__class__.__name__, 'HOST_DELETED', hostStr['name']) def hostExists(self, hostName): """ @param hostName: The host name to check @type hostName: str @return: Whether the host name exists. @rtype: bool """ for rowDict, item in self.hostTable.trackedItems.iteritems(): if item['name'].text() == hostName: return True return False def writeHost(self, runEvents=True): """ Writes the host both to the SettingsFile, then reloads the hosts from the file. @param runEvents: Option to run event callbacks. @type runEvents: bool """ #print "write host" #-------------------- # Close popup #-------------------- self.currModal.close() self.currModal = None #-------------------- # Determine if enetered host was set to default, # which means it will be loaded up on startup. #-------------------- modifiable = self.lineEdits['hostname'] in self.PERMANENT_HOSTS modStr = str(modifiable) checkStr = str(self.checkBoxes['setdefault'].isChecked()) #-------------------- # Save Host to SettingsFile. #-------------------- self.SettingsFile.saveHost(self.lineEdits['hostname'].text, self.lineEdits['url'].text, isModifiable = modifiable, isDefault = self.checkBoxes['setdefault'].\ isChecked()) self.__setNonCriticalSettings() #-------------------- # Reload hosts from the SettingsFile. #-------------------- #self.Events.runEventCallbacks('HOSTADDED') self.__loadHosts() if runEvents: self.Events.runEventCallbacks('SETTINGS_FILE_MODIFIED', self.__class__.__name__, 'HOST_ADDED', self.lineEdits['hostname'].text) def updateFromSettings(self): """ Callback function for when the settings file changes. """ #MokaUtils.debug.lf() #MokaUtils.debug.lf("UPDATE", self.__class__.__name__) self.__loadHosts() def __showEditHostModal(self): """ Shows the modal that prompts the user to edit a given host. """ #MokaUtils.debug.lf() self.currModal = makeEditHostModal(self) self.currModal.setWindowModality(1) self.currModal.show() for key, line in self.errorLines.iteritems(): line.setText('') def __showDeleteHostModal(self, message=None): """ Shows the modal that prompts the user to delete a given host. """ #MokaUtils.debug.lf() self.currModal = makeDeleteHostModal(self) self.currModal.show() def __showAddHostModal(self): """ Shows the modal that prompts the user to add a given host. """ #MokaUtils.debug.lf() self.currModal = makeAddHostModal(self) self.currModal.show() def __makeFrame(self): """ Makes the widget frame. """ #MokaUtils.debug.lf() #-------------------- # Layout for top part of frame (host list) #-------------------- self.masterLayout.addWidget(self.hostTable) #-------------------- # Layout for bottom part of frame (buttons) #-------------------- buttonLayout = qt.QHBoxLayout() buttonLayout.addStretch() buttonLayout.addWidget(self.addButton) buttonLayout.addWidget(self.editButton) buttonLayout.addWidget(self.deleteButton) self.masterLayout.addLayout(buttonLayout)
class XnatDownloadPopup(XnatEmptyPopup): """ Subclass of the Popup class pertaining specifically to downloading files. """ FONT_NAME = 'Arial' FONT_SIZE = 10 LABEL_FONT = qt.QFont(FONT_NAME, FONT_SIZE, 10, False) def __init__(self, title="XNAT Download Queue", memDisplay="MB"): """ @param title: The window title. @type title: string @param memDisplay: The memory value to display. @type memDisplay: string """ super(XnatDownloadPopup, self).__init__(title=title) self.memDisplay = memDisplay self.downloadRows = {} self.setFixedWidth(710) self.setMinimumHeight(300) self.setStyleSheet('padding: 0px') self.innerWidget = None self.innerWidgetLayout = None self.scrollWidget = None self.masterLayout.setContentsMargins(0, 0, 0, 0) self.hide() self.cancelCallback = None self.rowWidgetHeight = 95 def setCancelCallback(self, callback): """ """ self.cancelCallback = callback def addDownloadRow(self, uri, size=-1): """ Constructs a download row object based on the URI """ #------------------- # Cancel button row #------------------- rowWidget = qt.QWidget() rowWidget.setObjectName('downloadRowWidget') rowWidget.setStyleSheet( '#downloadRowWidget {border: 1px ' + ' solid rgb(160,160,160); border-radius: 2px; width: 100%;}') #rowWidget.setFixedHeight(self.rowWidgetHeight) #rowWidget.setSizePolicy(qt.QSizePolicy.MinimumExpanding, # qt.QSizePolicy.MinimumExpanding) layout = qt.QVBoxLayout() rowWidget.setLayout(layout) #------------------- # Text Edit #------------------- textEdit = qt.QTextEdit() textEdit.setStyleSheet("border: none") textEdit.setFixedHeight(55) textEdit.verticalScrollBar().hide() textEdit.setFont( qt.QFont(XnatDownloadPopup.FONT_NAME, XnatDownloadPopup.FONT_SIZE, 10, False)) layout.addWidget(textEdit) #------------------- # Progress Bar #------------------- progressBar = qt.QProgressBar(rowWidget) progressBar.setFixedHeight(17) progressBar.setFixedWidth(600) progressBar.setMinimum(0) progressBar.setMaximum(100) progressBar.setAlignment(0x0084) #------------------- # Cancel button row #------------------- cancelButton = qt.QPushButton() cancelButton.setText("Cancel") cancelButton.setFont(XnatDownloadPopup.LABEL_FONT) cancelButton.setFixedWidth(60) cancelButton.setFixedHeight(19) #------------------- # Progress bar row #------------------- progressRow = qt.QHBoxLayout() progressRow.addWidget(progressBar) progressRow.addStretch() progressRow.addWidget(cancelButton) layout.addLayout(progressRow) #------------------- # Row dict #------------------- downloadRow = { 'queuePosition': len(self.downloadRows), 'size': 0, 'downloaded': 0, 'textEdit': textEdit, 'pathDict': XnatSlicerUtils.getXnatPathDict(uri), 'progressBar': progressBar, 'widget': rowWidget, 'cancelButton': cancelButton } #------------------- # default text #------------------- dlStr = self.makeDownloadPath(downloadRow['pathDict']) textEdit.setText("QUEUED<br>%s<br>Please wait...<br>" % (dlStr)) #------------------- # Cancel callback #------------------- def cancelClick(): rowWidget.setEnabled(False) #print "Cancelling download '%s'"%(dlStr) textEdit.setText(textEdit.toHtml().replace('DOWNLOADING', 'CANCELLED')) for key, item in self.downloadRows.iteritems(): if item['progressBar'] == progressBar: item['progressBar'].setEnabled(False) item['progressBar'].setMaximum(100) self.cancelCallback(key) cancelButton.connect('pressed()', cancelClick) self.downloadRows[uri] = downloadRow self.remakeWidget() def remakeWidget(self): """ Ideally, this would be unncessary. But, since QScrollArea doesn't dynamically update, we have to update this ourselves. """ #------------------- # Clear all of the inner widgets #------------------- if self.innerWidget: del self.innerWidget if self.innerWidgetLayout: del self.innerWidgetLayout if self.scrollWidget: del self.scrollWidget #------------------- # Reset the inner widget layout #------------------- self.innerWidgetLayout = qt.QFormLayout() self.innerWidgetLayout.setVerticalSpacing(10) #------------------- # Sort download rows by their queue positions, # add them to the innerWidgetLayout. #------------------- sortedRows = [None] * len(self.downloadRows) for key, item in self.downloadRows.iteritems(): #print len(sortedRows), item['queuePosition'] sortedRows[item['queuePosition']] = key for key in sortedRows: self.innerWidgetLayout.addRow(self.downloadRows[key]['widget']) #------------------- # Remake the inner widget #------------------- self.innerWidget = qt.QWidget() self.innerWidget.setLayout(self.innerWidgetLayout) self.innerWidget.setObjectName('innerWidget') self.innerWidget.setStyleSheet('#innerWidget {width: 100%;}') self.innerWidget.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.MinimumExpanding) #------------------- # Remake the scroll widget #------------------- self.scrollWidget = qt.QScrollArea() self.scrollWidget.setWidget(self.innerWidget) self.scrollWidget.verticalScrollBar().setStyleSheet('width: 15px') self.scrollWidget.setObjectName('scrollWidget') self.scrollWidget.setStyleSheet('#scrollWidget {border: none}') self.scrollWidget.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.MinimumExpanding) self.scrollWidget.setWidgetResizable(True) #------------------- # Clear the master widget and add the new contents. #------------------- delWidget = self.masterLayout.itemAt(0) while (delWidget): self.masterLayout.removeItem(delWidget) del delWidget delWidget = self.masterLayout.itemAt(0) self.innerWidget.update() self.masterLayout.addRow(self.scrollWidget) self.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.MinimumExpanding) calcHeight = (self.rowWidgetHeight + 12) * len(self.downloadRows) if calcHeight < 800: self.setMinimumHeight(calcHeight) else: self.setMinimumHeight(800) self.update() def setText(self, uriKey, text): """ """ self.downloadRows[uriKey]['textEdit'].setText(text) #added by qwaddles def inDownloadRows(self, uriKey): uriBreakdown = uriKey.split("/") if uriKey in self.downloadRows: return uriKey else: for key in self.downloadRows: if self.downloadRows[key]['pathDict'][ 'subjects'] in uriBreakdown and self.downloadRows[key][ 'pathDict'][ 'experiments'] in uriBreakdown and self.downloadRows[ key]['pathDict'][ 'projects'] in uriBreakdown: return key return False # modified by qwaddles def setSize(self, uriKey, size=-1): """ """ print self.downloadRows print("######### size = %d ########" % size) key = self.inDownloadRows(uriKey) print("######### key ###########") print(key) if key != False: if size > -1: self.downloadRows[key]['size'] = self.recalcMem(size) self.downloadRows[key]['progressBar'].setMaximum(100) else: self.downloadRows[key]['progressBar'].setMinimum(0) self.downloadRows[key]['progressBar'].setMaximum(0) def makeDownloadPath(self, pathDict): """ """ if isinstance(pathDict, basestring): pathDict = self.downloadRows[pathDict]['pathDict'] dlStr = '' for level in Xnat.path.DEFAULT_LEVELS: if level in pathDict and str(pathDict[level]) != 'None': dlStr += "<b>%s:</b> %s " % (level, pathDict[level]) return dlStr # modified by Qwaddles def updateDownload(self, uriKey, downloaded=0): """ """ key = self.inDownloadRows(uriKey) if key != False: self.downloadRows[key]['downloaded'] = self.recalcMem(downloaded) downloadSize = str(self.downloadRows[key]['size']) + 'MB' if downloadSize == '0MB': downloadSize = '[Unknown Size]' self.downloadRows[key]['textEdit'].setText(\ "DOWNLOADING<br>%s<br>%sMB out of %s<br>"%(\ self.makeDownloadPath(\ self.downloadRows[key]['pathDict']), self.downloadRows[key]['downloaded'], downloadSize)) if self.downloadRows[key]['size'] > 0: self.downloadRows[key]['progressBar'].setValue(\ (self.downloadRows[key]['downloaded'] \ / self.downloadRows[key]['size']) * 100) else: self.downloadRows[key]['progressBar'].setValue(\ self.downloadRows[key]['downloaded']) def changeRowKey(self, oldKey, newKey): """ """ self.downloadRows[newKey] = self.downloadRows.pop(oldKey) def resizeEvent(self): """ Overloaded callback when the user resizes the download popup window. """ if self.scrollWidget != None: self.scrollWidget.resize(self.width, self.height) def abbreviateFile(self, filename): """ """ maxLen = 55 return filename if len(filename) < maxLen else '...' + \ filename[-1 * (maxLen-3):] def setCancelled(self, uriKey): """ Updates the relevant download row to the cancelled state. @param uriKey: The key referring to the download row. @type uriKey: str """ self.downloadRows[uriKey]['widget'].setEnabled(False) self.downloadRows[uriKey]['textEdit'].setText("CANCELLED<br><i>%s</i>"\ %(self.makeDownloadPath(self.downloadRows[uriKey]['pathDict']))) # modified by Qwaddles def setFinished(self, uriKey): """ Updates the relevant download row to the complete state. @param uriKey: The key referring to the download row. @type uriKey: str """ key = self.inDownloadRows(uriKey) if key != False: self.downloadRows[key]['widget'].setEnabled(False) self.downloadRows[key]['textEdit'].setText("FINISHED<br><i>%s</i>"\ %(self.makeDownloadPath(self.downloadRows[key]['pathDict']))) self.setProgressBarValue(key, 100) def setEnabled(self, uriKey, enabled=True): """ """ self.downloadRows[uriKey]['widget'].setEnabled(enabled) def setProgressBarValue(self, uriKey, value, _min=0, _max=100): """ """ self.downloadRows[uriKey]['progressBar'].setMinimum(_min) self.downloadRows[uriKey]['progressBar'].setMaximum(_max) self.downloadRows[uriKey]['progressBar'].setValue(value) def recalcMem(self, size): """ For toggling between MB display and byte display. """ if (self.memDisplay.lower() == 'mb'): return math.ceil(MokaUtils.convert.bytesToMB(size) * 100) / 100 return size def setDownloadFileSize(self, uriKey, size): """ Descriptor """ if size: self.downloadRows[uriKey]['size'] = size self.downloadRows[uriKey]['progressBar'].setMinimum(0) self.downloadRows[uriKey]['progressBar'].setMaximum(100)
def LABEL_FONT_LARGE(self): return qt.QFont(self.FONT_NAME, self.FONT_SIZE + 2, 10, False)
def addDownloadRow(self, uri, size=-1): """ Constructs a download row object based on the URI """ #------------------- # Cancel button row #------------------- rowWidget = qt.QWidget() rowWidget.setObjectName('downloadRowWidget') rowWidget.setStyleSheet( '#downloadRowWidget {border: 1px ' + ' solid rgb(160,160,160); border-radius: 2px; width: 100%;}') #rowWidget.setFixedHeight(self.rowWidgetHeight) #rowWidget.setSizePolicy(qt.QSizePolicy.MinimumExpanding, # qt.QSizePolicy.MinimumExpanding) layout = qt.QVBoxLayout() rowWidget.setLayout(layout) #------------------- # Text Edit #------------------- textEdit = qt.QTextEdit() textEdit.setStyleSheet("border: none") textEdit.setFixedHeight(55) textEdit.verticalScrollBar().hide() textEdit.setFont( qt.QFont(XnatDownloadPopup.FONT_NAME, XnatDownloadPopup.FONT_SIZE, 10, False)) layout.addWidget(textEdit) #------------------- # Progress Bar #------------------- progressBar = qt.QProgressBar(rowWidget) progressBar.setFixedHeight(17) progressBar.setFixedWidth(600) progressBar.setMinimum(0) progressBar.setMaximum(100) progressBar.setAlignment(0x0084) #------------------- # Cancel button row #------------------- cancelButton = qt.QPushButton() cancelButton.setText("Cancel") cancelButton.setFont(XnatDownloadPopup.LABEL_FONT) cancelButton.setFixedWidth(60) cancelButton.setFixedHeight(19) #------------------- # Progress bar row #------------------- progressRow = qt.QHBoxLayout() progressRow.addWidget(progressBar) progressRow.addStretch() progressRow.addWidget(cancelButton) layout.addLayout(progressRow) #------------------- # Row dict #------------------- downloadRow = { 'queuePosition': len(self.downloadRows), 'size': 0, 'downloaded': 0, 'textEdit': textEdit, 'pathDict': XnatSlicerUtils.getXnatPathDict(uri), 'progressBar': progressBar, 'widget': rowWidget, 'cancelButton': cancelButton } #------------------- # default text #------------------- dlStr = self.makeDownloadPath(downloadRow['pathDict']) textEdit.setText("QUEUED<br>%s<br>Please wait...<br>" % (dlStr)) #------------------- # Cancel callback #------------------- def cancelClick(): rowWidget.setEnabled(False) #print "Cancelling download '%s'"%(dlStr) textEdit.setText(textEdit.toHtml().replace('DOWNLOADING', 'CANCELLED')) for key, item in self.downloadRows.iteritems(): if item['progressBar'] == progressBar: item['progressBar'].setEnabled(False) item['progressBar'].setMaximum(100) self.cancelCallback(key) cancelButton.connect('pressed()', cancelClick) self.downloadRows[uri] = downloadRow self.remakeWidget()
class LoginMenu(qt.QWidget): """ LoginMenu is the class that handles all of the UI to the XnatIo related to logging in to a given XNAT host. Handles UI for loggin into XNAT as well as settings by linking to button clicks to external methods in the XnatIo. """ FONT_NAME = "Arial" FONT_SIZE = 10 LABEL_FONT = qt.QFont(FONT_NAME, FONT_SIZE, 10, False) LABEL_FONT_BOLD = qt.QFont(FONT_NAME, FONT_SIZE, 100, False) LABEL_FONT_ITALIC = qt.QFont(FONT_NAME, FONT_SIZE, 10, True) EVENT_TYPES = ['HOSTSELECTED', 'MANAGEHOSTSCLICKED'] def __init__(self, parent=None, MODULE=None, Setting=None): """ @param parent: The parent widget to attach to. @type parent: qt.QWidget @param MODULE: The XNATSlicer module @type MODULE: XnatSlicerWidget """ super(LoginMenu, self).__init__(self) self.MODULE = MODULE self.Setting = Setting #-------------------- # Set relevant variables. #-------------------- self.currHostUrl = None self.currHostName = None self.currHostAddress = None self.XnatHosts = None self.hostLoggedIn = False self.defaultPasswordText = "Password" self.defaultUsernameText = "Login" #-------------------- # Create Username and password lines #-------------------- self.usernameLabel, self.passwordLabel, \ self.usernameLine, self.passwordLine = makeCredentialsWidgets(self) #-------------------- # Create login button #-------------------- self.loginButton = makeLoginButton(self) #-------------------- # Create host dropdown. #-------------------- self.hostDropdown = makeHostDropdown(self) #-------------------- # Create settings button. #-------------------- self.manageHostsButton = makeManageHostsButton(self) #-------------------- # Create login layout. #-------------------- self.loginLayout = makeLoginLayout(self) #-------------------- # Set event connections. #-------------------- self.usernameLine.installEventFilter(self) self.usernameLine.setObjectName("XnatUsernameLine") self.passwordLine.installEventFilter(self) self.passwordLine.setObjectName("XnatPasswordLine") self.passwordLine.connect('returnPressed()', self.simulateLoginClicked) self.hostDropdown.connect('currentIndexChanged(const QString&)', self.__onHostSelected) self.manageHostsButton.connect('pressed()', self.__onManageHostsButtonClicked) #-------------------- # Define the widgets list. #-------------------- self.Events = MokaUtils.Events(self.EVENT_TYPES) self.setLayout(self.loginLayout) def updateFromSettings(self): """ """ #MokaUtils.debug.lf("Update from settings") self.loadDefaultHost() def eventFilter(self, eventObject, event): """ """ if event.type() == qt.QEvent.FocusIn: if str(eventObject.objectName).strip() == \ str(self.passwordLine.objectName).strip(): self.onPasswordLineFocused() elif str(eventObject.objectName).strip() == \ str(self.usernameLine.objectName).strip(): self.onUsernameLineFocused() def resetHostDropdown(self): """ Clears the host dropdown widget and then loads the defaults from the Settings object. """ #-------------------- # Clear host dropdown #-------------------- self.hostDropdown.clear() #MokaUtils.debug.lf("Update from settings") #-------------------- # Get the dictionary from settings and the key to # the dropdown widget. #-------------------- #print "\n\n" hostDict = self.MODULE.SettingsFile.getHostsDict() slicer.app.processEvents() #MokaUtils.debug.lf("hostDict", hostDict) for name in hostDict: if self.hostDropdown.findText(name) == -1: self.hostDropdown.addItem(name) def loadDefaultHost(self): """ Loads the default host into the hostDropdown from Settings. """ #MokaUtils.debug.lf("LOAD DEFAULT HOST") #-------------------- # Reset the dropdown. #-------------------- self.resetHostDropdown() #-------------------- # Set host dropdown to default stored hostName. #-------------------- defaultName = self.MODULE.SettingsFile.getDefault() self.setHost(defaultName) #-------------------- # Populate the stored user into the username line. #-------------------- self.__onHostSelected() self.populateCurrUser() def setHost(self, hostName): """ Sets the current intem in the hostDropdown to the name specified in the 'hostName' argument by looping through all of its visible items. """ #MokaUtils.debug.lf(hostName) if not hostName: return for i in range(0, self.hostDropdown.maxVisibleItems): if self.hostDropdown.itemText(i).lower() == \ hostName.strip().lower(): self.hostDropdown.setCurrentIndex(i) self.currHostName = self.hostDropdown.itemText(i) break def populateCurrUser(self): """ If "Remember username" is clicked, queries the settings file to bring up the username saved. """ #-------------------- # Does the username exist in the settings file? #-------------------- if self.currHostName: currUser = self.MODULE.SettingsFile.getCurrUsername(\ self.currHostName).strip() # # If it does, and it's not a '' string, then apply it to the # usernameLine.... # if len(currUser) > 0: self.usernameLine.setText(currUser) # # Otherwise apply a default string to the username line. # else: self.usernameLine.setText(self.defaultUsernameText) #-------------------- # If not, populate with default line #-------------------- else: self.usernameLine.setText(self.defaultUsernameText) def simulateLoginClicked(self): """ Equivalent of clicking the login button. """ self.loginButton.animateClick() def __onManageHostsButtonClicked(self): """ Event function for when the settings button is clicked. Displays the SettingsPopup from the MODULE. """ self.Events.runEventCallbacks('MANAGEHOSTSCLICKED', 'host manager') def onUsernameLineFocused(self): """ Event function for when the username line is edited. """ if self.defaultUsernameText in str(self.usernameLine.text): self.usernameLine.setText("") def onPasswordLineFocused(self): """ Event function for when the password line is edited. """ ##print "PWD FOCUSED" if self.defaultPasswordText in str(self.passwordLine.text): self.passwordLine.setText('') self.passwordLine.setStyleSheet("color: black") self.passwordLine.setEchoMode(2) def __onHostSelected(self): """ Event function for when the hostDropdown is clicked. Loads the stored username into the username line, if it's there. @param name: Dummy variable for the host name. @param type: name """ selHostName = self.hostDropdown.currentText #-------------------- # Clear the password line if the newly selected # host is different from the previous #-------------------- if (self.currHostName != selHostName): self.passwordLine.setText('') self.currHostName = selHostName if self.hostDropdown.currentText: self.populateCurrUser() #MokaUtils.debug.lf("ON HOST SELECTED: ", selHostName, # self.hostDropdown.currentText) self.Events.runEventCallbacks('HOSTSELECTED', selHostName)