def testPropertyValues(self):
     app = QApplication(sys.argv)
     textEdit = QPlainTextEdit()
     textEdit.insertPlainText("PySide INdT")
     selection = QTextEdit.ExtraSelection()
     selection.cursor = textEdit.textCursor()
     selection.cursor.setPosition(2)
     self.assertEqual(selection.cursor.position(), 2)
Exemple #2
0
 def testPropertyValues(self):
     app = QApplication(sys.argv)
     textEdit = QPlainTextEdit()
     textEdit.insertPlainText("PySide INdT")
     selection = QTextEdit.ExtraSelection()
     selection.cursor = textEdit.textCursor()
     selection.cursor.setPosition(2)
     self.assertEqual(selection.cursor.position(), 2)
Exemple #3
0
class MainWindow(QMainWindow):
    def __init__(self, application, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.printer_thread = WorkerThread()
        self.printer_thread.message.connect(self.standardOutputWritten)
        self.printer_thread.start()

        self.app = application
        self.app.setStyle("Fusion")

        self.__set_interface()
        self.__set_layouts()
        self.__set_stylesheet()
        self.__set_connections()
        self.__set_params()

    def closeEvent(self, event):
        self.printer_thread.stop()

    def __set_interface(self):
        self.button_width = 0.35
        self.button_height = 0.05

        self.setWindowTitle("GSI-RADS")
        self.__getScreenDimensions()

        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setMaximumWidth(self.width)
        #self.setMaximumHeight(self.height)
        self.setMinimumWidth(self.width)
        self.setMinimumHeight(self.height)
        self.move(self.width / 2, self.height / 2)

        self.menu_bar = QMenuBar(self)
        self.menu_bar.setNativeMenuBar(
            False
        )  # https://stackoverflow.com/questions/25261760/menubar-not-showing-for-simple-qmainwindow-code-qt-creator-mac-os
        self.file_menu = self.menu_bar.addMenu('File')
        self.import_dicom_action = QAction(
            QIcon(
                os.path.join(os.path.dirname(os.path.realpath(__file__)),
                             'images/database-icon.png')), 'Import DICOM',
            self)
        self.import_dicom_action.setShortcut('Ctrl+D')
        self.file_menu.addAction(self.import_dicom_action)
        self.quit_action = QAction('Quit', self)
        self.quit_action.setShortcut("Ctrl+Q")
        self.file_menu.addAction(self.quit_action)

        self.settings_menu = self.menu_bar.addMenu('Settings')
        self.settings_seg_menu = self.settings_menu.addMenu("Segmentation...")
        self.settings_seg_preproc_menu = self.settings_seg_menu.addMenu(
            "Preprocessing...")
        self.settings_seg_preproc_menu_p1_action = QAction(
            "Brain-masking off (P1)", checkable=True)
        self.settings_seg_preproc_menu_p2_action = QAction(
            "Brain-masking on (P2)", checkable=True)
        self.settings_seg_preproc_menu_p2_action.setChecked(True)
        self.settings_seg_preproc_menu.addAction(
            self.settings_seg_preproc_menu_p1_action)
        self.settings_seg_preproc_menu.addAction(
            self.settings_seg_preproc_menu_p2_action)

        self.help_menu = self.menu_bar.addMenu('Help')
        self.readme_action = QAction(
            QIcon(
                os.path.join(os.path.dirname(os.path.realpath(__file__)),
                             'images/readme-icon.jpeg')), 'Tutorial', self)
        self.readme_action.setShortcut("Ctrl+R")
        self.help_menu.addAction(self.readme_action)
        self.about_action = QAction(
            QIcon(
                os.path.join(os.path.dirname(os.path.realpath(__file__)),
                             'images/about-icon.png')), 'About', self)
        self.about_action.setShortcut("Ctrl+A")
        self.help_menu.addAction(self.about_action)
        self.help_action = QAction(
            QIcon.fromTheme("help-faq"), "Help", self
        )  # Default icons can be found here: https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html#guidelines
        self.help_action.setShortcut("Ctrl+J")
        self.help_menu.addAction(self.help_action)

        self.input_image_lineedit = QLineEdit()
        self.input_image_lineedit.setFixedWidth(self.width *
                                                (0.93 - self.button_width / 2))
        self.input_image_lineedit.setFixedHeight(self.height *
                                                 self.button_height)
        self.input_image_lineedit.setReadOnly(True)
        self.input_image_pushbutton = QPushButton('Input MRI')
        self.input_image_pushbutton.setFixedWidth(self.height *
                                                  self.button_width)
        self.input_image_pushbutton.setFixedHeight(self.height *
                                                   self.button_height)

        self.input_segmentation_lineedit = QLineEdit()
        self.input_segmentation_lineedit.setReadOnly(True)
        self.input_segmentation_lineedit.setFixedWidth(
            self.width * (0.93 - self.button_width / 2))
        self.input_segmentation_lineedit.setFixedHeight(self.height *
                                                        self.button_height)
        self.input_segmentation_pushbutton = QPushButton('Input segmentation')
        self.input_segmentation_pushbutton.setFixedWidth(self.height *
                                                         self.button_width)
        self.input_segmentation_pushbutton.setFixedHeight(self.height *
                                                          self.button_height)

        self.output_folder_lineedit = QLineEdit()
        self.output_folder_lineedit.setReadOnly(True)
        self.output_folder_lineedit.setFixedWidth(
            self.width * (0.93 - self.button_width / 2))
        self.output_folder_lineedit.setFixedHeight(self.height *
                                                   self.button_height)
        self.output_folder_pushbutton = QPushButton('Output destination')
        self.output_folder_pushbutton.setFixedWidth(self.height *
                                                    self.button_width)
        self.output_folder_pushbutton.setFixedHeight(self.height *
                                                     self.button_height)

        self.run_button = QPushButton('Run diagnosis')
        self.run_button.setFixedWidth(self.height * self.button_width)
        self.run_button.setFixedHeight(self.height * self.button_height)

        self.main_display_tabwidget = QTabWidget()

        self.tutorial_textedit = QPlainTextEdit()
        self.tutorial_textedit.setReadOnly(True)
        self.tutorial_textedit.setFixedWidth(self.width * 0.97)
        self.tutorial_textedit.setPlainText(
            "HOW TO USE THE SOFTWARE: \n"
            "  1) Click 'Input MRI...' to select from your file explorer the MRI scan to process (unique file).\n"
            "  1*) Alternatively, Click File > Import DICOM... if you wish to process an MRI scan as a DICOM sequence.\n"
            "  2) Click 'Output destination' to choose a directory where to save the results \n"
            "  3) (OPTIONAL) Click 'Input segmentation' to choose a tumor segmentation mask file, if nothing is provided the internal model with generate the segmentation automatically \n"
            "  4) Click 'Run diagnosis' to perform the analysis. The human-readable version will be displayed in the interface.\n"
            " \n"
            "NOTE: \n"
            "The output folder is populated automatically with the following: \n"
            "  * The diagnosis results in human-readable text (report.txt) and Excel-ready format (report.csv).\n"
            "  * The automatic segmentation masks of the brain and the tumor in the original patient space (input_brain_mask.nii.gz and input_tumor_mask.nii.gz).\n"
            "  * The input volume and tumor segmentation mask in MNI space in the sub-directory named \'registration\'.\n"
        )
        self.main_display_tabwidget.addTab(self.tutorial_textedit, 'Tutorial')
        self.prompt_lineedit = QPlainTextEdit()
        self.prompt_lineedit.setReadOnly(True)
        self.prompt_lineedit.setFixedWidth(self.width * 0.97)
        self.main_display_tabwidget.addTab(self.prompt_lineedit, 'Logging')
        self.results_textedit = QPlainTextEdit()
        self.results_textedit.setReadOnly(True)
        self.results_textedit.setFixedWidth(self.width * 0.97)
        self.main_display_tabwidget.addTab(self.results_textedit, 'Results')

        self.sintef_logo_label = QLabel()
        self.sintef_logo_label.setPixmap(
            QPixmap(
                os.path.join(os.path.dirname(os.path.realpath(__file__)),
                             'images/sintef-logo.png')))
        self.sintef_logo_label.setFixedWidth(0.95 * (self.width / 3))
        self.sintef_logo_label.setFixedHeight(
            1 * (self.height * self.button_height))
        self.sintef_logo_label.setScaledContents(True)
        self.stolavs_logo_label = QLabel()
        self.stolavs_logo_label.setPixmap(
            QPixmap(
                os.path.join(os.path.dirname(os.path.realpath(__file__)),
                             'images/stolavs-logo.png')))
        self.stolavs_logo_label.setFixedWidth(0.95 * (self.width / 3))
        self.stolavs_logo_label.setFixedHeight(
            1 * (self.height * self.button_height))
        self.stolavs_logo_label.setScaledContents(True)
        self.amsterdam_logo_label = QLabel()
        self.amsterdam_logo_label.setPixmap(
            QPixmap(
                os.path.join(os.path.dirname(os.path.realpath(__file__)),
                             'images/amsterdam-logo.png')))
        self.amsterdam_logo_label.setFixedWidth(0.95 * (self.width / 3))
        self.amsterdam_logo_label.setFixedHeight(
            1 * (self.height * self.button_height))
        self.amsterdam_logo_label.setScaledContents(True)

    def __set_layouts(self):
        self.input_volume_hbox = QHBoxLayout()
        self.input_volume_hbox.addStretch(1)
        self.input_volume_hbox.addWidget(self.input_image_lineedit)
        self.input_volume_hbox.addWidget(self.input_image_pushbutton)
        self.input_volume_hbox.addStretch(1)

        self.input_seg_hbox = QHBoxLayout()
        self.input_seg_hbox.addStretch(1)
        self.input_seg_hbox.addWidget(self.input_segmentation_lineedit)
        self.input_seg_hbox.addWidget(self.input_segmentation_pushbutton)
        self.input_seg_hbox.addStretch(1)

        self.output_dir_hbox = QHBoxLayout()
        self.output_dir_hbox.addStretch(1)
        self.output_dir_hbox.addWidget(self.output_folder_lineedit)
        self.output_dir_hbox.addWidget(self.output_folder_pushbutton)
        self.output_dir_hbox.addStretch(1)

        self.run_action_hbox = QHBoxLayout()
        self.run_action_hbox.addStretch(1)
        self.run_action_hbox.addWidget(self.run_button)
        self.run_action_hbox.addStretch(1)

        self.dump_area_hbox = QHBoxLayout()
        self.dump_area_hbox.addStretch(1)
        self.dump_area_hbox.addWidget(self.main_display_tabwidget)
        self.dump_area_hbox.addStretch(1)

        self.logos_hbox = QHBoxLayout()
        self.logos_hbox.addStretch(1)
        self.logos_hbox.addWidget(self.sintef_logo_label)
        self.logos_hbox.addWidget(self.stolavs_logo_label)
        self.logos_hbox.addWidget(self.amsterdam_logo_label)
        self.logos_hbox.addStretch(1)

        self.main_vbox = QVBoxLayout()
        self.main_vbox.addWidget(self.menu_bar)
        #self.main_vbox.addStretch(1)
        self.main_vbox.addLayout(self.input_volume_hbox)
        self.main_vbox.addLayout(self.output_dir_hbox)
        self.main_vbox.addLayout(self.input_seg_hbox)
        self.main_vbox.addLayout(self.run_action_hbox)
        #self.main_vbox.addStretch(1)
        self.main_vbox.addLayout(self.dump_area_hbox)
        self.main_vbox.addLayout(self.logos_hbox)
        #self.main_vbox.addStretch(1)

        self.central_label = QLabel()
        self.central_label.setLayout(self.main_vbox)
        self.setCentralWidget(self.central_label)

    def __set_stylesheet(self):
        self.central_label.setStyleSheet(
            'QLabel{background-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgba(207, 209, 207, 255), stop:1 rgba(230, 229, 230, 255));}'
        )
        self.menu_bar.setStyleSheet(get_stylesheet('QMenuBar'))
        self.input_image_lineedit.setStyleSheet(get_stylesheet('QLineEdit'))
        self.input_image_pushbutton.setStyleSheet(
            get_stylesheet('QPushButton'))
        self.input_segmentation_lineedit.setStyleSheet(
            get_stylesheet('QLineEdit'))
        self.input_segmentation_pushbutton.setStyleSheet(
            get_stylesheet('QPushButton'))
        self.output_folder_lineedit.setStyleSheet(get_stylesheet('QLineEdit'))
        self.output_folder_pushbutton.setStyleSheet(
            get_stylesheet('QPushButton'))

        self.results_textedit.setStyleSheet(get_stylesheet('QTextEdit'))
        self.prompt_lineedit.setStyleSheet(get_stylesheet('QTextEdit'))

        self.run_button.setStyleSheet(get_stylesheet('QPushButton'))

    def __set_connections(self):
        self.run_button.clicked.connect(self.diagnose_main_wrapper)
        self.input_image_pushbutton.clicked.connect(
            self.run_select_input_image)
        self.input_segmentation_pushbutton.clicked.connect(
            self.run_select_input_segmentation)
        self.output_folder_pushbutton.clicked.connect(
            self.run_select_output_folder)

        self.readme_action.triggered.connect(self.readme_action_triggered)
        self.about_action.triggered.connect(self.about_action_triggered)
        self.quit_action.triggered.connect(self.quit_action_triggered)
        self.import_dicom_action.triggered.connect(
            self.import_dicom_action_triggered)
        self.help_action.triggered.connect(self.help_action_triggered)
        self.settings_seg_preproc_menu_p1_action.triggered.connect(
            self.settings_seg_preproc_menu_p1_action_triggered)
        self.settings_seg_preproc_menu_p2_action.triggered.connect(
            self.settings_seg_preproc_menu_p2_action_triggered)

    def __set_params(self):
        self.input_image_filepath = ''
        self.input_annotation_filepath = ''
        self.output_folderpath = ''

    def __getScreenDimensions(self):
        screen = self.app.primaryScreen()
        size = screen.size()

        self.left = size.width() / 2
        self.top = size.height() / 2
        self.width = 0.4 * size.width()
        self.height = 0.4 * size.height()

    def readme_action_triggered(self):
        popup = QMessageBox()
        popup.setWindowTitle('Tutorial')
        popup.setText(
            "HOW TO USE THE SOFTWARE: \n"
            "  1) Click 'Input MRI...' to select from your file explorer the MRI scan to process (unique file).\n"
            "  1*) Alternatively, Click File > Import DICOM... if you wish to process an MRI scan as a DICOM sequence.\n"
            "  2) Click 'Output destination' to choose a directory where to save the results \n"
            "  3) (OPTIONAL) Click 'Input segmentation' to choose a tumor segmentation mask file, if nothing is provided the internal model with generate the segmentation automatically \n"
            "  4) Click 'Run diagnosis' to perform the analysis. The human-readable version will be displayed in the interface.\n"
            " \n"
            "NOTE: \n"
            "The output folder is populated automatically with the following: \n"
            "  * The diagnosis results in human-readable text (report.txt) and Excel-ready format (report.csv).\n"
            "  * The automatic segmentation masks of the brain and the tumor in the original patient space (input_brain_mask.nii.gz and input_tumor_mask.nii.gz).\n"
            "  * The input volume and tumor segmentation mask in MNI space in the sub-directory named \'registration\'.\n"
        )
        popup.exec_()

    def about_action_triggered(self):
        popup = QMessageBox()
        popup.setWindowTitle('About')
        popup.setText(
            'Software developed as part of a collaboration between: \n'
            '  * Departement of Health Research, SINTEF\n'
            '  * St. Olavs hospital, Trondheim University Hospital\n'
            '  * Amsterdam University Medical Center\n\n'
            'Contact: David Bouget, Andre Pedersen\n\n'
            'For questions about the software, please visit:\n'
            'https://github.com/SINTEFMedtek/GSI-RADS\n'
            'For questions about the methodological aspect, please refer to the original publication:\n'
            'https://www.mdpi.com/2072-6694/13/12/2854/review_report')
        popup.exec_()

    def quit_action_triggered(self):
        self.printer_thread.stop()
        sys.exit()

    def diagnose_main_wrapper(self):
        self.run_diagnosis_thread = threading.Thread(target=self.run_diagnosis)
        self.run_diagnosis_thread.daemon = True  # using daemon thread the thread is killed gracefully if program is abruptly closed
        self.run_diagnosis_thread.start()

    def run_diagnosis(self):
        if not os.path.exists(self.input_image_filepath) or not os.path.exists(
                self.output_folderpath):
            self.standardOutputWritten(
                'Process could not be started - The 1st and 2nd above-fields must be filled in.\n'
            )
            return

        self.run_button.setEnabled(False)
        self.prompt_lineedit.clear()
        self.main_display_tabwidget.setCurrentIndex(1)
        QApplication.processEvents(
        )  # to immidiently update GUI after button is clicked
        self.seg_preprocessing_scheme = 'P1' if self.settings_seg_preproc_menu_p1_action.isChecked(
        ) else 'P2'

        try:
            start_time = time.time()
            print('Initialize - Begin (Step 0/6)')
            from diagnosis.main import diagnose_main
            print('Initialize - End (Step 0/6)')
            print('Step runtime: {} seconds.'.format(
                np.round(time.time() - start_time, 3)) + "\n")
            diagnose_main(
                input_volume_filename=self.input_image_filepath,
                input_segmentation_filename=self.input_annotation_filepath,
                output_folder=self.output_folderpath,
                preprocessing_scheme=self.seg_preprocessing_scheme)
        except Exception as e:
            print('{}'.format(traceback.format_exc()))
            self.run_button.setEnabled(True)
            self.standardOutputWritten(
                'Process could not be completed - Issue arose.\n')
            QApplication.processEvents()
            return

        self.run_button.setEnabled(True)
        results_filepath = os.path.join(
            ResourcesConfiguration.getInstance().output_folder, 'report.txt')
        self.results_textedit.setPlainText(open(results_filepath, 'r').read())
        self.main_display_tabwidget.setCurrentIndex(2)

    def run_select_input_image(self):
        input_image_filedialog = QFileDialog()
        self.input_image_filepath = input_image_filedialog.getOpenFileName(
            self, 'Select input T1 MRI', '~',
            "Image files (*.nii *.nii.gz *.nrrd *.mha *.mhd)")[0]
        self.input_image_lineedit.setText(self.input_image_filepath)

    def run_select_input_segmentation(self):
        filedialog = QFileDialog()
        self.input_annotation_filepath = filedialog.getOpenFileName(
            self, 'Select input segmentation file', '~',
            "Image files (*.nii *.nii.gz)")[0]
        self.input_segmentation_lineedit.setText(
            self.input_annotation_filepath)

    def import_dicom_action_triggered(self):
        filedialog = QFileDialog()
        filedialog.setFileMode(QFileDialog.DirectoryOnly)
        self.input_image_filepath = filedialog.getExistingDirectory(
            self, 'Select DICOM folder', '~')
        self.input_image_lineedit.setText(self.input_image_filepath)

    def run_select_output_folder(self):
        filedialog = QFileDialog()
        filedialog.setFileMode(QFileDialog.DirectoryOnly)
        self.output_folderpath = filedialog.getExistingDirectory(
            self, 'Select output folder', '~')
        self.output_folder_lineedit.setText(self.output_folderpath)

    def standardOutputWritten(self, text):
        self.prompt_lineedit.moveCursor(QTextCursor.End)
        self.prompt_lineedit.insertPlainText(text)

        QApplication.processEvents()

    def help_action_triggered(self):
        # opens browser with specified url, directs user to Issues section of GitHub repo
        QDesktopServices.openUrl(
            QUrl("https://github.com/SINTEFMedtek/GSI-RADS/issues"))

    def settings_seg_preproc_menu_p1_action_triggered(self, status):
        if status:
            self.settings_seg_preproc_menu_p2_action.setChecked(False)
        else:
            self.settings_seg_preproc_menu_p2_action.setChecked(True)

    def settings_seg_preproc_menu_p2_action_triggered(self, status):
        if status:
            self.settings_seg_preproc_menu_p1_action.setChecked(False)
        else:
            self.settings_seg_preproc_menu_p1_action.setChecked(True)
class VentanaAdministradorDePersonas(QFrame):
    def __init__(self, parent=None):
        super(VentanaAdministradorDePersonas, self).__init__(parent)
        raiz.setWindowTitle("Administracion de personas")
        self.operacionesConPersonas = OperacionesConPersonas()
        self.instanciarVentana()

    def instanciarVentana(self):
        #Contenedor De todas las cosas de arriba a abajo
        layoutGeneral = QVBoxLayout()

        #Cosas de Derecha
        layoutDerecha = QVBoxLayout()  #Ordena cosas de arriba a abajo
        layoutDerecha.setMargin(20)

        self.btnAgregarPersona = QPushButton("Agregar persona")
        self.btnAgregarPersona.setToolTip("Toma los datos ")
        self.btnAgregarPersona.clicked.connect(self.agregarPersona)
        layoutDerecha.addWidget(self.btnAgregarPersona)

        self.btnBuscarPersona = QPushButton("Buscar persona")
        self.btnBuscarPersona.setToolTip("Busca por cedula a una persona")
        self.btnBuscarPersona.clicked.connect(self.buscarPersona)
        layoutDerecha.addWidget(self.btnBuscarPersona)

        self.btnEliminarPersona = QPushButton("Eliminar persona")
        self.btnEliminarPersona.setToolTip(
            "Elimina a la persona que esta en busqueda")
        self.btnEliminarPersona.clicked.connect(self.eliminarPersona)
        layoutDerecha.addWidget(self.btnEliminarPersona)

        self.btnActualizarPersona = QPushButton("Actualizar persona")
        self.btnActualizarPersona.setToolTip(
            "Cambia los datos de la persona seleccionada")
        self.btnActualizarPersona.clicked.connect(self.actualizarPersona)
        layoutDerecha.addWidget(self.btnActualizarPersona)

        self.btnLimpiarTexto = QPushButton("Limpiar")
        self.btnLimpiarTexto.setToolTip(
            "Limpia los campos de texto para ingresar datos")
        self.btnLimpiarTexto.clicked.connect(self.limpiarCampos)
        layoutDerecha.addWidget(self.btnLimpiarTexto)

        self.btnVolverAlMenu = QPushButton("Volver")
        self.btnVolverAlMenu.setToolTip("Vuelve al menu principal")
        self.btnVolverAlMenu.clicked.connect(self.volverAlMenu)
        layoutDerecha.addWidget(self.btnVolverAlMenu)

        #Cosas de Izquierda
        layoutIzquierda = QVBoxLayout()  #ordena cosas de arriba a abajo

        self.lblDNI = QLabel("DNI: ")
        layoutIzquierda.addWidget(self.lblDNI)
        self.DNI = QLineEdit()
        layoutIzquierda.addWidget(self.DNI)

        self.lblPrimerNombre = QLabel("Primer nombre: ")
        layoutIzquierda.addWidget(self.lblPrimerNombre)
        self.PrimerNombre = QLineEdit()
        layoutIzquierda.addWidget(self.PrimerNombre)

        self.lblSegundoNombre = QLabel("Segundo nombre: ")
        layoutIzquierda.addWidget(self.lblSegundoNombre)
        self.SegundoNombre = QLineEdit()
        layoutIzquierda.addWidget(self.SegundoNombre)

        self.lblPrimerApellido = QLabel("Primer apellido: ")
        layoutIzquierda.addWidget(self.lblPrimerApellido)
        self.PrimerApellido = QLineEdit()
        layoutIzquierda.addWidget(self.PrimerApellido)

        self.lblSegundoApellido = QLabel("Segundo apellido: ")
        layoutIzquierda.addWidget(self.lblSegundoApellido)
        self.SegundoApellido = QLineEdit()
        layoutIzquierda.addWidget(self.SegundoApellido)

        self.lblFechaDeNacimiento = QLabel("Fecha de nacimiento")
        layoutIzquierda.addWidget(self.lblFechaDeNacimiento)
        self.fechaDeNacimiento = QDateEdit()
        self.fechaDeNacimiento.setDisplayFormat("yyyy-MM-dd")
        self.fechaDeNacimiento.setCalendarPopup(True)
        self.fechaDeNacimiento.setDate(date.today())
        layoutIzquierda.addWidget(self.fechaDeNacimiento)

        #Cosas de layout de arriba
        layoutSuperior = QHBoxLayout()  #Ordena cosas de derecha a izquierda
        layoutSuperior.addLayout(layoutIzquierda)
        layoutSuperior.addLayout(layoutDerecha)

        #Cosas layout de abajo
        layoutInferior = QVBoxLayout()
        self.mostrarError = QPlainTextEdit(readOnly=True)
        layoutInferior.addWidget(self.mostrarError)

        #cosas del layout general
        layoutGeneral.addLayout(layoutSuperior)
        layoutGeneral.addLayout(layoutInferior)
        self.setLayout(layoutGeneral)

        #Redimensionar
        raiz.adjustSize()
        self.adjustSize()

    def agregarPersona(self):
        self.limpiarErrores()
        try:
            laPersona = self.llenarPersona()
            salida = self.operacionesConPersonas.insertarPersona(laPersona)
            self.mostrarError.insertPlainText(str(salida))
            self.limpiarCampos(
            )  #habilitamos la edicion y evitamos dejar datos basura
        except Exception as e:
            self.mostrarError.insertPlainText(''.join(e.args))
        pass

    def buscarPersona(self):
        self.limpiarErrores()
        try:
            laPersona = self.operacionesConPersonas.buscarPersonaPorDNI(
                int(''.join(self.DNI.text())))
            if type(laPersona) == type(""):
                self.mostrarError.insertPlainText(''.join(laPersona))
                return None
            self.llenarCampos(laPersona)
        except Exception as e:
            self.mostrarError.insertPlainText(''.join(e.args))

    def eliminarPersona(self):
        self.limpiarErrores()
        try:
            laPersona = self.llenarPersona()
            mensajeDeConfirmacion = "DNI: " + self.DNI.text()
            opcionElegida = QMessageBox.question(
                self, "Desea eliminar a la persona?", mensajeDeConfirmacion,
                QMessageBox.Yes, QMessageBox.No)
            if opcionElegida == QMessageBox.Yes:
                respuesta = self.operacionesConPersonas.eliminarPersona(
                    laPersona)
                if type(respuesta) == type(""):
                    self.mostrarError.insertPlainText(''.join(respuesta))
                    self.limpiarCampos()
                    return None
        except Exception as e:
            self.mostrarError.insertPlainText(''.join(e.args))

    def actualizarPersona(self):
        self.limpiarErrores()
        try:
            laPersona = self.llenarPersona()
            mensajeDeConfirmacion = "DNI: " + self.DNI.text()
            opcionElegida = QMessageBox.question(
                self, "Desea eliminar a la persona?", mensajeDeConfirmacion,
                QMessageBox.Yes, QMessageBox.No)
            if opcionElegida == QMessageBox.Yes:
                respuesta = self.operacionesConPersonas.actualizarPersona(
                    laPersona)
                if type(respuesta) == type(""):
                    self.mostrarError.insertPlainText(''.join(respuesta))
                    self.limpiarCampos()
                    return None
        except Exception as e:
            print(e.args)

    def llenarCampos(self, laPersona):
        self.limpiarCampos()
        self.DNI.setText(str(laPersona.getDNI()))
        self.DNI.setReadOnly(True)
        self.PrimerNombre.setText(laPersona.getPrimerNombre())
        self.SegundoNombre.setText(laPersona.getSegundoNombre())
        self.PrimerApellido.setText(laPersona.getPrimerApellido())
        self.SegundoApellido.setText(laPersona.getSegundoApellido())
        self.fechaDeNacimiento.setDate(laPersona.getFechaDeNacimiento())

    def llenarPersona(self):
        return Persona(int(''.join(self.DNI.text())),
                       ''.join(self.PrimerNombre.text()),
                       ''.join(self.SegundoNombre.text()),
                       ''.join(self.PrimerApellido.text()),
                       ''.join(self.SegundoApellido.text()),
                       ''.join(self.fechaDeNacimiento.text()))

    def limpiarCampos(self):
        self.DNI.clear()
        self.DNI.setReadOnly(False)
        self.PrimerNombre.clear()
        self.SegundoNombre.clear()
        self.PrimerApellido.clear()
        self.SegundoApellido.clear()
        self.fechaDeNacimiento.setDate(date.today())
        #limpiar campos de texto y permitir la edicion de todos ellos

    def limpiarErrores(self):
        self.mostrarError.clear()

    def volverAlMenu(self):
        raiz.setCentralWidget(None)
        raiz.setCentralWidget(VentanaPrincipal())
Exemple #5
0
class ExerciseWindow(QWidget):
    closed = Signal()

    def __init__(self, nursery, exercise):
        super().__init__()
        self.log = logging.getLogger("Test qt lean")

        self.server = ServerInterface(nursery)

        self.exercise = exercise
        self.statements = self.exercise.course.statements

        self._initUI()

        # Link signals
        self.server.proof_state_change.connect(self.proof_state_update)

        # Start waiter task
        self.server.nursery.start_soon(self.server_task)

        # Update initial proof state
        #self.proof_state_update(self.server.proof_state)

    async def server_task(self):
        await self.server.start()
        await self.server.exercise_set(self.exercise)
        async with qtrio.enter_emissions_channel(
                signals=[self.closed, self.send.clicked, self.undo.clicked
                         ]) as emissions:
            async for emission in emissions.channel:
                if emission.is_from(self.closed):
                    break
                elif emission.is_from(self.send.clicked):
                    await self.go_send()
                elif emission.is_from(self.undo.clicked):
                    await self.go_undo()

        self.server.stop()

    async def go_send(self):
        self.log.info("Send file to lean")
        self.freeze(True)

        txt = self.edit.toPlainText()
        try:
            await self.server.code_set("add", txt)
        except exceptions.FailedRequestError as ex:
            msg = QMessageBox(self)
            msg.setIcon(QMessageBox.Critical)
            msg.setWindowTitle("Failed lean request")
            msg.setText("I am broken :'(")

            detailed = ""
            for err in ex.errors:
                detailed += f"* at {err.pos_line} : {err.text}\n"

            msg.setDetailedText(detailed)
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()

        self.freeze(False)

    async def go_undo(self):
        self.log.info("Undo")
        self.freeze(True)
        await self.server.history_undo()
        self.edit.setPlainText(self.server.lean_file.inner_contents)
        self.freeze(False)

    def closeEvent(self, ev):
        super().closeEvent(ev)
        self.closed.emit()

    def _initUI(self):
        # Create widgets
        self.objects = PropobjList()
        self.properties = PropobjList()

        self.goal = Goal("TODO")

        self.edit = QPlainTextEdit()
        self.send = QPushButton("Send to lean")
        self.undo = QPushButton("Undo")

        self.deflist = QListWidget()

        # --> Build deflist
        for st in self.statements:
            self.deflist.addItem(st.pretty_name)

        # --> Link signal
        self.deflist.itemClicked.connect(self.add_statement_name)

        # Create layouts
        goal_layout = QHBoxLayout()
        main_layout = QVBoxLayout()
        workspace_layout = QHBoxLayout()
        propobj_layout = QVBoxLayout()
        tools_layout = QVBoxLayout()
        btns_layout = QHBoxLayout()

        # Create QGroupBox to have titles
        propobj_gb = QGroupBox('Properties and objects')
        self.tools_gb = QGroupBox('Lean code')

        # Put widgets in layouts and group boxes
        goal_layout.addStretch()
        goal_layout.addWidget(self.goal)
        goal_layout.addStretch()

        # Add space below goal
        goal_layout.setContentsMargins(0, 10, 0, 30)  #LTRB

        # Build propobj layout
        propobj_layout.addWidget(self.objects)
        propobj_layout.addWidget(self.properties)
        propobj_gb.setLayout(propobj_layout)

        # Build tools layout
        btns_layout.addWidget(self.send)
        btns_layout.addWidget(self.undo)

        tools_layout.addWidget(self.deflist)
        tools_layout.addWidget(self.edit)
        tools_layout.addLayout(btns_layout)

        self.tools_gb.setLayout(tools_layout)

        # Build workspace layout
        workspace_layout.addWidget(propobj_gb)
        workspace_layout.addWidget(self.tools_gb)

        # Don't forget me
        main_layout.addLayout(goal_layout)
        main_layout.addLayout(workspace_layout)
        self.setWindowTitle("d∃∀duction")
        self.setLayout(main_layout)
        self.show()

    def freeze(self, state: bool):
        self.tools_gb.setEnabled(not state)

    @Slot(QListWidgetItem)
    def add_statement_name(self, item):
        st = self.statements[self.deflist.row(item)]
        self.edit.insertPlainText(st.lean_name)

    @Slot(ProofState)
    def proof_state_update(self, po: ProofState):
        # Update goal
        # log.debug("Updating goal")
        goal = po.goals[0]
        target = goal.target.math_type.format_as_utf8()

        self.goal.setText(target)

        # Update properties and objects
        self.properties.clear()
        self.objects.clear()
        for type_, instances in goal.math_types:
            utf8 = type_.format_as_utf8(is_math_type=True)

            for obj in instances:
                txt = f"{obj.format_as_utf8()} : {utf8}"
                if obj.is_prop(): self.properties.addItem(txt)
                else: self.objects.addItem(txt)
Exemple #6
0
    def _init_widgets(self):

        layout = QGridLayout()

        row = 0

        # validation_failures = set()

        addr = hex(self._addr)

        address_label = QLabel(self)
        address_label.setText(f"Hook at address {addr}:")

        layout.addWidget(address_label, row, 0)
        row += 1

        options_container = QGroupBox(self)
        options = QVBoxLayout()

        for name, template in sorted(self.templates.items()):
            child = QRadioButton()
            child.setText(name)
            child.template = template
            child.toggled.connect(self.selected)
            options.addWidget(child)

        scroll_area = QScrollArea(self)
        scroll_area.setWidgetResizable(True)
        widget = QWidget()
        scroll_area.setWidget(widget)
        layout_scroll = QVBoxLayout(widget)

        header_label = QLabel(self)
        header_label.setText("Presets:")

        layout_scroll.addWidget(header_label)
        layout_scroll.addWidget(options_container)
        options_container.setLayout(options)
        layout.addWidget(scroll_area, row, 0)
        row += 1

        function_box = QPlainTextEdit(self)

        if addr in self.hooks.keys():
            function_box.insertPlainText(self.hooks[addr])

        highlight = PythonHighlighter(function_box.document())
        function_box.setWordWrapMode(QTextOption.WordWrap)
        self._function_box = function_box

        layout.addWidget(function_box, row, 0)
        row += 1

        # def add_indent():
        #     txt = function_box.toPlainText()
        #     if txt.endswith('\n'):
        #         embed()
        #         indent = txt.search()
        #     if txt.endswith(':\n'):
        #         function_box.insertPlainText('    ')

        # function_box.textChanged.connect(add_indent)
        # TODO: add python autoindent

        # buttons

        ok_button = QPushButton(self)
        ok_button.setText('OK')

        def do_ok():
            hook_code_string = function_box.toPlainText()
            self.instance.apply_hook(self._addr, hook_code_string)
            self.hooks[hex(self._addr)] = hook_code_string
            disasm_view = self.instance.workspace.view_manager.first_view_in_category(
                "disassembly")
            # So the hook icon shows up in the disasm view
            disasm_view.refresh()
            self.close()

        ok_button.clicked.connect(do_ok)

        cancel_button = QPushButton(self)
        cancel_button.setText('Cancel')

        def do_cancel():
            self.close()

        cancel_button.clicked.connect(do_cancel)

        buttons_layout = QHBoxLayout()
        buttons_layout.addWidget(ok_button)
        buttons_layout.addWidget(cancel_button)

        self.main_layout.addLayout(layout)
        self.main_layout.addLayout(buttons_layout)