Example #1
0
class MainWnd(QMainWindow):
    def __init__(self):
        super().__init__()
        self.exporter = Exporter()
        self.initUI()
        self.controlTower = None

    def setControlTower(self, ct):
        self.controlTower = ct

    def initUI(self):

        self.menuBar = QMenuBar(self)
        self.menuBar.setNativeMenuBar(False)

        file_menu = self.menuBar.addMenu('File')
        file_menu.addAction('New', self.save)
        file_menu.addAction('Open', self.save)
        file_menu.addAction('Close', self.save)
        file_menu.addAction('Save', self.save)
        file_menu.addAction('Save as', self.save)
        file_menu.addAction('Quit', self.quit)

        repo_menu = self.menuBar.addMenu('Repository')
        repo_menu.addAction('private')
        repo_menu.addAction('global')

        config_menu = self.menuBar.addMenu('Tools')
        config_menu.addAction('Preferences')
        config_menu.addAction('Export', self.export)
        box_menu = config_menu.addMenu('Box')
        box_menu.addAction('New combo box', self.createCompositeBox)
        box_menu.addAction('New Code box', self.createCodeBox)

        window_menu = self.menuBar.addMenu('Window')
        window_menu.addAction('Description')

        help_menu = self.menuBar.addMenu('Help')
        help_menu.addAction('online document', self.quit)

        self.setMenuBar(self.menuBar)

        self.setWindowTitle('Athena')
        self.statusBar().show()

    def createCodeBox(self):
        self.controlTower.createNewBox('CODE')

    def createCompositeBox(self):
        self.controlTower.createNewBox('COMPOSITION')

    def save(self):
        pass

    def export(self):
        exporter = Exporter()
        exporter.processExport(self.controlTower.getOpenedBox())

    def quit(self):
        sys.exit(0)
Example #2
0
    def createMenus(self):
        menus = QMenuBar()
        fileMenu = menus.addMenu("&Fichier")
        file_newMenu = fileMenu.addMenu(
            self.style().standardIcon(QStyle.SP_FileIcon), "Nouveau")
        file_newMenu.addAction("Date", self.createDateDialog, 'CTRL+D')
        file_newMenu.addAction("Durée", self.createDurationDialog, 'CTRL+N')
        fileMenu.addSeparator()
        fileMenu.addAction(self.style().standardIcon(QStyle.SP_BrowserStop),
                           "Quitter", sys.exit, 'CTRL+Q')

        optionMenu = menus.addMenu("&Options")
        optionMenu.addAction(
            self.style().standardIcon(QStyle.SP_MessageBoxInformation),
            "Évènements", self.createNotificationPopup, 'CTRL+O')
        optionMenu.addAction(
            QAction("Rester au premier plan",
                    optionMenu,
                    triggered=self.stayOnTop,
                    checkable=True))
        aideMenu = menus.addMenu("&Aide")
        aideMenu.addAction(
            self.style().standardIcon(QStyle.SP_DialogHelpButton),
            "À propos", lambda: QMessageBox.information(
                self, "À propos", TITLE + " " + str(VERSION)), 'CTRL+H')
        aideMenu.addSeparator()
        aideMenu.addAction(
            self.style().standardIcon(QStyle.SP_TitleBarMenuButton),
            "À propos de Qt", QApplication.aboutQt, 'CTRL+A')

        self.setMenuBar(menus)
Example #3
0
 def __init__(self,
              parent,
              title,
              person,
              unsorted_objects,
              autoshow=True,
              progress_indicator=None):
     super().__init__(None)
     act = QAction("close", self)
     act.triggered.connect(self._do_close)
     act.setShortcut(QKeySequence("escape"))
     self.addAction(act)
     layout = QGridLayout()
     bar = QMenuBar(self)
     self._object_actions = bar.addMenu(_("Object actions"))
     property_actions = bar.addMenu(_("Property actions"))
     self._create_item(property_actions, _("Copy property value"), "ctrl+c",
                       self.on_copypropvalue_selected)
     self._create_item(property_actions, _("Copy property name"), "alt+c",
                       self.on_copypropname_selected)
     self._create_item(property_actions, _("Copy property name and value"),
                       "ctrl+alt+c", self.on_copypropline_selected)
     objects_label = QLabel(_("Objects"), self)
     layout.addWidget(objects_label, 0, 0)
     self._objects_list = QListWidget(self)
     self._objects_list.setAccessibleName(objects_label.text())
     self._objects_list.setContextMenuPolicy(Qt.CustomContextMenu)
     self._objects_list.currentRowChanged.connect(self.on_objects_listbox)
     self._objects_list.customContextMenuRequested.connect(
         self._on_objects_list_menu)
     objects_label.setBuddy(self._objects_list)
     layout.addWidget(self._objects_list, 1, 0)
     props_label = QLabel(_("Object properties"), self)
     layout.addWidget(props_label, 0, 1)
     self._props = QTreeWidget(self)
     self._props.setAccessibleName(props_label.text())
     props_label.setBuddy(self._props)
     layout.addWidget(self._props, 1, 1)
     goto_button = QPushButton(_("Go to"), self)
     goto_button.setDefault(True)
     goto_button.clicked.connect(self.on_goto_clicked)
     self._objects_list.itemActivated.connect(goto_button.click)
     layout.addWidget(goto_button, 2, 0)
     close_button = QPushButton(_("Close"), self)
     close_button.clicked.connect(self.close)
     layout.addWidget(close_button, 2, 1)
     self.setLayout(layout)
     self.setWindowTitle(title + _(" ({num_objects} objects shown)").format(
         num_objects=len(unsorted_objects)))
     self._person = person
     self._autoshow = autoshow
     self._progress_indicator = progress_indicator
     self._all_actions = []
     for member in object_actions.__dict__.values():
         if inspect.isclass(member) and issubclass(member, ObjectAction):
             self._all_actions.append(member)
     self._objects_list.setCurrentRow(0)
     self._sorter = ObjectsSorter(unsorted_objects, person)
     self._sorter.objects_sorted.connect(self._objects_sorted)
     self._sorter.start()
Example #4
0
    def _create_menu_bar(self):
        menuBar = QMenuBar(self)

        home_menu = menuBar.addMenu('Homepage')
        home_menu.addAction(self.home_action)

        workspace_menu = menuBar.addMenu('Workspace')
        workspace_menu.addAction(self.search_action)
        workspace_menu.addAction(self.list_documents_action)
        workspace_menu.addAction(self.list_labels_action)
        workspace_menu.addAction(self.write_notebook_action)
        workspace_menu.addAction(self.write_remark_action)
        workspace_menu.addAction(self.upload_pdfs_action)
        workspace_menu.addAction(self.download_action)

        network_menu = menuBar.addMenu('Network')
        network_menu.addAction(self.find_path_action)
        network_menu.addAction(self.print_label_action)
        network_menu.addAction(self.loc_label_action)
        network_menu.addAction(self.show_labels_action)
        network_menu.addAction(self.show_network_action)

        help_menu = menuBar.addMenu('Help')
        help_menu.addAction(self.about_action)
        help_menu.addAction(self.source_code_action)
        help_menu.addAction(self.online_docs_action)

        self.setMenuBar(menuBar)
Example #5
0
    def createMenuBar(self):
        menuBar = QMenuBar(parent=None)

        # File Menu
        fileMenu = menuBar.addMenu('&File')

        dumpListsAction = QAction('Dump Lists', fileMenu)
        dumpListsAction.setShortcut('Ctrl+S')
        dumpListsAction.triggered.connect(self.writeLists)
        fileMenu.addAction(dumpListsAction)

        fileMenu.addSeparator()

        exitAction = QAction('E&xit', fileMenu)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.triggered.connect(QApplication.closeAllWindows)
        fileMenu.addAction(exitAction)

        # View Menu
        viewMenu = menuBar.addMenu('V&iew')

        t = ' pair' if self.mode == MAIN_WINDOW_MODE.COMPARE else ''

        nextImageAction = QAction('next image' + t, viewMenu)
        nextImageAction.setShortcut('Ctrl+]')
        nextImageAction.triggered.connect(self.nextImage)
        viewMenu.addAction(nextImageAction)

        prevImageAction = QAction('prev image' + t, viewMenu)
        prevImageAction.setShortcut('Ctrl+[')
        prevImageAction.triggered.connect(self.prevImage)
        viewMenu.addAction(prevImageAction)

        viewMenu.addSeparator()

        dropImageAction = QAction('Drop image' + t, viewMenu)
        dropImageAction.setShortcut('Ctrl+D')
        dropImageAction.triggered.connect(self.dropImage)
        viewMenu.addAction(dropImageAction)

        if self.mode == MAIN_WINDOW_MODE.COMPARE:
            viewMenu.addSeparator()

            nextDiffPixelAction = QAction('next diff pixel', viewMenu)
            nextDiffPixelAction.setShortcut('Ctrl+.')
            nextDiffPixelAction.triggered.connect(
                self.centralWidgetDict[MAIN_WINDOW_MODE.COMPARE].nextDiffPixel)
            viewMenu.addAction(nextDiffPixelAction)

            prevDiffPixelAction = QAction('prev diff pixel', viewMenu)
            prevDiffPixelAction.setShortcut('Ctrl+,')
            prevDiffPixelAction.triggered.connect(
                self.centralWidgetDict[MAIN_WINDOW_MODE.COMPARE].prevDiffPixel)
            viewMenu.addAction(prevDiffPixelAction)
        return menuBar
Example #6
0
    def _menubar(self) -> None:
        menubar = QMenuBar()
        self.layout.addWidget(menubar)

        fileMenu = menubar.addMenu('File')
        fileMenu.addAction('Open', self.browse_file)
        fileMenu.addSeparator()
        fileMenu.addAction('Exit', self.close)

        helpMenu = menubar.addMenu('Help')
        helpMenu.addSeparator()
        helpMenu.addAction('About Us', self.about_us)
Example #7
0
class MainWindow(QMainWindow):

    def __init__(self,application,parent=None):
        super(MainWindow,self).__init__(parent)

        #private attributes
        self.menuBar_ = QMenuBar()
        self.fileMenu_ = FileMenu(self)
        self.editMenu_ = EditMenu(self)
        self.toolbarDoc_ = QDockWidget(self)
        self.toolbarWidget_ = Toolbar(self)

        self.setGeometry(0,0,1280,720)

        #public attributes
        self.application = application
        self.contentTab = ContentTab()
        self.statusBar = QStatusBar()

        #menuBar
        self.menuBar_.addMenu(self.fileMenu_)
        self.menuBar_.addMenu(self.editMenu_)
        self.menuBar_.addAction("Help",self.helpFunc)
        self.setMenuBar(self.menuBar_)
        #statusBar
        self.statusBar.showMessage("status bar")
        self.setStatusBar(self.statusBar)
        #toolBar
        self.toolbarDoc_.setFeatures(QDockWidget.NoDockWidgetFeatures )
        self.addDockWidget(Qt.LeftDockWidgetArea,self.toolbarDoc_)
        self.toolbarDoc_.setWidget(self.toolbarWidget_)
        #contentab
        self.setCentralWidget(self.contentTab)



    def helpFunc(self):
        """
        Call the help tab
        To be added
        """
        print("called helpFunc")



    def quit(self):
        """
        Quit the application
        """
        self.application.quit()
Example #8
0
 def add_menu_bar(self, menus):
     """Adds the menu bar to the main window."""
     menu_bar = QMenuBar(self)
     for menu, actions in menus.items():
         menu = menu_bar.addMenu(menu)
         for action in actions:
             menu.addAction(action)
     return menu_bar
Example #9
0
class AppWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        #initialize app menu bar
        self.menu_bar = QMenuBar(parent=None)
        file_menu = self.menu_bar.addMenu('File')
        file_menu.addAction('To Excel')
        edit_menu = self.menu_bar.addMenu('Edit')
        edit_menu.addAction('&Undo')
        view_menu = self.menu_bar.addMenu('View')
        view_menu.addAction('Show All')

        # set manager widget
        manager = AppManager()
        self.setCentralWidget(manager)

        self.show()
Example #10
0
 def __init__(self, parent=None):
     super().__init__(parent)
     self.view: QtCharts.QChartView = None
     menuBar = QMenuBar()
     fileMenu = menuBar.addMenu('File')
     self._saveAc = QAction('Save as image', fileMenu)
     self._saveAc.setShortcut(QKeySequence(self.tr('Ctrl+S')))
     self._closeAc = QAction('Close', fileMenu)
     viewMenu = menuBar.addMenu('View')
     self._resetAc = QAction('Reset zoom', viewMenu)
     self._resetAc.setShortcut(QKeySequence(self.tr('Ctrl+R')))
     self._zoomInAc = QAction('Zoom in', viewMenu)
     self._zoomInAc.setShortcut(QKeySequence(self.tr('Ctrl++')))
     self._zoomOutAc = QAction('Zoom out', viewMenu)
     self._zoomOutAc.setShortcut(QKeySequence(self.tr('Ctrl+-')))
     fileMenu.addActions([self._saveAc, self._closeAc])
     viewMenu.addActions([self._zoomInAc, self._zoomOutAc, self._resetAc])
     self.setMenuBar(menuBar)
     self.setWindowTitle('dataMole - Plot')
Example #11
0
    def initActions(self):
        self.newEntryAction = QAction("New entry", self)
        self.newEntryAction.setShortcut(QKeySequence.New)
        self.newEntryAction.triggered.connect(self.addNewEntry)

        self.removeEntryAction = QAction("Remove entry", self)
        self.removeEntryAction.setShortcut(QKeySequence.Delete)
        self.removeEntryAction.triggered.connect(self.removeEntry)

        self.demoAction = QAction("Demo entry", self)
        self.demoAction.triggered.connect(self.addDemoEntry)

        self.printAction = QAction("Print Preview...", self)
        self.printAction.triggered.connect(self.printPreview)

        self.zoomInAction = QAction("Zoom In", self)
        self.zoomInAction.setShortcut(QKeySequence.ZoomIn)
        self.zoomInAction.triggered.connect(self.zoomIn)

        self.zoomOutAction = QAction("Zoom Out", self)
        self.zoomOutAction.setShortcut(QKeySequence.ZoomOut)
        self.zoomOutAction.triggered.connect(self.zoomOut)

        self.ui.ganttView.leftView().setContextMenuPolicy(Qt.CustomContextMenu)
        self.ui.ganttView.leftView().addAction(self.newEntryAction)
        self.ui.ganttView.leftView().addAction(self.removeEntryAction)

        menuBar = QMenuBar(self)
        self.setMenuBar(menuBar)
        entryMenu = menuBar.addMenu("Entry")
        entryMenu.addAction(self.newEntryAction)
        entryMenu.addAction(self.removeEntryAction)
        entryMenu.addSeparator()
        entryMenu.addAction(self.demoAction)
        entryMenu.addSeparator()
        entryMenu.addAction(self.printAction)

        zoomMenu = menuBar.addMenu("Zoom")
        zoomMenu.addAction(self.zoomInAction)
        zoomMenu.addAction(self.zoomOutAction)
Example #12
0
    def buildMenuBar(self):
        menuBar = QMenuBar(self)

        fileMenu = QMenu("File")
        loadImageAction = QAction("Load Image", self)
        loadDataAction = QAction("Load Lot Data", self)
        saveDataAction = QAction("Save Lot Data", self)
        exitAction = QAction("Exit", self)

        # Set Trigger for each Action
        loadImageAction.triggered.connect(self.loadImage)
        loadDataAction.triggered.connect(self.loadData)
        saveDataAction.triggered.connect(self.saveData)
        exitAction.triggered.connect(QtGui.qApp.quit)

        # Add actions to menu
        fileMenu.addAction(loadImageAction)
        fileMenu.addAction(loadDataAction)
        fileMenu.addAction(saveDataAction)
        fileMenu.addAction(exitAction)

        menuBar.addMenu(fileMenu)
        return menuBar
Example #13
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('Stat Tracker')

        exit_action = QAction('&exit', self)
        exit_action.triggered.connect(self.close)

        menu_bar = QMenuBar(self)
        file_menu = menu_bar.addMenu('&File')
        file_menu.addAction('Save')
        file_menu.addAction(exit_action)

        self.widget = MainWidget()
        self.setCentralWidget(self.widget)
Example #14
0
    def setup_menu(self) -> QMenuBar:
        """Create the menu of the main window"""
        menubar = QMenuBar(self)
        setting_menu = menubar.addMenu("Einstellungen")

        # bell sound selection
        bell_select_action = QAction("Klingelton", self)
        bell_select_action.setStatusTip("Wähle einen Klingelton")
        bell_select_action.triggered.connect(self.on_bell_select)
        setting_menu.addAction(bell_select_action)

        # volume settings
        volume_setting_action = QAction("Lautstärke", self)
        volume_setting_action.setStatusTip("Lautstärke ändern")
        volume_setting_action.triggered.connect(self.on_volume_setting)
        setting_menu.addAction(volume_setting_action)

        return menubar
Example #15
0
class MainWindow(QMainWindow):
    def __init__(self, *, setup_input_panel=None, plot_panel=None):
        super().__init__()
        self.setup_input_panel = setup_input_panel
        self.plot_panel = plot_panel

        self.main_widget = None
        self.menu_bar = None
        self.new_menu_action = None

        self.setup_ui()
        self.setWindowTitle(TITLE)

    def setup_ui(self):
        self.main_widget = QSplitter(Qt.Horizontal)
        self.setCentralWidget(self.main_widget)

        self.main_widget.addWidget(self.setup_input_panel)
        self.main_widget.addWidget(self.plot_panel)

        self.main_widget.setStretchFactor(0, 2)
        self.main_widget.setStretchFactor(1, 1)

        self.create_menu_bar()

    def create_menu_bar(self):
        self.menu_bar = QMenuBar(self)
        self.setMenuBar(self.menu_bar)

        self.create_file_menu()

    def create_file_menu(self):
        file_menu = self.menu_bar.addMenu('&File')

        self.new_menu_action = QAction('New', self)
        self.new_menu_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_N))

        file_menu.addAction(self.new_menu_action)
Example #16
0
class MainGui(QMainWindow):
    def __init__(self, parent=None):
        QLocale.setDefault(QLocale.English)
        QMainWindow.__init__(self, parent)
        self.setWindowTitle("AMLab Software v1.0")
        self.supported_printers = ['DLP', 'Metal']
        self.selected_printer = self.supported_printers[0]
        self.__init_setup__()
        self.dlp_gui = None
        self.metal_gui = None
        # self.dlp_gui.hide()
        # self.metal_gui.hide()
        self.setup_widget.hide()
        self.__init_menu_bar__()
        if not self.__load_settings__():
            self.__select_setup_widget__()

    def __load_settings__(self):
        base_path = Path(__file__).parent
        settings_path = str(
            (base_path / './resources/PRINTER_SETTINGS.json').resolve())
        settings_file = QFile(settings_path)
        if settings_file.open(QIODevice.ReadOnly | QIODevice.Text):
            file_data = QJsonDocument.fromJson(
                settings_file.readAll()).object()
            if "printer_type" in file_data:
                printer_type = str(file_data["printer_type"])
                if printer_type == self.supported_printers[0]:
                    self.__select_dlp__()
                elif printer_type == self.supported_printers[1]:
                    self.__select_metal__()
                else:
                    return False
                return True
            settings_file.close()
        return False

    def __init_setup__(self):
        self.setup_widget = QWidget(self)
        dlp_button = QPushButton("DLP \nPrinter", self.setup_widget)
        dlp_button.setFixedSize(200, 200)
        dlp_button.clicked.connect(self.__select_dlp__)
        metal_button = QPushButton("Metal \nPrinter", self.setup_widget)
        metal_button.setFixedSize(200, 200)
        metal_button.clicked.connect(self.__select_metal__)
        self.setup_layout = QHBoxLayout()
        self.setup_layout.addWidget(dlp_button)
        self.setup_layout.addWidget(metal_button)
        self.setup_widget.setLayout(self.setup_layout)

    def __select_setup_widget__(self):
        self.setup_widget.show()
        self.setCentralWidget(self.setup_widget)

    def __select_dlp__(self):
        self.dlp_gui = DLPGUI(self)
        self.selected_printer = self.supported_printers[0]
        self.setCentralWidget(self.dlp_gui)
        self.adjustSize()

    def __select_metal__(self):
        self.metal_gui = MetalGUI(self)
        self.selected_printer = self.supported_printers[1]
        self.setCentralWidget(self.metal_gui)
        self.adjustSize()

    @Slot()
    def closeEvent(self, event: QCloseEvent):
        try:
            self.dlp_gui.close()
        except:
            print("already deleted")
        try:
            self.metal_gui.close()
        except:
            print("already deleted")
        event.accept()

    def __init_menu_bar__(self):
        self.__menu_bar = QMenuBar(self)
        self.__init_file_menu()
        self.setMenuBar(self.__menu_bar)

    def __init_file_menu(self):
        self.file_menu = self.__menu_bar.addMenu("File")
        settings_action = QAction("Settings", self)
        settings_action.setStatusTip("Open Settings")
        settings_action.triggered.connect(self.__open_settings_window)
        self.file_menu.addAction(settings_action)

    @Slot()
    def __open_settings_window(self):
        settings_window = QDialog(self)
        settings_window.setWindowTitle("Settings")
        printer_settings = QGroupBox("Printer Settings:", settings_window)
        printer_type_label = QLabel("Printer Type:", printer_settings)
        self.printer_type_combo = QComboBox(printer_settings)
        self.printer_type_combo.addItems(self.supported_printers)
        self.printer_type_combo.setCurrentIndex(
            self.supported_printers.index(self.selected_printer))
        apply_button = QPushButton("Apply Changes", printer_settings)
        apply_button.clicked.connect(self.__apply_settings)
        apply_button.clicked.connect(settings_window.close)
        apply_button.setAutoDefault(False)
        printer_settings_layout = QGridLayout(printer_settings)
        printer_settings_layout.addWidget(printer_type_label, 0, 0)
        printer_settings_layout.addWidget(self.printer_type_combo, 0, 1)
        printer_settings_layout.addWidget(apply_button, 4, 1)
        if self.selected_printer is self.supported_printers[0]:
            extra_settings = self.dlp_gui.get_settings_window(settings_window)
        elif self.selected_printer is self.supported_printers[1]:
            extra_settings = self.metal_gui.get_settings_window(
                settings_window)
        settings_layout = QVBoxLayout(settings_window)
        settings_layout.addWidget(printer_settings)
        settings_layout.addWidget(extra_settings)
        settings_window.open()

    @Slot()
    def __apply_settings(self):
        self.selected_printer = self.supported_printers[
            self.printer_type_combo.currentIndex()]
        try:
            self.dlp_gui.close()
        except:
            print("already deleted")
        try:
            self.metal_gui.close()
        except:
            print("already deleted")
        if self.selected_printer is self.supported_printers[0]:
            self.__select_dlp__()
        elif self.selected_printer is self.supported_printers[1]:
            self.__select_metal__()
class ExtensionMenu:
    """MDIArea menu for extensions."""

    # ----------------------------------------------------------------------
    def build_menu_visualization(self, visualization: bool, debugger: Optional[bool] = False) -> None:
        """Menu for visualizations."""
        self.menubar = QMenuBar(self)
        self.menubar.clear()
        self.menubar.setMinimumWidth(1e4)

        self.accent_menubar = QMenuBar(self)

        # Title
        if debugger:
            menu_stimuli = QMenu(f"Debugging: {visualization}")
        else:
            if visualization:
                menu_stimuli = QMenu(f'{visualization } 🞃')
            else:
                menu_stimuli = QMenu('Data analysis 🞃')

        # Add visualizations
        for viz, path in self.extensions_list:
            if viz != visualization:
                menu_stimuli.addAction(QAction(viz, menu_stimuli,
                                               triggered=self.set_extension(path)))

        self.accent_menubar.addMenu(menu_stimuli)

        # Menu with accent color
        self.accent_menubar.setStyleSheet(f"""
        QMenuBar::item {{
            background-color: {os.getenv('QTMATERIAL_PRIMARYCOLOR', '#ffffff')};
            color: {os.getenv('QTMATERIAL_PRIMARYTEXTCOLOR', '#ffffff')};
            }}""")

        # Set the menu in first position
        self.menubar.setCornerWidget(
            self.accent_menubar, corner=Qt.TopLeftCorner)

        # View
        menu_view = QMenu("View")
        if visualization:

            menu_view.addAction(
                QAction('Reload', menu_view, triggered=self.reload))

            menu_view.addAction(
                QAction('Save capture', menu_view, triggered=self.save_img))
            if not debugger:
                menu_view.addSeparator()
                menu_view.addAction(
                    QAction('Close', menu_view, triggered=self.remove))
        else:
            menu_view.setEnabled(False)
        self.menubar.addMenu(menu_view)

        # DPI
        menu_dpi = QMenu("DPI (60)")
        if visualization:
            for dpi in [60, 70, 80, 90, 100, 110, 120, 130]:
                menu_dpi.addAction(QAction(
                    f'{dpi}', menu_dpi, checkable=True, triggered=self.set_dpi(menu_dpi, f'{dpi}', dpi)))
                if dpi == 60:
                    self.set_dpi(menu_dpi, f'{dpi}', dpi)()
        else:
            menu_dpi.setEnabled(False)
        self.menubar.addMenu(menu_dpi)

    # ----------------------------------------------------------------------
    def build_menu_stimuli(self, visualization: bool, debugger: Optional[bool] = False) -> None:
        """Menu for stimuli delivery."""
        self.menubar = QMenuBar(self)
        self.menubar.clear()

        self.accent_menubar = QMenuBar(self)
        self.accent_menubar.clear()
        self.menubar.setMinimumWidth(1e4)

        # Title
        if debugger:
            menu_stimuli = QMenu(f"Debugging: {visualization}")
        else:
            if visualization:
                menu_stimuli = QMenu(visualization + ' 🞃')
            else:
                menu_stimuli = QMenu('Stimuli' + ' 🞃')

        for viz, path in self.extensions_list:
            if viz != visualization:
                menu_stimuli.addAction(QAction(viz, menu_stimuli,
                                               triggered=self.set_extension(path)))
        # self.menubar.addMenu(menu_stimuli)
        self.accent_menubar.addMenu(menu_stimuli)

        self.accent_menubar.setStyleSheet(f"""
        QMenuBar::item {{
            background-color: {os.getenv('QTMATERIAL_PRIMARYCOLOR', '#ffffff')};
            color: {os.getenv('QTMATERIAL_PRIMARYTEXTCOLOR', '#ffffff')};
        }}

        """)

        # self.menubar.addMenu(menu_stimuli)
        self.menubar.setCornerWidget(
            self.accent_menubar, corner=Qt.TopLeftCorner)

        # View
        menu_view = QMenu("View")
        if visualization:

            menu_view.addAction(
                QAction('Reload', menu_view, triggered=self.reload))

            if debugger:
                menu_view.addAction(
                    QAction('Open subwindow delivery', menu_view, triggered=debugger.open_subwindow))
            if not debugger:
                menu_view.addSeparator()
                menu_view.addAction(
                    QAction('Close', menu_view, triggered=self.remove))
        else:
            menu_view.setEnabled(False)
        self.menubar.addMenu(menu_view)

    # ----------------------------------------------------------------------
    def set_dpi(self, menu_dpi, text: str, dpi: int) -> Callable:
        """Set the DPI value for matplotlib figures."""
        def wrap():
            [action.setChecked(False) for action in menu_dpi.actions()]
            [action.setChecked(
                True) for action in menu_dpi.actions() if action.text() == text]
            self.main.DPI = dpi
            menu_dpi.setTitle(f'DPI ({dpi})')
        return wrap

    # ----------------------------------------------------------------------
    def set_extension(self, visualization: str) -> Callable:
        """Load extension from menu."""
        def wrap():
            self.load_extension(visualization)
        return wrap
Example #18
0
class Window(QMainWindow):
    """Class to create main widnow

    Creates main window for displaying frame read from a connected camera.
    The main window contains memu bar, tool bar, status bar, sliders and the
    boxes showing the camera's information. These widget are created and added to
    main window in the instance method of this class.

    """
    def __init__(
            self, device: int = 0, suffix: str = "png", camtype: str = "usb_cam",
            color: str = "RGB", dst: str = ".", param: str = "full",
            rule: str = "Sequential", parent=None):
        super(Window, self).__init__(parent)
        self.device = device
        self.camtype = camtype
        self.colorspace = color
        self.image_suffix = suffix
        self.video_codec = "AVC1"
        self.video_suffix = "avi"
        self.dst = Path(dst)
        self.parent_dir = Path(__file__).parent.resolve()

        self.filename_rule_lst = FileIO.file_save
        self.filename_rule = FileIO.file_save_lst[-1]

        self.is_display = True
        self.param_separate = False

        self.slot = Slot(self)

        cam = self.get_cam()
        self.camera = cam(self.device, self.colorspace, parent=self)
        self.support_params = self.camera.get_supported_params()
        self.current_params = self.camera.get_current_params(param)

        # List of camera properties with temporal initial values
        self.prop_table = [
            ["Fourcc", "aa"],
            ["Width", 640],
            ["Height", 480],
            ["FPS", 30.0],
            ["Bit depth", 8],
            ["File naming style", self.filename_rule]
        ]
        self.setup()
        self.set_timer()

    def get_cam(self) -> str:
        """Return camera object according to current OS.

        Detects what OS you are using, return camera objects  in order to function properly.

            - Linux: LinuxCamera
            - RaspberryPi OS: RaspiCamera
            - Windows: WindowsCamera

        Returns:
            Camera class
        """
        if self.camtype == "raspi":
            return RaspiCamera

        self.system = platform.system()
        if re.search("linux", self.system, re.IGNORECASE):
            return LinuxCamera
        elif re.search("windows", self.system, re.IGNORECASE):
            return WindowsCamera
        else:
            return "Unknown type"

    def setup(self):
        """Setup the main window for displaying frame and widget.

        Creates a QMainWindow object, then add menubar, toolbar, statusbar, widgets and layout
        into the window.
        """
        self.setFocusPolicy(Qt.ClickFocus)
        self.setContentsMargins(20, 0, 20, 0)
        self.information_window_setup()
        self.view_setup()
        self.layout_setup()
        self.image_setup()
        self.toolbar_setup()
        self.setWindowTitle("usbcamGUI")
        self.update_prop_table()
        self.adjust_windowsize()
        self.set_theme()

    def adjust_windowsize(self):
        """Adjusts the main window size
        """
        system = Utility.get_os()
        if system == "linux":
            w, h, _ = self.get_screensize()
            wscale = 0.5
            hscale = 0.7
            self.resize(wscale * w, hscale * h)
        else:
            self.resize(800, 600)

    def set_theme(self):
        """Set color theme of the main window.
        """
        self.style_theme = "light"
        self.style_theme_sheet = ":/{}.qss".format(self.style_theme)
        self.slot.switch_theme()
        self.set_font(self.camera.font_family, self.camera.font_size)

    def set_font(self, family: str = "Yu Gothic", size: int = 14):
        """Sets font-family and size of UI.

        Args:
            family (str, optional): Font-family. Defaults to "Yu Gothic".
            size (int, optional): Font-size. Defaults to 20.
        """
        self.setStyleSheet('font-family: "{}"; font-size: {}px;'.format(family, size))

    def set_timer(self):
        """Set QTimer

        Creates a QTimer object to update frame on view area. The interval is set to the inverse
        of camera FPS.
        """
        self.qtime_factor = 0.8
        self.fps = 30.0
        if self.fps:
            self.msec = 1 / self.fps * 1000 * self.qtime_factor
        else:
            self.msec = 1 / 30.0 * 1000 * self.qtime_factor
        self.timer = QTimer()
        self.timer.setInterval(self.msec)
        self.timer.timeout.connect(self.next_frame)
        self.timer.start()

    def stop_timer(self):
        """Deactivate the Qtimer object.
        """
        self.timer.stop()

    def start_timer(self):
        """Activate the Qtimer object.
        """
        self.fps = 30.0
        if self.fps:
            self.msec = 1 / self.fps * 1000 * self.qtime_factor
        else:
            self.msec = 1 / 30.0 * 1000 * self.qtime_factor
        self.timer.setInterval(self.msec)
        self.timer.start()

    def toolbar_setup(self):
        """Create toolbar
        """
        self.toolbar = QToolBar("test", self)
        self.addToolBar(self.toolbar)

        current_size = str(self.font().pointSize())
        lst = [str(i) for i in range(6, 14)]
        lst.extend([str(i) for i in range(14, 40, 2)])
        index = lst.index(current_size)

        self.fontsize_combo = QComboBox()
        self.fontsize_combo.addItems(lst)
        self.fontsize_combo.setCurrentIndex(index)
        self.fontsize_combo.currentTextChanged.connect(self.slot.set_fontsize)
        self.fontsize_label = QLabel("Font size")
        self.fontsize_label.setFrameShape(QFrame.Box)

        self.comb = QFontComboBox()

        self.toolbar.addWidget(self.save_button)
        self.toolbar.addWidget(self.stop_button)
        self.toolbar.addWidget(self.rec_button)
        self.toolbar.addWidget(self.close_button)
        self.toolbar.addWidget(self.theme_button)
        self.toolbar.addWidget(self.help_button)
        self.toolbar.addWidget(self.fontsize_label)
        self.toolbar.addWidget(self.fontsize_combo)
        self.toolbar.setStyleSheet(
            """
            QToolBar {spacing:5px;}
            """
            )

    def view_setup(self):
        """Set view area to diplay read frame in part of the main window
        """
        self.view = QGraphicsView()
        self.scene = QGraphicsScene()
        self.view.setScene(self.scene)
        self.width = 640
        self.height = 480
        self.scene.setSceneRect(0, 0, self.width, self.height)
        self.view.setMouseTracking(True)
        self.view.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
        self.view.setCacheMode(QGraphicsView.CacheBackground)
        self.view.setViewportUpdateMode(QGraphicsView.SmartViewportUpdate)

    def layout_setup(self):
        """Set layout of objects on the window.
        """
        self.window = QWidget()
        self.setCentralWidget(self.window)
        #self.view.mouseMoveEvent = self.get_coordinates

        self.main_layout = QHBoxLayout()
        self.window.setLayout(self.main_layout)

        self.add_actions()
        self.add_menubar()
        self.add_statusbar()
        self.button_block = self.add_buttons()
        self.slider_group = self.add_params()
        self.prop_block = self.add_prop_window()
        self.create_mainlayout()

    def image_setup(self):
        """Creates a Qimage to assign frame, then initialize with an image which has zero in all pixels.
        """
        self.frame = np.zeros((640, 480, 3), dtype=np.uint8)
        #cinit = np.ctypeslib.as_ctypes(self.frame)
        #self.frame.buffer = sharedctypes.RawArray(cinit._type_, cinit)
        self.qimage = QImage(
            self.frame.data,
            640,
            480,
            640 * 3,
            QImage.Format_RGB888
            )
        self.pixmap = QPixmap.fromImage(self.qimage)

    def add_actions(self):
        """Add actions executed when press each item in the memu window.
        """
        self.save_act = self.create_action("&Save", self.save_frame, "Ctrl+s")
        self.stop_act = self.create_action("&Pause", self.stop_frame, "Ctrl+p", checkable=True)
        self.rec_act = self.create_action("&Record", self.record, "Ctrl+r", True)
        self.quit_act = self.create_action("&Quit", self.slot.quit, "Ctrl+q")

        self.theme_act = self.create_action("Switch &Theme", self.slot.switch_theme, "Ctrl+t")
        self.param_act = self.create_action("Choose parameter slider", self.slot.switch_paramlist, "Ctrl+g")
        self.show_paramlist_act = self.create_action("Parameters &List", self.slot.show_paramlist, "Ctrl+l")
        self.show_shortcut_act = self.create_action("&Keybord shortcut", self.slot.show_shortcut, "Ctrl+k")
        self.font_act = self.create_action("&Font", self.slot.set_font, "Ctrl+f")

        self.usage_act = self.create_action("&Usage", self.slot.usage, "Ctrl+h")
        self.about_act = self.create_action("&About", self.slot.about, "Ctrl+a")

    def create_action(self, text: str, slot: Callable, key: str = None, checkable: bool = False,
        check_defalut: bool = False) -> QAction:
        """Create a QAction object.

        Args:
            text (str): Text shown on menu.
            slot (Callable): A method called when click the menu.
            key (str, optional): Shortcut key. Defaults to None.
            checkable (bool, optional): Add a checkbox into the menu. Defaults to False.
            check_defalut (bool, optional): Check default status. Defaults to False.

        Returns:
            QAction: PySide2 QAction
        """
        act = QAction(text)
        act.setShortcut(key)
        if checkable:
            act.setCheckable(True)
            act.setChecked(check_defalut)
            act.toggled.connect(slot)
        else:
            act.triggered.connect(slot)

        return act

    def add_menubar(self):
        """Create menu bar, then add to the main window.
        """
        self.menubar = QMenuBar()
        self.setMenuBar(self.menubar)

        self.file_tab = QMenu("&File")
        self.file_tab.addAction(self.save_act)
        self.file_tab.addAction(self.stop_act)
        self.file_tab.addAction(self.rec_act)
        self.file_tab.addSeparator()
        self.file_tab.addAction(self.quit_act)
        #self.file_tab.setSizePolicy(policy)

        self.view_tab = QMenu("&View")
        self.view_tab.addAction(self.theme_act)
        self.view_tab.addAction(self.font_act)
        self.view_tab.addAction(self.param_act)
        self.view_tab.addAction(self.show_shortcut_act)
        self.view_tab.addAction(self.show_paramlist_act)

        self.help_tab = QMenu("&Help")
        self.help_tab.addAction(self.usage_act)
        self.help_tab.addAction(self.about_act)

        self.menubar.addMenu(self.file_tab)
        self.menubar.addMenu(self.view_tab)
        self.menubar.addMenu(self.help_tab)
        self.menubar.setStyleSheet(
            """
            QMenuBar {
                    font-size: 16px;
                    spacing:10px;
                    padding-top: 5px;
                    padding-bottom: 10px;
                }
            """
            )

    def add_statusbar(self):
        """Create status bar, then add to the main window.

        The status bar shows the coordinates on the frame where the cursor is located and
        its pixel value. The pixel value has RGB if the format of is color (RGB), does grayscale
        value if grayscale.
        """
        self.statbar_list = []
        if self.colorspace == "rgb":
            self.stat_css = {
                "postion": "color: white",
                "R": "color: white;",
                "G": "color: white;",
                "B": "color: white;",
                "alpha": "color: white;",
            }
        else:
            self.stat_css = {
                "postion": "color: black;",
                "gray": "color: black"
            }

        for s in self.stat_css.values():
            stat = QStatusBar(self)
            stat.setStyleSheet(s)
            self.statbar_list.append(stat)

        first = True
        for stat in self.statbar_list:
            if first:
                self.setStatusBar(stat)
                self.statbar_list[0].reformat()
                first = False
            else:
                self.statbar_list[0].addPermanentWidget(stat)

    def add_buttons(self):
        """Add push buttons on the window.

        Add quit, save stop and usage buttons on the windows. When press each button, the set
        method (called "slot" in Qt framework) are execeuted.
        """
        self.save_button = self.create_button("&Save", self.save_frame, None, None, "Save the frame")
        self.stop_button = self.create_button("&Pause", self.stop_frame, None, None, "Stop reading frame", True)
        self.rec_button = self.create_button("&Rec", self.record, None, None, "Start recording", True)
        self.close_button = self.create_button("&Quit", self.slot.quit, None, None, "Quit the program")
        self.theme_button = self.create_button("Light", self.slot.switch_theme, None, None, "Switche color theme")
        self.help_button = self.create_button("&Usage", self.slot.usage, None, None, "Show usage")

        self.frame_button = self.create_button(
            "Properties",
            self.slot.change_frame_prop,
            None,
            tip="Change properties",
            minsize=(150, 30)
            )
        self.default_button = self.create_button(
            "&Default params",
            self.set_param_default,
            "Ctrl+d",
            tip="Set default parameters",
            minsize=(150, 30)
            )
        self.filerule_button = self.create_button(
            "&Naming style",
            self.slot.set_file_rule,
            "Ctrl+n",
            tip="Change naming style",
            minsize=(150, 30)
            )

        hbox = QHBoxLayout()
        hbox.addWidget(self.save_button)
        hbox.addWidget(self.stop_button)
        hbox.addWidget(self.rec_button)
        hbox.addWidget(self.close_button)
        hbox.addWidget(self.theme_button)
        hbox.addWidget(self.help_button)
        return hbox

    def create_button(self, text: str, slot: Callable, key: str = None, icon: Icon = None,
        tip: str = None, checkable: bool = False, minsize: tuple = None) -> QPushButton:
        """Create a QPushButton object.

        Args:
            text (str): Text shown on the button.
            slot (Callable): A method called when click the button.
            key (str, optional): Shortcut key. Defaults to None.
            icon (Icon, optional): An icon shown on the button. Defaults to None.
            tip (str, optional): A tips shown when position the pointer on the button. Defaults to None.
            checkable (bool, optional): Add button to checkbox. Defaults to False.
            msize (tuple, optional): Minimum size of the button box, (width, height).

        Returns:
            QPushButton: PySide2 QPushButton
        """
        button = QPushButton(text)
        if checkable:
            button.setCheckable(True)
            button.toggled.connect(slot)
        else:
            button.clicked.connect(slot)

        if key:
            button.setShortcut(key)
        if icon:
            button.setIcon(QIcon(icon))
        if tip:
            button.setToolTip(tip)
        if minsize:
            button.setMinimumSize(minsize[0], minsize[1])
        else:
            button.setMinimumSize(80, 30)
        return button

    def add_params(self) -> QGridLayout:
        """Set the properties of camera parameter.

        Set the properties of camera parameter, then add sliders to change each parameter.
        When change value on the slider, the value of paramter also changes by the caller
        function.

        """
        lst = self.current_params
        for key, value in lst.items():
            self.add_slider(key)

        # add sliders
        self.slider_table = QGridLayout()
        self.slider_table.setSpacing(15)
        self.slider_table.setContentsMargins(20, 20, 20, 20)
        for row, param in enumerate(self.current_params):
            self.slider_table.addWidget(self.current_params[param]["slider_label"], row, 0)
            self.slider_table.addWidget(self.current_params[param]["slider"], row, 1)
            self.slider_table.addWidget(self.current_params[param]["slider_value"], row, 2)
        if len(self.current_params) > 15:
            self.param_separate = True
        else:
            self.param_separate = False
        return self.slider_table

    def update_params(self, plist: list) -> QGridLayout:
        """Update camera's paramters and sliders shown on the windows.
        """
        #self.current_params.clear()
        self.current_params = self.camera.get_current_params("selected", plist)
        for key, value in self.current_params.items():
            self.add_slider(key)

        # add sliders
        grid = QGridLayout()
        grid.setSpacing(15)
        grid.setContentsMargins(20, 20, 20, 20)
        for row, param in enumerate(self.current_params):
            grid.addWidget(self.current_params[param]["slider_label"], row, 0)
            grid.addWidget(self.current_params[param]["slider"], row, 1)
            grid.addWidget(self.current_params[param]["slider_value"], row, 2)
        if len(self.current_params) > 15:
            self.param_separate = True
        else:
            self.param_separate = False
        self.slider_group = grid
        self.update_mainlayout()
        self.update_prop_table()
        self.write_text("update sliders")
        return grid

    def add_slider(self, param: str):
        """Creates slider, labels to show pamarater's name and its value.

        Args:
            param (str): A parameter to create slider.
        """
        min_ = self.current_params[param]["min"]
        max_ = self.current_params[param]["max"]
        step = self.current_params[param]["step"]
        value = self.current_params[param]["value"]

        slider = QSlider(Qt.Horizontal)
        if max_:
            slider.setRange(min_, max_)
        else:
            slider.setRange(0, 1)
        slider.setValue(int(value))
        slider.setTickPosition(QSlider.TicksBelow)
        slider.valueChanged.connect(lambda val, p=param: self.set_sliderval(p, val))

        if step:
            if max_ < 5:
                slider.setTickInterval(step)
            else:
                slider.setTickInterval(10)

        slider_label = QLabel(param)
        slider_value = QLabel(str(value))

        slider_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        slider_value.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)

        self.current_params[param]["slider"] = slider
        self.current_params[param]["slider_label"] = slider_label
        self.current_params[param]["slider_value"] = slider_value

    def add_prop_window(self) -> QGridLayout:
        """Create a table to show the current properties of camera.

        Returns:
            QGridLayout: PySide2 QGridLayout
        """
        header = ["property", "value"]
        self.prop_table_widget = QTableWidget(self)
        self.prop_table_widget.setColumnCount(len(header))
        self.prop_table_widget.setRowCount(len(self.prop_table))

        self.prop_table_widget.setHorizontalHeaderLabels(header)
        self.prop_table_widget.verticalHeader().setVisible(False)
        self.prop_table_widget.setAlternatingRowColors(True)
        self.prop_table_widget.horizontalHeader().setStretchLastSection(True)
        self.prop_table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.prop_table_widget.setFocusPolicy(Qt.NoFocus)

        for row, content in enumerate(self.prop_table):
            for col, elem in enumerate(content):
                self.item = QTableWidgetItem(elem)

                self.prop_table_widget.setItem(row, col, self.item)
        self.prop_table_widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        #self.prop_table_widget.resizeColumnsToContents()
        #self.prop_table_widget.resizeRowsToContents()
        self.prop_table_widget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.prop_table_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.prop_table_widget.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContentsOnFirstShow)
        self.prop_table_widget.setColumnWidth(0, 150)
        self.prop_table_widget.setColumnWidth(1, 150)

        vbox = QVBoxLayout()
        vbox.addWidget(self.prop_table_widget)
        vbox.setContentsMargins(20, 20, 20, 20)
        self.prop_group = QGroupBox("Frame Properties")
        self.prop_group.setLayout(vbox)
        return self.prop_group

    def information_window_setup(self):
        """Creates information window.

        Creates the information window where the event related to camera or window.
        """
        self.text_edit = QTextEdit()
        self.text_edit.setReadOnly(True)
        self.text_edit.show()
        vbox = QVBoxLayout()
        vbox.addWidget(self.text_edit)
        self.text_edit_box = QGroupBox("Information", self)
        self.text_edit_box.setLayout(vbox)
        self.text_edit_box.setAlignment(Qt.AlignLeft)

    def create_mainlayout(self):
        """Create the main layout which consists of view area and information window.
        """
        self.main_layout.addLayout(self.create_view_area_layout())
        self.main_layout.addLayout(self.create_information_layout())

    def update_mainlayout(self):
        """Recreate the main layout.
        """
        self.delete_layout(self.information_layout)
        self.delete_layout(self.upper_right)
        self.add_prop_window()
        self.main_layout.addLayout(self.create_information_layout())

    def delete_layout(self, layout):
        """Delete layout

        Args:
            layout (QBoxLayout): QBoxLayout class object to delete
        """
        while layout.count():
            child = layout.takeAt(0)
            if child.widget():
                child.widget().deleteLater()
            try:
                child.spacerIitem().deleteLater()
            except:
                pass

    def create_view_area_layout(self) -> QVBoxLayout:
        """Creates view area layout
        """
        self.view_area_layout = QVBoxLayout()
        self.view_area_layout.addWidget(self.view, 2)
        self.view_area_layout.addWidget(self.text_edit_box)
        return self.view_area_layout

    def create_information_layout(self):
        """Creates information part layout

        upper-left: current properties
        upper-right: buttons
        lower: sliders
        """
        if self.param_separate:
            self.entry_box = QVBoxLayout()
            self.entry_box.addWidget(self.frame_button)
            self.entry_box.addWidget(self.filerule_button)
            self.entry_box.addWidget(self.default_button)
            self.entry_box.addStretch(1)
            self.entry_box.setSpacing(20)
            self.entry_box.setContentsMargins(20, 20, 20, 20)

            self.button_group_box = QGroupBox("Buttons", self)
            self.button_group_box.setLayout(self.entry_box)
            self.button_group_box.setAlignment(Qt.AlignLeft)

            self.upper_right = QVBoxLayout()
            self.upper_right.addWidget(self.prop_group, 1)
            self.upper_right.addWidget(self.button_group_box, 1)

            self.slider_group_box = QGroupBox("Parameters")
            self.slider_group_box.setLayout(self.slider_group)
            self.slider_group_box.setContentsMargins(20, 20, 20, 20)

            self.information_layout = QHBoxLayout()
            self.information_layout.addLayout(self.upper_right, 1)
            self.information_layout.addWidget(self.slider_group_box, 2)
            #self.information_layout.addStretch(1)
            return self.information_layout
        else:
            self.entry_box = QVBoxLayout()
            self.entry_box.addWidget(self.frame_button)
            self.entry_box.addWidget(self.filerule_button)
            self.entry_box.addWidget(self.default_button)
            self.entry_box.addStretch(1)
            self.entry_box.setSpacing(20)
            self.entry_box.setContentsMargins(20, 20, 20, 20)

            self.button_group_box = QGroupBox("Buttons", self)
            self.button_group_box.setLayout(self.entry_box)
            self.button_group_box.setAlignment(Qt.AlignLeft)

            self.upper_right = QHBoxLayout()
            self.upper_right.addWidget(self.prop_group)
            self.upper_right.addWidget(self.button_group_box)

            self.slider_group_box = QGroupBox("Parameters")
            self.slider_group_box.setLayout(self.slider_group)
            self.slider_group_box.setContentsMargins(20, 20, 20, 20)

            self.information_layout = QVBoxLayout()
            self.information_layout.addLayout(self.upper_right)
            self.information_layout.addWidget(self.slider_group_box)
            self.information_layout.setSpacing(30)
            return self.information_layout

    # decorator
    def display(func):
        def wrapper(self, *args, **kwargs):
            try:
                self.is_display = False
                self.stop_timer()
                func(self, *args, **kwargs)
            finally:
                self.is_display = True
                self.start_timer()
        return wrapper

    def stop_frame(self, checked: bool):
        """Stop reading next frame.

        Args:
            checked (bool): True when presse the Stop button (toggle on). False when press
                again (toggel off).
        """
        if checked:
            self.write_text("Stop !!")
            self.is_display = False
            self.stop_button.setText('Start')
            self.stop_button.setChecked(True)
            self.stop_act.setText('Start')
            self.stop_act.setChecked(True)
        else:
            self.write_text("Start !!")
            self.is_display = True
            self.stop_button.setText('&Pause')
            self.stop_button.setChecked(False)
            self.stop_act.setText('&Pause')
            self.stop_act.setChecked(False)

    def keyPressEvent(self, event):
        """Exit the program

        This method will be called when press the Escape key on the window.
        """
        if event.key() == Qt.Key_Escape:
            QApplication.quit()

    def get_coordinates(self, event):
        """Show the current coordinates and value in the pixel where the cursor is located.

        The status bar is updates by the obtained values.
        """
        if self.item is self.view.itemAt(event.pos()):
            sp = self.view.mapToScene(event.pos())
            lp = self.item.mapFromScene(sp).toPoint()
            (x, y) = lp.x(), lp.y()
            #color = self.frame.image.pixel(x, y)
            color = self.qimage.pixelColor(x, y)
            if self.colorspace == "rgb":
                value = color.getRgb()
            elif self.colorspace == "gray":
                value = color.value()

            # Return none if the coordinates are out of range
            if x < 0 and self.frame.width < x:
                return
            elif y < 0 and self.frame.height < y:
                return

            if self.frame.img_is_rgb:
                status_list = [
                    "( x : {}, y :{} )".format(x, y),
                    "R : {}".format(value[0]),
                    "G : {}".format(value[1]),
                    "B : {}".format(value[2]),
                    "alpha : {}".format(value[3])
                ]
            else:
                status_list = [
                    "( x : {}, y :{} )".format(x, y),
                    "gray value : {}".format(value),
                ]

            for statbar, stat in zip(self.statbar_list, status_list):
                statbar.showMessage(stat)

    def next_frame(self):
        """Get next frame from the connected camera.

        Get next frame, set it to the view area and update.
        """
        #print("display :", self.is_display)
        if self.is_display:
            self.camera.read_frame()
            self.convert_frame()
            self.scene.clear()
            self.scene.addPixmap(self.pixmap)
            self.update()
            #print("update")

    def convert_frame(self):
        """Convert the class of frame

        Create qimage, qpixmap objects from ndarray frame for displaying on the window.

        """
        if self.colorspace == "rgb":
            self.qimage = QImage(
                self.camera.frame.data,
                self.camera.frame.shape[1],
                self.camera.frame.shape[0],
                self.camera.frame.shape[1] * 3,
                QImage.Format_RGB888
                )
        elif self.colorspace == "gray":
            self.qimage = QImage(
                self.camera.frame.data,
                self.camera.frame.shape[1],
                self.camera.frame.shape[0],
                self.camera.frame.shape[1] * 1,
                QImage.Format_Grayscale8)

        self.pixmap.convertFromImage(self.qimage)

    def save_frame(self):
        """Save the frame on the window as an image.
        """
        if self.filename_rule == "Manual":
            self.save_frame_manual()
            if not self.filename:
                return None
            prm = re.sub(r"\.(.*)", ".csv", str(self.filename))
        else:
            self.filename = FileIO.get_filename(self.filename_rule, self.image_suffix, self.parent_dir)
            prm = str(self.filename).replace(self.image_suffix, "csv")

        if not self.dst.exists():
            self.dst.mkdir(parents=True)
        im = Image.fromarray(self.camera.frame)
        im.save(self.filename)

        # make a parameter file
        with open(prm, "w") as f:
            for name, key in self.current_params.items():
                f.write("{},{}\n".format(name, self.current_params[name]["value"]))

        self.write_text("{:<10}: {}".format("save image", self.filename))
        self.write_text("{:<10}: {}".format("save param", prm))

    def update_prop_table(self):
        """Updates the table that shows the camera properties.
        """
        w, h, cc, f = self.camera.get_properties()
        self.prop_table = [
            ["Fourcc", cc],
            ["Width", int(w)],
            ["Height", int(h)],
            ["FPS", "{:.1f}".format(f)],
            ["Bit depth", 8],
            ["Naming Style", self.filename_rule]
        ]
        col = 1
        for row in range(len(self.prop_table)):
            text = str(self.prop_table[row][col])
            self.prop_table_widget.item(row, col).setText(text)

    def record(self):
        """Start or end recording
        """
        if self.camera.is_recording:
            self.camera.stop_recording()
            self.rec_button.setText('&Rec')
            self.rec_act.setText('&Record')
            self.write_text("save : {}".format(self.video_filename))
        else:
            self.video_filename = FileIO.get_filename(self.filename_rule, self.video_suffix, self.parent_dir)
            self.camera.start_recording(self.video_filename, self.video_codec)
            self.rec_button.setText('Stop rec')
            self.rec_act.setText('Stop record')

    @display
    def save_frame_manual(self) -> bool:
        """Determine file name of image to save with QFileDialog
        """
        self.dialog = QFileDialog()
        self.dialog.setWindowTitle("Save File")
        self.dialog.setNameFilters([
            "image (*.jpg *.png *.tiff *.pgm)",
            "All Files (*)"
            ])
        self.dialog.setAcceptMode(QFileDialog.AcceptSave)
        self.dialog.setOption(QFileDialog.DontUseNativeDialog)

        if self.dialog.exec_():
            r = self.dialog.selectedFiles()

            # If the file name doesn't include supproted suffixes, add to the end.
            if re.search(".pgm$|.png$|.jpg$|.tiff$", r[0]):
                self.filename = r[0]
            else:
                self.filename = "{}.{}".format(r[0], self.image_suffix)
            return True
        else:
            return False

    def get_screensize(self):
        """Get current screen size from the output of linux cmd `xrandr`.
        """
        cmd = ["xrandr"]
        ret = subprocess.check_output(cmd)
        output = ret.decode()
        pattern = r"current(\s+\d+\s+x\s+\d+)"

        m = re.search(pattern, output)
        if m:
            size = re.sub(" ", "", m.group(1))
            w, h = map(int, size.split("x"))
            return w, h, size
        else:
            return None

    def set_sliderval(self, param: str, value: int):
        """Changes a camera parameter.

        Updates the label on the right of the slider if input value is valid.

        Args:
            param (str): A camera parameter
            value (int): its value
        """
        val = self.camera.set_parameter(param, value)
        self.current_params[param]["value"] = str(val)
        self.current_params[param]["slider_value"].setText(str(value))

    def set_param_default(self):
        """Sets all paramters to default.
        """
        for param, values in self.current_params.items():
            default = values["default"]
            self.camera.set_parameter(param, default)
            self.current_params[param]["slider"].setValue(int(default))
            self.current_params[param]["slider_value"].setText(str(default))

    def get_properties(self) -> list:
        """Get the current camera properties.

        Returns:
            list: parameters. fourcc, width, height, fps.
        """
        tmp = []
        for row in range(4):
            tmp.append(self.prop_table[row][1])
        return tmp

    def write_text(self, text: str, level: str = "info", color: str = None):
        """Writes the message into information window.

        Args:
            text (str): A text to write.
            level (str, optional): Log lebel of the message. Defaults to "info".
            color (str, optional): Font color. Defaults to None.
        """
        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
        now = now[:-3]
        if color == "red":
            form = f"<font color='red'>[{level.upper():<4} {now}] {text}</font>"
        elif color == "yellow":
            form = f"<font color='yellow'>[{level.upper():<4} {now}] {text}</font>"
        else:
            form = f"[{level.upper():<4} {now}] {text}"
        self.text_edit.append(form)
Example #19
0
    class App(QWidget):
        def __init__(self):
            super().__init__()
            self.setWindowIcon(QIcon('icon.ico'))
            QApplication.setFont(
                QFont("Helvetica", 9, QFont.Normal, italic=False))
            self.title = 'DanielPaskalev'
            self.left, self.top = 0, 0
            self.width, self.height = 900, 920
            self.current_tests = process(get_filename())
            self.original_tests = process(get_filename())
            self.search = ""
            self.initUI()

        def initUI(self):
            # self.is_button_clicked = False
            self.setWindowTitle(self.title)
            self.setWindowState(Qt.WindowMaximized)
            self.createLabel()
            self.createLe()
            self.createTable()
            self.createButton()
            self.createCopyButton()
            self.createRefreshButton()
            self.createMergeButton()
            self.createMenuBox()
            # Create vertical box layout and horizontal box layout,
            # add label, button, to hbox,
            # add hbox to vbox,
            # and add table to vbox.
            self.layout = QVBoxLayout()
            self.layout.setContentsMargins(0, 5, 0, 0)
            # self.layout.setSpacing(0)
            self.hbox = QHBoxLayout()
            self.hbox.addWidget(self.menuBar)
            self.hbox.addWidget(self.label)
            self.hbox.addWidget(self.le)
            self.hbox.addWidget(self.button)
            self.hbox.addWidget(self.copyButton)
            self.hbox.addWidget(self.refreshButton)
            self.hbox.addWidget(self.mergeButton)
            self.layout.addLayout(self.hbox)
            self.layout.addWidget(self.tableWidget)
            self.setLayout(self.layout)
            # Show widget
            self.show()

        def createLe(self):
            # Create user input box for filter.
            self.le = QLineEdit()
            self.le.setObjectName("Filter")
            self.le.setPlaceholderText("Filter")
            self.le.setToolTip('Enter text to filter the pending list')
            self.le.setMaximumWidth(200)
            self.le.returnPressed.connect(
                self.filter_accessions)  # Enter pressed

        def createButton(self):
            # Create "Filter Accessions" button.
            self.button = QPushButton('Filter', self)
            self.button.setToolTip('Filters the accessions by text matches.')
            self.button.setMaximumWidth(60)
            self.button.clicked.connect(self.filter_accessions)

        def createCopyButton(self):
            # Create Copy accessions button.
            self.copyButton = QPushButton('Copy', self)
            self.copyButton.setToolTip(
                'Copy all unique accessions to clipboard.')
            self.copyButton.setMaximumWidth(60)
            self.copyButton.clicked.connect(self.on_copyButton_click)

        def createRefreshButton(self):
            # Re-acquire the ref pending list.
            self.refreshButton = QPushButton('Refresh', self)
            self.refreshButton.setToolTip(
                'Refresh table with new pending list.')
            self.refreshButton.setMaximumWidth(60)
            self.refreshButton.clicked.connect(self.on_refresh)

        def createMergeButton(self):
            # Merge the currently showing accessions.
            self.mergeButton = QPushButton('Merge', self)
            self.mergeButton.setToolTip(
                'Merges tests for duplicate accessions')
            self.mergeButton.setMaximumWidth(60)
            self.mergeButton.clicked.connect(self.on_merge)

        def createLabel(self):
            # label with general information.
            self.label = QLabel()
            self.label.setTextFormat(Qt.PlainText)
            text = ("Double click entry to copy | Order count: " +
                    str(len(self.current_tests)))
            self.label.setText(text)
            self.label.setAlignment(Qt.AlignCenter)

        def createTable(self):
            # Initialize table with proper attributes. Then populateTable.
            self.tableWidget = QTableWidget()
            self.tableWidget.clicked.connect(
                self.on_click)  # If cell is clicked, copy.
            self.tableWidget.setEditTriggers(
                QAbstractItemView.NoEditTriggers)  # no edit
            self.tableWidget.setWordWrap(True)
            self.tableWidget.setColumnCount(5)
            self.tableWidget.setHorizontalHeaderLabels(
                ["Accession", "Name", "DOC", "Worklist(s)", "Pending Tests"])
            self.tableWidget.horizontalHeader().setStretchLastSection(True)
            self.tableWidget.horizontalHeaderItem(4).setTextAlignment(
                Qt.AlignLeft)
            self.populateTable(self.current_tests)  # Populate table with data
            self.tableWidget.resizeColumnsToContents(
            )  # Resize columns only once.
            self.tableWidget.resizeRowsToContents(
            )  # Resize height to fit tests.

        def populateTable(self, orderList):
            # Re-populate table with argument 'orderList'
            self.tableWidget.setSortingEnabled(False)
            self.tableWidget.clearContents()
            self.tableWidget.setRowCount(len(orderList))
            for i in range(len(orderList)):
                self.tableWidget.setItem(i, 0,
                                         QTableWidgetItem(orderList[i][1]))
                self.tableWidget.setItem(i, 1,
                                         QTableWidgetItem(orderList[i][4]))
                self.tableWidget.setItem(i, 2,
                                         QTableWidgetItem(orderList[i][3]))
                self.tableWidget.setItem(i, 3,
                                         QTableWidgetItem(orderList[i][0]))
                self.tableWidget.setItem(i, 4,
                                         QTableWidgetItem(orderList[i][2]))
            self.tableWidget.resizeRowsToContents(
            )  # Resize height to fit tests
            # self.tableWidget.resizeColumnsToContents()
            self.label.setText("Double click entry to copy | Order count: " +
                               str(len(orderList)))
            self.tableWidget.setSortingEnabled(True)

        def createMenuBox(self):
            # Menu bar at the top of the window.
            self.menuBar = QMenuBar()
            self.fileMenu = self.menuBar.addMenu('File')
            self.open_action = QAction('Open', self)
            self.exit_action = QAction('Exit', self)
            self.open_action.triggered.connect(self.open)
            self.exit_action.triggered.connect(app.quit())  # just quit
            self.fileMenu.addAction(self.open_action)
            self.fileMenu.addAction(self.exit_action)

        @Slot()
        def open(self):
            fname = QFileDialog.getOpenFileName(
                self, 'Open File', os.path.expanduser('~/Documents'),
                'Text Files (*.txt)')
            if fname[0]:
                self.original_tests = process(fname[0])
                self.filter_accessions()

        @Slot()
        def on_click(self):
            # Double click to put selected item into clipboard
            qApp.clipboard().setText(
                self.tableWidget.selectedItems()[0].text())

        @Slot()
        def on_refresh(self):
            # Refresh button clicked to re-create table with new pending list.
            self.original_tests = process(get_filename())
            self.filter_accessions()

        @Slot()
        def on_copyButton_click(self):
            # Click to copy all accessions into clipboard
            self.cp = [i[1] for i in self.current_tests]
            qApp.clipboard().setText(
                self.search + ''.join(['\n' + a
                                       for a in filter_dups(self.cp)]))

        @Slot()
        def on_merge(self):
            # Merge current accessions to remove situation where multiple tests for
            # the same patient are on multiple worklists.
            self.tableWidget.setSortingEnabled(False)
            # Aglorithm to merge duplicate accessions.
            temp_tests = deepcopy(self.current_tests)  # DEEEEPcopy
            temp_tests.sort(key=lambda x: x[1])  # Sort by accession number
            result = []
            i = 0
            # Compare the current accession to the next to see if duplicate.
            length = len(temp_tests) - 1
            while i < length:
                if temp_tests[i][1] == temp_tests[i + 1][1]:
                    # If duplicates, add worklist and tests to first accesion.
                    temp_tests[i][0] += ', ' + temp_tests[i + 1][0]
                    temp_tests[i][2] += ' ||| ' + temp_tests[i + 1][2]
                    del temp_tests[i + 1]  # Delete second accession.
                    length -= 1
                else:  # If current and next accession numbers don't match
                    result.append(temp_tests[i])
                    i += 1
            result.append(
                temp_tests[-1])  # add the last accession that we missed.

            # Re-create table with 'result'
            self.populateTable(result)
            self.mergeButton.setDown(True)  # Click down merge button

        @Slot()
        def filter_accessions(self):
            # Button / Return pressed to filter the orders.
            self.tableWidget.setSortingEnabled(False)
            self.mergeButton.setDown(False)  # Unclick merge button
            self.search = self.le.text().upper()
            self.current_tests = [
                a for a in self.original_tests
                if self.search in a[0] or self.search in a[1] or self.search in
                a[2] or self.search in a[3] or self.search in a[4]
            ]
            self.populateTable(self.current_tests)
Example #20
0
class ListenerView(QMainWindow):
    def __init__(self, *args):
        super(ListenerView, self).__init__(*args)

        self.layout = QVBoxLayout()
        self.setLayout(self.layout)
        self.window_branding()

        self.create_menu()
        self.create_main()
        self.create_status()

        self.create_container_view()
        self.create_audio_view()

    app = property(appref.app)

    def window_branding(self):
        """Setup our general branding for the window"""
        self.setWindowTitle(defaults.APP_NAME_HUMAN)
        self.setWindowIcon(icons.get_icon("microphone"))

    def create_menu(self):
        """Create the overall application menu"""
        self.menu = QMenuBar()
        app = self.app
        self.dictation_menu = self.menu.addMenu('&Dictation')
        self.dictation_menu.addAction(app.start_listening)
        self.dictation_menu.addAction(app.stop_listening)
        self.dictation_menu.addAction(app.reposition_overlay)
        self.setMenuBar(self.menu)

    def create_main(self):
        """Create our main central widgets"""
        self.mdi = QMdiArea(self)
        self.setCentralWidget(self.mdi)

    def create_status(self):
        """Create our listening status-bar"""
        self.status_bar = QStatusBar(self)
        self.setStatusBar(self.status_bar)
        self.status_bar.showMessage('%s is loading...' %
                                    (defaults.APP_NAME_HUMAN))

    def create_audio_view(self):
        """Create the audio control view"""
        self.audio_dock = QDockWidget("Audio", self)
        self.audio_dock.setFloating(False)
        self.audio_view = audioview.ListenerAudio(self)
        self.audio_dock.setWidget(self.audio_view)
        self.addDockWidget(
            Qt.LeftDockWidgetArea,
            self.audio_dock,
        )

    def create_container_view(self):
        """Create the container view"""
        self.container_dock = QDockWidget("Container", self)
        self.container_dock.setFloating(False)
        self.container_view = containersettings.ContainerSettings(self)
        self.container_dock.setWidget(self.container_view)
        self.addDockWidget(
            Qt.LeftDockWidgetArea,
            self.container_dock,
        )
Example #21
0
    def setupUi(self, Main_Window):

        def about_fn():
            about_msgbox = QMessageBox()
            about_msgbox.setWindowTitle("About")
            about_msgbox.setIcon(QMessageBox.Information)
            about_msgbox.setText(f"CV Collector {settings.version}")
            about_msgbox.setInformativeText(f'''
CV Collector is an app that lets you store your CVs in a secure and lightweight sqlite3 database.
{settings.special_text}.
            ''')
            about_msgbox.setStandardButtons(QMessageBox.Close)
            about_msgbox.exec_()
        font1 = QFont("Roboto", 20)
        font2 = QFont("Roboto", 16)
        Main_Window.setObjectName("Main_Window")
        Main_Window.resize(700, 535)
        Main_Window.setFixedSize(Main_Window.size())
        self.centralwidget = QWidget(Main_Window)
        self.centralwidget.setObjectName("centralwidget")
        self.search = QLineEdit(self.centralwidget)
        self.search.setGeometry(QRect(60, 30, 460, 50))
        self.search.setFont(font1)
        self.search.setPlaceholderText("Search..")

        menuBar = QMenuBar(self.centralwidget)
        Help = menuBar.addMenu("Help")
        About = Help.addAction("About")
        About.triggered.connect(about_fn)
        self.addBtn = QPushButton(self.centralwidget)
        self.addBtn.setGeometry(QRect(20, 90, 191, 41))
        self.addBtn.setObjectName("addBtn")
        self.deleteBtn = QPushButton(self.centralwidget)
        self.deleteBtn.setGeometry(QRect(245, 90, 191, 41))
        self.deleteBtn.setObjectName("deleteBtn")
        self.showBtn = QPushButton(self.centralwidget)
        self.showBtn.setGeometry(QRect(470, 90, 191, 41))
        self.showBtn.setObjectName("showBtn")
        self.listWidget = QTableWidget(self.centralwidget)
        self.listWidget.setGeometry(QRect(20, 150, 661, 350))
        self.listWidget.setRowCount(20)
        self.listWidget.setColumnCount(4)
        self.listWidget.setObjectName("listWidget")
        self.listWidget.hideColumn(0)
        horizontal_names = ('hidden', 'CV Name', 'CV Filename', 'Date')
        self.listWidget.setHorizontalHeaderLabels(horizontal_names)
        self.listWidget.setColumnWidth( 1, 200)
        self.listWidget.setColumnWidth( 2, 200)
        self.listWidget.setColumnWidth( 3, 200)
        self.listWidget.setFont(font2)

        def initialize():
            self.Show_Data()
        initialize()

        def search_fn():
            columnOfInterest = 1
            valueOfInterest = self.search.text()
            for rowIndex in range(self.listWidget.rowCount()):
                item = self.listWidget.item(rowIndex, columnOfInterest)
                if self.search.text() in item.text():
                    self.listWidget.setRowHidden(rowIndex, False)
                else:
                    self.listWidget.setRowHidden(rowIndex, True)


        self.searchBtn = QPushButton(self.centralwidget)
        self.searchBtn.setGeometry(QRect(530, 30, 100, 50))
        self.searchBtn.setObjectName("addBtn")
        self.searchBtn.clicked.connect(search_fn)

        Main_Window.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(Main_Window)
        self.menubar.setGeometry(QRect(0, 0, 723, 22))
        self.menubar.setObjectName("menubar")
        Main_Window.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(Main_Window)
        self.statusbar.setObjectName("statusbar")
        Main_Window.setStatusBar(self.statusbar)

        self.retranslateUi(Main_Window)
        QMetaObject.connectSlotsByName(Main_Window)
        self.showBtn.clicked.connect(self.Show_Data)

        self.addBtn.clicked.connect(self.Add)
        self.deleteBtn.clicked.connect(self.Delete)
Example #22
0
class MainWidget(QWidget):
    data_directory_group_box: DataDirectoryBox
    error_message: QErrorMessage
    grid: QVBoxLayout
    network_grid: Tabs
    network_widget: NetworkWidget
    settings_tab: SettingsTabDialog

    def __init__(self):
        super().__init__()
        self.setWindowTitle('Node Launcher')
        self.error_message = QErrorMessage(self)
        try:
            self.network_widget = NetworkWidget()
        except ZmqPortsNotOpenError as e:
            self.error_message.showMessage(str(e))
            self.error_message.exec_()
            sys.exit(0)

        self.network_grid = Tabs(self, self.network_widget)
        self.network_grid.currentChanged.connect(self.on_tab_change)

        self.grid = QVBoxLayout()

        self.settings_tab = SettingsTabDialog(
            node_set=self.network_widget.node_set)

        settings_action = QAction('&Settings', self)
        settings_action.setShortcut(QKeySequence.Preferences)
        settings_action.triggered.connect(self.settings_tab.show)

        self.menubar = QMenuBar()
        self.menubar.setMinimumWidth(self.menubar.sizeHint().width())
        file_menu = self.menubar.addMenu('&File')
        file_menu.addAction(settings_action)
        self.grid.addWidget(self.menubar)

        self.grid.addStretch()
        self.grid.addWidget(self.network_grid)
        self.setLayout(self.grid)

        self.settings_tab.bitcoin_tab.change_network.connect(
            self.change_network)

        timer = QTimer()
        timer.singleShot(1000, self.check_version)

    def on_tab_change(self, index: int):
        log.info('on_tab_change', index=index)
        if index == 1:
            self.network_grid.lncli_widget.input.setFocus()
        elif index == 2:
            self.network_grid.bitcoin_cli_widget.input.setFocus()

    def check_version(self):
        latest_version = LauncherSoftware().get_latest_release_version()
        if latest_version is None:
            return
        latest_major, latest_minor, latest_bugfix = latest_version.split('.')
        major, minor, bugfix = NODE_LAUNCHER_RELEASE.split('.')

        major_upgrade = latest_major > major

        minor_upgrade = (latest_major == major and latest_minor > minor)

        bugfix_upgrade = (latest_major == major and latest_minor == minor
                          and latest_bugfix > bugfix)

        if major_upgrade or minor_upgrade or bugfix_upgrade:
            message_box = QMessageBox(self)
            message_box.setTextFormat(Qt.RichText)
            message_box.setText(UPGRADE)
            message_box.setInformativeText(
                f'Your version: {NODE_LAUNCHER_RELEASE}\n'
                f'New version: {latest_version}')
            message_box.exec_()

    def change_network(self, network: Network):
        self.network_widget.nodes_layout.image_label.set_image(
            f'bitcoin-{network}.png')

    def mousePressEvent(self, event):
        focused_widget = QApplication.focusWidget()
        if isinstance(focused_widget, QLineEdit):
            focused_widget.clearFocus()
        QMainWindow.mousePressEvent(self, event)
Example #23
0
class MainWindow(QMainWindow):
    """
    Main Window service for the nexxT frameworks. Other services usually create dock windows, filters use the
    subplot functionality to create grid-layouted views.
    """
    mdiSubWindowCreated = Signal(
        QMdiSubWindow
    )  # TODO: remove, is not necessary anymore with subplot feature
    aboutToClose = Signal(object)

    def __init__(self, config):
        super().__init__()
        self.config = config
        self.config.appActivated.connect(self._appActivated)
        self.mdi = QMdiArea(self)
        self.mdi.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdi.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdi)
        self.menu = self.menuBar().addMenu("&Windows")
        self.aboutMenu = QMenuBar(self)
        self.menuBar().setCornerWidget(self.aboutMenu)
        m = self.aboutMenu.addMenu("&About")
        self.aboutNexxT = QAction("About nexxT ...")
        self.aboutQt = QAction("About Qt ...")
        self.aboutPython = QAction("About Python ...")
        m.addActions([self.aboutNexxT, self.aboutQt, self.aboutPython])
        self.aboutNexxT.triggered.connect(lambda: QMessageBox.about(
            self, "About nexxT", """\
This program uses <b>nexxT</b> %(version)s, a generic hybrid python/c++ framework for developing computer vision 
algorithms.<br><br>

nexxT is available under the <a href='https://github.com/ifm/nexxT/blob/master/LICENSE'>Apache 2.0 License</a> together 
with the <a href='https://github.com/ifm/nexxT/blob/master/NOTICE'>notice</a>. 
""" % dict(version=nexxT.__version__)))
        self.aboutQt.triggered.connect(lambda: QMessageBox.aboutQt(self))
        self.aboutPython.triggered.connect(self._aboutPython)
        self.toolbar = None
        self.managedMdiWindows = []
        self.managedSubplots = {}
        self.windows = {}
        self.activeApp = None
        self._ignoreCloseEvent = False

    def closeEvent(self, closeEvent):
        """
        Override from QMainWindow, saves the state.

        :param closeEvent: a QCloseEvent instance
        :return:
        """
        self._ignoreCloseEvent = False
        self.aboutToClose.emit(self)
        if self._ignoreCloseEvent:
            logger.info("Ignoring event")
            closeEvent.ignore()
            return
        closeEvent.accept()
        self.saveState()
        self.saveMdiState()
        super().closeEvent(closeEvent)

    def ignoreCloseEvent(self):
        """
        Can be called in slots connected to aboutToClose for requesting to ignore the event.
        Use case is the "There are unsaved changes" dialog.

        :return:
        """
        self._ignoreCloseEvent = True

    def restoreState(self):
        """
        restores the state of the main window including the dock windows of Services

        :return:
        """
        logger.info("restoring main window's state")
        settings = QSettings()
        v = settings.value("MainWindowState")
        if v is not None:
            super().restoreState(v)
        v = settings.value("MainWindowGeometry")
        if v is not None:
            self.restoreGeometry(v)
        if self.toolbar is not None:
            # TODO: add toolbar to windows menu, so we don't need this
            self.toolbar.show()

    def saveState(self):
        """
        saves the state of the main window including the dock windows of Services

        :return:
        """
        logger.info("saving main window's state")
        settings = QSettings()
        settings.setValue("MainWindowState", super().saveState())
        settings.setValue("MainWindowGeometry", self.saveGeometry())

    def saveMdiState(self):
        """
        saves the state of the individual MDI windows

        :return:
        """
        for i in self.managedMdiWindows:
            window = i["window"]
            propColl = i["propColl"]
            prefix = i["prefix"]
            logger.debug("save window geometry %s: %s", prefix,
                         window.geometry())
            geom = str(window.saveGeometry().toBase64(), "ascii")
            visible = self.windows[shiboken2.getCppPointer(window)
                                   [0]].isChecked()  # pylint: disable=no-member
            propColl.setProperty(prefix + "_geom", geom)
            logger.debug("%s is visible: %d", prefix, int(visible))
            propColl.setProperty(prefix + "_visible", int(visible))
        self.managedMdiWindows = []

    def __del__(self):
        logging.getLogger(__name__).debug("deleting MainWindow")

    @Slot()
    def getToolBar(self):
        """
        Get the main toolbar (adds seperators as appropriate).

        :return:
        """
        if self.toolbar is None:
            self.toolbar = self.addToolBar("NexxT")
            self.toolbar.setObjectName("NexxT_main_toolbar")
        else:
            self.toolbar.addSeparator()
        return self.toolbar

    @Slot(str, QObject, int, int)
    def newDockWidget(self,
                      name,
                      parent,
                      defaultArea,
                      allowedArea=Qt.LeftDockWidgetArea
                      | Qt.BottomDockWidgetArea,
                      defaultLoc=None):
        """
        This function is supposed to be called by services

        :param name: the name of the dock window
        :param parent: the parent (usually None)
        :param defaultArea: the default dock area
        :param allowedArea: the allowed dock areas
        :return: a new QDockWindow instance
        """
        res = NexxTDockWidget(name, parent if parent is not None else self)
        res.setAllowedAreas(allowedArea)
        res.setAttribute(Qt.WA_DeleteOnClose, False)
        self.addDockWidget(defaultArea, res)
        self._registerWindow(res, res.objectNameChanged)
        res.setObjectName(name)
        if defaultLoc is not None:
            dl = self.findChild(QDockWidget, defaultLoc)
            if dl is not None:
                self.tabifyDockWidget(dl, res)
        return res

    @staticmethod
    def parseWindowId(windowId):
        """
        convers a subplot window id into windowTitle, row and column

        :param windowId: the window id
        :return: title, row, column
        """
        regexp = re.compile(r"([^\[]+)\[(\d+),\s*(\d+)\]")
        match = regexp.match(windowId)
        if not match is None:
            return match.group(1), int(match.group(2)), int(match.group(3))
        return windowId, 0, 0

    @Slot(str, QObject, QWidget)
    def subplot(self, windowId, theFilter, widget):
        """
        Adds widget to the GridLayout specified by windowId.

        :param windowId: a string with the format "<windowTitle>[<row>,<col>]" where <windowTitle> is the caption
                         of the MDI window (and it is used as identifier for saving/restoring window state) and
                         <row>, <col> are the coordinates of the addressed subplots (starting at 0)
        :param theFilter: a Filter instance which is requesting the subplot
        :param widget:   a QWidget which shall be placed into the grid layout. Note that this widget is reparented
                         as a result of this operation and the parents can be used to get access to the MDI sub window.
                         Use releaseSubplot to remove the window
        :return: None
        """
        logger.internal("subplot '%s'", windowId)
        title, row, col = self.parseWindowId(windowId)
        if title == "":
            title = "(view)"
        if title in self.managedSubplots and (
                row, col) in self.managedSubplots[title]["plots"]:
            logger.warning(
                "subplot %s[%d,%d] is already registered. Creating a new window for the plot.",
                title, row, col)
            i = 2
            while "%s(%d)" % (title, i) in self.managedSubplots:
                i += 1
            title = "%s(%d)" % (title, i)
            row = 0
            col = 0
        if title not in self.managedSubplots:
            subWindow = self._newMdiSubWindow(theFilter, title)
            swwidget = QWidget()
            subWindow.setWidget(swwidget)
            layout = QGridLayout(swwidget)
            swwidget.setLayout(layout)
            self.managedSubplots[title] = dict(mdiSubWindow=subWindow,
                                               layout=layout,
                                               swwidget=swwidget,
                                               plots={})
        self.managedSubplots[title]["layout"].addWidget(widget, row, col)
        self.managedSubplots[title]["mdiSubWindow"].updateGeometry()
        widget.setParent(self.managedSubplots[title]["swwidget"])
        QTimer.singleShot(
            0, lambda:
            (self.managedSubplots[title]["mdiSubWindow"].adjustSize()
             if widget.parent().size().height() < widget.minimumSizeHint().
             height() or widget.parent().size().height() < widget.minimumSize(
             ).height() else None))
        self.managedSubplots[title]["plots"][row, col] = widget

    @Slot(QWidget)
    @Slot(str)
    def releaseSubplot(self, arg):
        """
        This needs to be called to release the previously allocated subplot called windowId.
        The managed widget is deleted as a consequence of this function.

        :param arg: the widget as passed to subplot. Passing the windowId is also supported, but deprecated.
        :return:
        """
        if isinstance(arg, str):
            windowId = arg
            logger.warning(
                "Using deprecated API to release a subplot. Please pass the widget instead of the windowId."
            )
            logger.internal("releaseSubplot '%s'", windowId)
            title, row, col = self.parseWindowId(windowId)
            if title not in self.managedSubplots or (
                    row, col) not in self.managedSubplots[title]["plots"]:
                logger.warning("releasSubplot: cannot find %s", windowId)
                return
            widget = self.managedSubplots[title]["plots"][row, col]
        elif isinstance(arg, QWidget):
            widget = arg
            found = False
            for title in self.managedSubplots:
                for row, col in self.managedSubplots[title]["plots"]:
                    if self.managedSubplots[title]["plots"][row,
                                                            col] is widget:
                        found = True
                        break
                if found:
                    break
            if not found:
                raise RuntimeError(
                    "cannot find widget given for releaseSubplot.")
        else:
            raise RuntimeError(
                "arg of releaseSubplot must be either a string or a QWidget instance."
            )
        self.managedSubplots[title]["layout"].removeWidget(widget)
        self.managedSubplots[title]["plots"][row, col].deleteLater()
        del self.managedSubplots[title]["plots"][row, col]
        if len(self.managedSubplots[title]["plots"]) == 0:
            self.managedSubplots[title]["layout"].deleteLater()
            self.managedSubplots[title]["swwidget"].deleteLater()
            self.managedSubplots[title]["mdiSubWindow"].deleteLater()
            del self.managedSubplots[title]

    @Slot(QObject)
    @Slot(QObject, str)
    def newMdiSubWindow(self, filterOrService, windowTitle=None):
        """
        Deprectated (use subplot(...) instead): This function is supposed to be called by filters.

        :param filterOrService: a Filter instance
        :param windowTitle: the title of the window (might be None)
        :return: a new QMdiSubWindow instance
        """
        logger.warning(
            "This function is deprecated. Use subplot function instead.")
        return self._newMdiSubWindow(filterOrService, windowTitle)

    def _newMdiSubWindow(self, filterOrService, windowTitle):
        res = NexxTMdiSubWindow(None)
        res.setAttribute(Qt.WA_DeleteOnClose, False)
        self.mdi.addSubWindow(res)
        self._registerWindow(res, res.windowTitleChanged)
        if isinstance(filterOrService, Filter):
            propColl = filterOrService.guiState()
            res.setWindowTitle(
                propColl.objectName() if windowTitle is None else windowTitle)
        else:
            app = Application.activeApplication.getApplication()
            propColl = app.guiState("services/MainWindow")
            res.setWindowTitle(
                "<unnamed>" if windowTitle is None else windowTitle)
        prefix = re.sub(r'[^A-Za-z_0-9]', '_',
                        "MainWindow_MDI_" + res.windowTitle())
        i = dict(window=res, propColl=propColl, prefix=prefix)
        self.managedMdiWindows.append(i)
        window = i["window"]
        propColl = i["propColl"]
        prefix = i["prefix"]
        propColl.defineProperty(prefix + "_geom", "", "Geometry of MDI window")
        b = QByteArray.fromBase64(
            bytes(propColl.getProperty(prefix + "_geom"), "ascii"))
        window.restoreGeometry(b)
        logger.debug("restored geometry %s:%s (%s)", prefix, window.geometry(),
                     b)
        propColl.defineProperty(prefix + "_visible", 1,
                                "Visibility of MDI window")
        if propColl.getProperty(prefix + "_visible"):
            window.show()
        else:
            window.hide()
        self.mdiSubWindowCreated.emit(res)
        return res

    def _registerWindow(self, window, nameChangedSignal):
        act = QAction("<unnamed>", self)
        act.setCheckable(True)
        act.toggled.connect(window.setVisible)
        window.visibleChanged.connect(act.setChecked)
        nameChangedSignal.connect(act.setText)
        self.windows[shiboken2.getCppPointer(window)[0]] = act  # pylint: disable=no-member
        self.menu.addAction(act)
        logger.debug("Registering window %s, new len=%d",
                     shiboken2.getCppPointer(window), len(self.windows))  # pylint: disable=no-member
        window.destroyed.connect(self._windowDestroyed)

    def _windowDestroyed(self, obj):
        logger.internal("_windowDestroyed")
        ptr = shiboken2.getCppPointer(obj)  # pylint: disable=no-member
        try:
            ptr = ptr[0]
        except TypeError:
            pass
        logger.debug("Deregistering window %s, old len=%d", ptr,
                     len(self.windows))
        self.windows[ptr].deleteLater()
        del self.windows[ptr]
        logger.debug("Deregistering window %s done", ptr)

    def _appActivated(self, name, app):
        if app is not None:
            self.activeApp = name
            app.aboutToClose.connect(self.saveMdiState, Qt.UniqueConnection)
        else:
            self.activeApp = None

    def _aboutPython(self):
        piplic = subprocess.check_output(
            [sys.executable, "-m", "piplicenses", "--format=plain"],
            encoding="utf-8").replace("\n", "<br>").replace(" ", "&nbsp;")
        QMessageBox.about(
            self, "About python", """\
This program uses <b>python</b> %(version)s and the following installed python packages.<br><br>
<pre>
%(table)s
</pre>
""" % dict(version=sys.version, table=piplic))
Example #24
0
class IccMainWindow(QMainWindow):
    def __init__(self, environment):
        QMainWindow.__init__(self)
        self.setWindowTitle("ImmoControlCenter   " + environment)
        self._menubar: QMenuBar = None
        self._viewsMenu: QMenu = None
        self._submenuShowTableContent: QMenu = None
        self._toolbar: QToolBar = None
        self._sdLetzteBuchung: SmartDateEdit = SmartDateEdit(self)
        self._leLetzteBuchung: QLineEdit = QLineEdit(self)

        # Summen
        self._idSumMiete = self._createSumDisplay("Summe aller Bruttomieten")
        self._idSummeSonstAus = self._createSumDisplay(
            "Summe aller sonstigen Ausgaben")
        self._idSummeHGV = self._createSumDisplay(
            "Summe aller Hausgeld-Vorauszahlungen")
        self._idSaldo = self._createSumDisplay(
            "Bruttomieten minus Ausgaben minus HG-Vorauszahlungen")
        self._summenfont = QFont("Times New Roman", 16, weight=QFont.Bold)
        self._summenartfont = QFont("Times New Roman", 9)
        # give others access to sum fields via Singleton SumFieldsAccess:
        self._sumfieldsAccess = SumFieldsProvider(
            self._idSumMiete, self._idSummeSonstAus, self._idSummeHGV,
            self._idSaldo, self.onSumFieldsProvidingFailed)

        self._actionCallbackFnc = None  #callback function for all action callbacks
        self._shutdownCallback = None  # callback function for shutdown action
        self._createUI()

    def onSumFieldsProvidingFailed(self, msg: str):
        self.showException(msg)

    def _createUI(self):
        self._menubar = QMenuBar(self)
        self._toolBar = QToolBar(self)

        self._createImmoCenterMenu()
        self._createMietobjektMenu()
        self._createMietverhaeltnisMenu()
        self._createZahlungenMenu()
        self._createAbrechnungenMenu()
        self._createAnlageVMenu()
        self._createExtrasMenu()
        self._createSqlMenu()
        self._createShowViewsMenu()

        self._toolBar.addSeparator()
        lbl = QLabel(self, text="Letzte verarbeitete Buchung: ")
        self._toolBar.addWidget(lbl)
        self._sdLetzteBuchung.setToolTip(
            "Freier Eintrag der Kenndaten der letzten Buchung,\n "
            "um beim nächsten Anwendungsstart gezielt weiterarbeiten zu können."
        )
        self._sdLetzteBuchung.setMaximumWidth(90)
        self._toolBar.addWidget(self._sdLetzteBuchung)
        dummy = QWidget()
        dummy.setFixedWidth(5)
        self._toolBar.addWidget(dummy)
        self._leLetzteBuchung.setToolTip(
            "Freier Eintrag der Kenndaten der letzten Buchung,\n "
            "um beim nächsten Anwendungsstart gezielt weiterarbeiten zu können."
        )
        # self._leLetzteBuchung.setMaximumWidth( 300 )
        self._toolBar.addWidget(self._leLetzteBuchung)

        dummy = QWidget()
        dummy.setFixedWidth(30)
        #dummy.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred )
        self._toolBar.addWidget(dummy)

        self._addSumFields()

        self.setMenuBar(self._menubar)
        self.addToolBar(QtCore.Qt.TopToolBarArea, self._toolBar)

    def _createImmoCenterMenu(self):
        # Menü "ImmoCenter"
        menu = QtWidgets.QMenu(self._menubar, title="ImmoCenter")
        self._menubar.addMenu(menu)

        # Menüpunkt "Alle Änderungen speichern"
        action = QAction(self, text="Alle Änderungen speichern")
        action.setShortcut(QKeySequence("Ctrl+Shift+s"))
        action.triggered.connect(self.onSaveAll)
        menu.addAction(action)

        menu.addSeparator()

        # Menü "Datenbank zum Server exportieren"
        action = QAction(self, text="Datenbank zum Server exportieren")
        action.triggered.connect(self.onExportDatabaseToServer)
        menu.addAction(action)

        # Menü "Datenbank vom Server importieren"
        action = QAction(self, text="Datenbank vom Server importieren")
        action.triggered.connect(self.onImportDatabaseFromServer)
        menu.addAction(action)

        menu.addSeparator()

        # Menüpunkt "Folgejahr einrichten"
        action = QAction(self, text="Folgejahr einrichten")
        action.triggered.connect(self.onFolgejahrEinrichten)
        menu.addAction(action)

        menu.addSeparator()

        # Menüpunkt "Ende"
        action = QAction(self, text="Ende")
        action.triggered.connect(self.onExit)
        action.setShortcut("Alt+F4")
        menu.addAction(action)

    def _createMietobjektMenu(self):
        menu = QtWidgets.QMenu(self._menubar, title="Mietobjekt")
        self._menubar.addMenu(menu)

        # Menüpunkt "Wohnungsstammdaten..."
        action = QAction(self, text="Objektstammdaten...")
        action.triggered.connect(self.onViewObjektStammdaten)
        menu.addAction(action)

        # # Menüpunkt "Mietverhältnis..."
        # action = QAction( self, text="Mietverhältnis..." )
        # action.triggered.connect( self.onViewMietverhaeltnis )
        # menu.addAction( action )

        menu.addSeparator()

        # action = QAction( self, text="Mieterwechsel..." )
        # action.triggered.connect( self.onMieterwechsel )
        # menu.addAction( action )

        action = QAction(self, text="Verwalterwechsel...")
        action.triggered.connect(self.onVerwalterwechsel)
        menu.addAction(action)

    def _createMietverhaeltnisMenu(self):
        menu = QtWidgets.QMenu(self._menubar, title="Mietverhältnis")
        self._menubar.addMenu(menu)

        # Menüpunkt "Mietverhältnis..."
        action = QAction(self, text="Mietverhältnis anschauen und ändern...")
        action.triggered.connect(self.onViewMietverhaeltnis)
        menu.addAction(action)

        menu.addSeparator()

        action = QAction(self, text="Mieterwechsel...")
        action.triggered.connect(self.onMieterwechsel)
        menu.addAction(action)

    def _createZahlungenMenu(self):
        menu = QtWidgets.QMenu(self._menubar, title="Ist- und Sollzahlungen")
        self._menubar.addMenu(menu)

        # Menüpunkt "Mietzahlungen..."
        action = QAction(self, text="Mietzahlungen...")
        action.triggered.connect(self.onViewMietzahlungen)
        menu.addAction(action)

        # Menüpunkt "HG-Vorauszahlungen..."
        action = QAction(self, text="HG-Vorauszahlungen...")
        action.triggered.connect(self.onViewHGVorauszahlungen)
        menu.addAction(action)

        # Menüpunkt "Rechnungen, Abgaben, Gebühren..."
        action = QAction(self, text="Rechnungen, Abgaben, Gebühren...")
        action.triggered.connect(self.onViewRechnungen)
        menu.addAction(action)

        menu.addSeparator()

        # Menüpunkt "Offene Posten"
        action = QAction(self, text="Offene Posten")
        action.triggered.connect(self.onViewOffenePosten)
        menu.addAction(action)

        menu.addSeparator()

        # Menüpunkt "Soll-Miete..."
        action = QAction(self, text="Soll-Miete...")
        action.triggered.connect(self.onViewSollMiete)
        menu.addAction(action)

        # Menüpunkt "Soll-Hausgeld..."
        action = QAction(self, text="Soll-Hausgeld...")
        action.triggered.connect(self.onViewSollHausgeld)
        menu.addAction(action)

        menu.addSeparator()

    def _createAbrechnungenMenu(self):
        menu = QtWidgets.QMenu(self._menubar, title="Abrechnungen")
        self._menubar.addMenu(menu)
        action = QAction(self, text="Nebenkostenabrechnung...")
        action.triggered.connect(self.onViewNebenkostenabrechnung)
        menu.addAction(action)

        action = QAction(self, text="Hausgeldabrechnung...")
        action.triggered.connect(self.onViewHausgeldabrechnung)
        menu.addAction(action)

    def _createAnlageVMenu(self):
        menu = QtWidgets.QMenu(self._menubar, title="AnlageV")
        self._menubar.addMenu(menu)
        action = QAction(self,
                         text="Anlagen V: Objektauswahl, Vorschau, Druck...")
        action.triggered.connect(self.onViewAnlageV)
        menu.addAction(action)

        # action = QAction( self, text="Anlagen V drucken..." )
        # action.triggered.connect( self.onViewHausgeldabrechnung )
        # menu.addAction( action )

    def _createExtrasMenu(self):
        menu = QtWidgets.QMenu(self._menubar, title="Extras")
        self._menubar.addMenu(menu)
        action = QAction(self, text="Geschäftsreise...")
        action.triggered.connect(self.onGeschaeftsreise)
        menu.addAction(action)
        action = QAction(self, text="Notizen...")
        action.triggered.connect(self.onNotizen)
        menu.addAction(action)
        menu.addSeparator()
        action = QAction(self, text="Sammelabgabenbescheid aufsplitten...")
        action.triggered.connect(self.onSammelabgabe)
        menu.addAction(action)
        menu.addSeparator()
        action = QAction(self, text="Renditevergleich...")
        action.triggered.connect(self.onRenditeVergleich)
        menu.addAction(action)
        menu.addSeparator()
        action = QAction(self, text="Exportiere aktive Tabelle in Calc")
        action.triggered.connect(self.onExportActiveTableView)
        menu.addAction(action)

    def _createSqlMenu(self):
        # Menü "ImmoCenter"
        menu = QtWidgets.QMenu(self._menubar, title="SQL")
        self._menubar.addMenu(menu)

        # Menüpunkt "Neue Abfrage
        action = QAction(self, text="Neue Datenbankabfrage")
        action.setShortcut(QKeySequence("Ctrl+n"))
        icon = QtGui.QIcon("../images/sql.xpm")
        action.setIcon(icon)
        action.triggered.connect(self.onNewSql)
        menu.addAction(action)
        #self._toolBar.addAction( action )

        #Menüpunkt "Ganze Tabelle anzeigen"
        self._submenuShowTableContent = QtWidgets.QMenu(
            menu, title="Ganze Tabelle anzeigen")
        menu.addMenu(self._submenuShowTableContent)

    def _createShowViewsMenu(self):
        menu = QtWidgets.QMenu(self._menubar, title="Views")
        self._menubar.addMenu(menu)
        self._viewsMenu = menu

    def _addSumFields(self):
        self._toolBar.addWidget(self._createSumLabel())
        self._toolBar.addWidget(self._createSumArtLabel("Miete", 30))
        self._toolBar.addWidget(self._idSumMiete)

        self._toolBar.addWidget(self._createLabel("-", 20))

        self._toolBar.addWidget(self._createSumLabel())
        self._toolBar.addWidget(self._createSumArtLabel("Ausgaben", 50))
        self._toolBar.addWidget(self._idSummeSonstAus)

        self._toolBar.addWidget(self._createLabel("-", 20))

        self._toolBar.addWidget(self._createSumLabel())
        self._toolBar.addWidget(self._createSumArtLabel("HGV", 40))
        self._toolBar.addWidget(self._idSummeHGV)

        self._toolBar.addWidget(self._createLabel("=", 20))

        self._toolBar.addWidget(self._idSaldo)

        self._toolBar.addWidget(self._createSpacer(20))

    def _createSumDisplay(self, tooltip: str) -> IntDisplay:
        display = IntDisplay(self)
        display.setMaximumWidth(70)
        display.setEnabled(False)
        display.setToolTip(tooltip)
        return display

    def _createSumLabel(self) -> QLabel:
        lbl = QLabel(self, text="∑")
        lbl.setFont(self._summenfont)
        lbl.setMaximumWidth(15)
        return lbl

    def _createSumArtLabel(self, sumart: str, width: int) -> QLabel:
        lbl = QLabel(self, text=sumart)
        lbl.setFont(self._summenartfont)
        lbl.setMaximumWidth(width)
        return lbl

    def _createLabel(self, text: str, width: int) -> QLabel:
        lbl = QLabel(self, text=text)
        lbl.setMinimumWidth(width)
        lbl.setMaximumWidth(width)
        lbl.setAlignment(Qt.AlignCenter)
        return lbl

    def _createSpacer(self, width: int) -> QWidget:
        spacer = QWidget(self)
        spacer.setMinimumWidth(width)
        spacer.setMaximumWidth(width)
        return spacer

    def canShutdown(self) -> bool:
        if self._shutdownCallback:
            return self._shutdownCallback()

    def setLetzteBuchung(self, datum: str, text: str) -> None:
        try:
            y, m, d = getDateParts(datum)
            self._sdLetzteBuchung.setDate(y, m, d)
        except:
            pass
        self._leLetzteBuchung.setText(text)

    def setTabellenAuswahl(self, tables: List[str]) -> None:
        """
        Fügt dem SubMenu "Ganze Tabelle anzeigen" soviele Tabellen-Namen hinzu wie in <tables> enthalten.
        :param tables:
        :return:
        """
        n = len(tables)
        actions = [QAction(self._submenuShowTableContent) for i in range(n)]
        for i in range(n):
            act = actions[i]
            act.setText(tables[i])
            #act.triggered.connect( lambda action=act: self.onShowTableContent(action) ) --> funktioniert nicht
            act.triggered.connect(partial(self.onShowTableContent, act))
            #txt = act.text()
            #act.triggered.connect( lambda table=txt: self.showTableContent.emit( txt ) ) --> funktioniert nicht
            self._submenuShowTableContent.addAction(act)

    def getLetzteBuchung(self) -> Dict:
        """
        :return: dictionary with keys "date" and "text"
        """
        d = dict()
        d["datum"] = self._sdLetzteBuchung.getDate()
        d["text"] = self._leLetzteBuchung.text()
        return d

    def setShutdownCallback(self, callbackFnc) -> None:
        self._shutdownCallback = callbackFnc

    def setActionCallback(self, callbackFnc) -> None:
        self._actionCallbackFnc = callbackFnc

    def addOpenedDialog(self, name: str, data: Any):
        """
        Fügt dem Views-Menü eine gerade geöffnete View hinzu
        :param name:
        :param data:
        :return:
        """
        action = QAction(self._viewsMenu, text=name)
        action.setData(data)
        self._viewsMenu.addAction(action)
        #action.triggered.connect( lambda name=name, data=data: self.bringDialogToFront.emit( name, data ) )
        action.triggered.connect(partial(self.onShowDialog, action))

    def getOpenedDialogs(self) -> List[IccDialog]:
        return [a.data() for a in self._viewsMenu.actions()]

    def removeClosedDialog(self, name: str, data: Any):
        """
        Entfernt den Eintrag <name> aus dem Views-Menü.
        :param name:  Name der zu entfernenden  View (entspricht dem Text des Menüpunktes)
        :param data: Wird zur Identifikation der View verwendet.
        :return:
        """
        for a in self._viewsMenu.actions():
            if a.data() == data:
                self._viewsMenu.removeAction(a)
                break
        return

    def doCallback(self, action: MainWindowAction, arg=None):
        if self._actionCallbackFnc:
            if arg:
                self._actionCallbackFnc(action, arg)
            else:
                self._actionCallbackFnc(action)

    def onNewWindow(self):
        self.doCallback(MainWindowAction.NEW_WINDOW)

    def onMieterwechsel(self):
        self.doCallback(MainWindowAction.MIETERWECHSEL)

    def onVerwalterwechsel(self):
        pass

    # def onChangeSollmiete( self ):
    #     pass
    #
    # def onChangeSollhausgeld( self ):
    #     pass

    # def onSaveActiveView( self ):
    #     self.doCallback( MainWindowAction.SAVE_ACTIVE_VIEW )

    def onSaveAll(self):
        self.doCallback(MainWindowAction.SAVE_ALL)

    def onExportDatabaseToServer(self):
        self.doCallback(MainWindowAction.EXPORT_DB_TO_SERVER)

    def onImportDatabaseFromServer(self):
        self.doCallback(MainWindowAction.IMPORT_DB_FROM_SERVER)

    def onFolgejahrEinrichten(self):
        self.doCallback(MainWindowAction.FOLGEJAHR)

    def onPrintActiveView(self):
        self.doCallback(MainWindowAction.PRINT_ACTIVE_VIEW)

    def onExit(self):
        self.doCallback(MainWindowAction.EXIT)

    def onViewMietzahlungen(self):
        self.doCallback(MainWindowAction.OPEN_MIETE_VIEW)

    def onViewHGVorauszahlungen(self):
        self.doCallback(MainWindowAction.OPEN_HGV_VIEW)

    def onViewSollMiete(self):
        self.doCallback(MainWindowAction.OPEN_SOLL_MIETE_VIEW)

    def onViewSollHausgeld(self):
        self.doCallback(MainWindowAction.OPEN_SOLL_HG_VIEW)

    def onViewNebenkostenabrechnung(self):
        self.doCallback(MainWindowAction.OPEN_NKA_VIEW)

    def onViewHausgeldabrechnung(self):
        self.doCallback(MainWindowAction.OPEN_HGA_VIEW)

    def onViewAnlageV(self):
        self.doCallback(MainWindowAction.OPEN_ANLAGEV_VIEW)

    def onExportActiveTableView(self):
        self.doCallback(MainWindowAction.EXPORT_CSV)

    def onNotizen(self):
        self.doCallback(MainWindowAction.NOTIZEN)

    def onSammelabgabe(self):
        self.doCallback(MainWindowAction.SAMMELABGABE_DETAIL)

    def onGeschaeftsreise(self):
        self.doCallback(MainWindowAction.OPEN_GESCHAEFTSREISE_VIEW)

    def onRenditeVergleich(self):
        self.doCallback(MainWindowAction.RENDITE_VIEW)

    def onViewRechnungen(self):
        self.doCallback(MainWindowAction.OPEN_SONST_EIN_AUS_VIEW)

    def onViewOffenePosten(self):
        self.doCallback(MainWindowAction.OPEN_OFFENE_POSTEN_VIEW)

    def onViewObjektStammdaten(self):
        self.doCallback(MainWindowAction.OPEN_OBJEKT_STAMMDATEN_VIEW)

    def onViewMietverhaeltnis(self):
        self.doCallback(MainWindowAction.OPEN_MIETVERH_VIEW)

    def onNewSql(self):
        pass

    def onShowTableContent(self, action):
        self.doCallback(MainWindowAction.SHOW_TABLE_CONTENT, action.text())

    def onShowDialog(self, action):
        self.doCallback(MainWindowAction.BRING_DIALOG_TO_FRONT, action.data())

    def showException(self, exception: str, moretext: str = None):
        print(exception)
        msg = QtWidgets.QMessageBox()
        msg.setIcon(QMessageBox.Critical)
        msg.setText(exception)
        if moretext:
            msg.setInformativeText(moretext)
        msg.setWindowTitle("Error")
        msg.exec_()

    def showInfo(self, title, msg):
        box = InfoBox(title, msg, "", "OK")
        box.exec_()
Example #25
0
    def __init__(self, enigma_api, cursor_handler):
        """Initializes Root QT window widgets
        :param enigma_api: {EnigmaAPI} Shared EnigmaAPI object
        """
        super().__init__()

        # QT WINDOW SETTINGS ==================================================

        self.setWindowIcon(QIcon(BASE_DIR + "enigma_200px.png"))
        main_layout = QVBoxLayout(self)
        self.setLayout(main_layout)

        # SAVE ATTRIBUTES =====================================================

        self.__enigma_api = enigma_api
        logging.info("Qt GUI initialized with EnigmaAPI settings:\n%s",
                     str(enigma_api))

        # MENU BAR ============================================================

        menu = QMenuBar(self)
        save_load_menu = menu.addMenu("Save/load settings")
        save_load_menu.addAction("Save settings", self.save_config)
        save_load_menu.addAction("Load settings", self.load_config)
        menu.addAction("Export message", self.export_message)

        # ROTORS INDICATOR ====================================================

        logging.info("Generating rotor and reflector indicators...")
        self.__rotors = _RotorsHandlerWidget(
            self,
            self.__enigma_api.positions,
            self.__enigma_api.generate_rotate_callback,
            self.__enigma_api.rotate_reflector,
            enigma_api,
            self.refresh_gui,
            enigma_api.reflector_position,
        )

        # LIGHTBOARD FRAME ====================================================

        logging.info("Adding Lightboard...")
        self.__lightboard = _LightboardWidget(self, self.__enigma_api.charset)

        # INPUT OUTPUT FOR ENCRYPTION/DECRYPTION ==============================

        logging.info("Adding I/O textboxes...")
        self.__output_textbox = _OutputTextBoxWidget(
            self, self.__lightboard.light_up, enigma_api.letter_group)
        self.__input_textbox = _InputTextBoxWidget(
            self, enigma_api.encrypt, self.__output_textbox.insert,
            self.__output_textbox, self.__rotors.set_positions,
            enigma_api.letter_group, enigma_api.revert_by,
            enigma_api.buffer_full,
            enigma_api.data()["charset"], cursor_handler)

        # PLUGBOARD BUTTONS ===================================================

        logging.info("Adding Plugboard button")
        self.__plug_button = QPushButton("Plugboard")
        self.__plug_button.setToolTip("Edit plugboard letter pairs")
        self.__plug_button.clicked.connect(self.__open_plugboard_window)

        # SHOW WIDGETS ========================================================

        logging.info("Showing all widgets...")
        main_layout.addWidget(menu, alignment=Qt.AlignTop)
        main_layout.addWidget(self.__rotors, alignment=Qt.AlignBottom)
        main_layout.addWidget(self.__lightboard)
        main_layout.addWidget(
            QLabel("INPUT", self, styleSheet="font-size: 20px"),
            alignment=Qt.AlignCenter,
        )
        main_layout.addWidget(self.__input_textbox)
        main_layout.addWidget(
            QLabel("OUTPUT", self, styleSheet="font-size: 20px"),
            alignment=Qt.AlignCenter,
        )
        main_layout.addWidget(self.__output_textbox)
        main_layout.addWidget(self.__plug_button)

        self.refresh_gui()
        self.show()
Example #26
0
class MyWidget(QWidget):
    MAX_SHOWN_LINES = 10
    PROCESS_NUMBER = 2
    STOP_THREADS = False
    # Files
    APP_DIR = 'app'
    HTML = '.html'
    XML = '.xml'
    TXT = '.txt'
    EXTENSIONS = [TXT, XML, HTML]

    def __init__(self):
        QWidget.__init__(self)
        # Configuration from CLI interface
        self.file_names = []
        self.disable_logging = False
        self.result_filter = None
        self.filters = []
        self.configuration = []
        # Internal subprocess attributes
        # Shared queues, first for steps and second for processes
        self.queues = None
        self.worker = None
        self.processes = []
        self.thread = None
        self.show_steps_thread = None
        self.web_views = []

        # Create Menu bar
        self.setWindowTitle("Sec&Po testing framework")
        self.main_menu = QMenuBar()
        self.file_menu = self.main_menu.addMenu("File")
        self.configure_menu = self.main_menu.addMenu("Configure")
        # Set actions
        file_actions = self.create_file_actions()
        for action in file_actions:
            self.file_menu.addAction(action)
        manage_actions = self.create_management_actions()
        for action in manage_actions:
            self.configure_menu.addAction(action)

        # Create main window
        self.selected_files = QLabel(
            "Here will be printed some of the selected files")
        self.finish_button = QPushButton("&Run security and"
                                         " portability testing")
        # Connecting the signal
        self.finish_button.clicked.connect(self.run_testing)

        self.results_label = QLabel("No results")
        self.show_results_button = QPushButton("&Show results")
        self.show_results_button.clicked.connect(self.load_html_result)

        # Create file dialog
        self.file_dialog = QFileDialog(self)
        # fixme: debug for pycharm
        # self.file_dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        self.file_dialog.setFileMode(QFileDialog.ExistingFiles)
        file_filters = ["All files files (*)"]
        for value in ProgramTypes:
            file_filters.append(value.name + " files (")
            for program_filters in next(iter(value.value.values())):
                file_filters[len(file_filters) - 1] += "*" + program_filters\
                                                       + " "
            file_filters[len(file_filters) - 1] += ")"
        self.file_dialog.setNameFilters(file_filters)
        self.file_dialog.setViewMode(QFileDialog.Detail)
        # Add proxy model to change default behaviour or file selector
        # todo: does not work with files only directories.
        # However selecting of both must be overridden with own QFileDialog
        # proxy = ProxyModel(self.file_dialog)
        # self.file_dialog.setProxyModel(proxy)
        # Set layout of elements
        self._set_layout()

    def _set_layout(self):
        self.layout = QFormLayout()
        self.layout.setFormAlignment(Qt.AlignHCenter | Qt.AlignTop)
        self.layout.setFieldGrowthPolicy(QFormLayout.FieldsStayAtSizeHint)
        self.layout.setVerticalSpacing(150)
        self.layout.setHorizontalSpacing(220)
        self.layout.setLabelAlignment(Qt.AlignRight)
        self.layout.addRow(self.main_menu)
        self.finish_button.setFixedSize(250, 65)
        self.layout.addRow(self.selected_files, self.finish_button)
        self.show_results_button.setFixedSize(250, 65)
        self.layout.addRow(self.results_label, self.show_results_button)
        self.setLayout(self.layout)

    def create_file_actions(self):
        openAct = QAction(QIcon("images/folder.png"), self.tr("&Open..."),
                          self)
        openAct.setShortcuts(QKeySequence.Open)
        openAct.setStatusTip(
            self.tr("Open an existing file, "
                    "files or directories"))
        openAct.triggered.connect(self.open)

        addFilter = QAction(QIcon("images/filter.png"), self.tr("&Add filter"),
                            self)
        # addFilter.setShortcuts()
        addFilter.setStatusTip(
            self.tr("Select filter files to apply "
                    " result filtering"))
        addFilter.triggered.connect(self.add_filter)

        return [openAct, addFilter]

    def create_management_actions(self):
        manageAct = QAction(QIcon("images/settings.png"),
                            self.tr("&Manage filters"), self)
        # manageAct.setShortcuts(QKeySequence.Open)
        manageAct.setStatusTip(self.tr("Manage added filters"))
        manageAct.triggered.connect(self.manage_filters)

        docker_conf_action = QAction(QIcon("images/docker.png"),
                                     self.tr("&Docker"), self)
        # docker_conf_action.setShortcuts()
        docker_conf_action.setStatusTip(self.tr("Docker"))
        docker_conf_action.triggered.connect(self.docker_conf)

        apparmor_conf_action = QAction(QIcon("images/apparmor.png"),
                                       self.tr("&Apparmor"), self)
        # apparmor_conf_action.setShortcuts()
        apparmor_conf_action.setStatusTip(self.tr("Apparmor"))
        apparmor_conf_action.triggered.connect(self.apparmor_conf)

        seccomp_conf_action = QAction(QIcon("images/lock.png"),
                                      self.tr("&Seccomp"), self)
        # docker_conf_action.setShortcuts()
        seccomp_conf_action.setStatusTip(self.tr("Seccomp"))
        seccomp_conf_action.triggered.connect(self.seccomp_conf)

        return [
            manageAct, docker_conf_action, apparmor_conf_action,
            seccomp_conf_action
        ]

    def add_filter(self):
        pass

    def manage_filters(self):
        output = subprocess.check_output(['secpo', '--list-filters'])
        dialog = QDialog(self)
        label = QLabel("Managed filters are: {}".format(
            output.decode('utf-8')))
        # dialog.set
        widgets = QWidget()

        layout = QHBoxLayout()
        layout.addWidget(dialog)
        layout.addWidget(label)

        widgets.setLayout(layout)
        widgets.show()
        dialog.exec()
        pass

    def docker_conf(self):
        pass

    def apparmor_conf(self):
        pass

    def seccomp_conf(self):
        pass

    def check_result_dir(self, file_name):
        result_dir = file_name.parent / self.APP_DIR
        if result_dir.exists():
            self.results_label.setText("Results present")

    def open(self):
        output = 'No files chosen!'
        self.file_names = []
        cnt = 0
        # fixme: running code from pycharm causes to not use
        # regular path system but symlinks
        # https://stackoverflow.com/questions/57646908/pyqt5-qfiledialog-is-not-returning-correct-paths-in-ubuntu
        if self.file_dialog.exec():
            self.file_names = self.file_dialog.selectedFiles()
            if self.file_names:
                output = ''
            for file_name in self.file_names:
                if cnt < self.MAX_SHOWN_LINES and file_name:
                    # Correct the path
                    absolute_path = pathlib.Path(file_name)
                    self.check_result_dir(absolute_path)
                    output += str(pathlib.Path(absolute_path.parts
                                               [len(absolute_path.parts) - 2])\
                                  / pathlib.Path(absolute_path.name)) + '\n'
                    cnt += 1
        self.selected_files.setText(output + "\n")

    def open_single_result_view(self, result_file):
        if isinstance(self.web_views[-1], QWebEngineView):
            self.web_views[-1].load(QUrl(result_file.as_uri()))
            self.web_views[-1].showMaximized()
        elif isinstance(self.web_views[-1], QTextBrowser):
            text_doc = QTextDocument()
            self.web_views[-1].setDocument(text_doc)
            self.web_views[-1].setSource(
                QUrl(result_file.as_uri(), QUrl.ParsingMode.TolerantMode))
            self.web_views[-1].show()

    def load_html_result(self):
        for file in self.file_names:
            root_dir = pathlib.Path(file).parent
            root_dir /= self.APP_DIR
            if root_dir.exists():
                for extension in self.EXTENSIONS:
                    result_files = root_dir.glob('**/*' + extension)
                    for result_file in result_files:
                        if extension == self.HTML or extension == self.XML:
                            self.web_views.append(QWebEngineView())
                        elif extension == self.TXT:
                            self.web_views.append(QTextBrowser())
                        self.open_single_result_view(result_file)

    def show_steps(self, progress):
        while True:
            time.sleep(0.5)
            if not self.queues[0].empty():
                steps = self.queues[0].get()
                progress.setValue(steps.value)
                if steps.value == len(self.file_names) * 2:
                    self.thread.quit()
                    self.check_result_dir(pathlib.Path(self.file_names[0]))
                    break
            if self.STOP_THREADS:
                break

    def remove_processes(self):
        self.processes = []

    def cancel(self):
        for process in self.processes:
            self.queues[1].put(process.pid)
            time.sleep(5)
        # Set stop threads to true to indicate end of program
        self.STOP_THREADS = True
        if self.thread:
            self.thread.quit()
        self.processes = []

    def run_testing(self):
        if not self.file_names:
            self.selected_files.setText(
                "No files were selected. Go to menu and "
                "select files to test.")
            return
        # Create new queues every run
        self.queues = [
            multiprocessing.Queue(maxsize=self.PROCESS_NUMBER),
            multiprocessing.Queue(maxsize=self.PROCESS_NUMBER)
        ]
        self.STOP_THREADS = False
        progress = QProgressDialog("Starting Docker and VMs", "Abort start", 0,
                                   len(self.file_names) * 2, self)
        progress.canceled.connect(self.cancel)
        progress.setWindowModality(Qt.WindowModal)

        # Create Qthread to show progress
        self.thread = QThread()
        self.worker = Worker(self, self.file_names, self.queues)
        self.worker.moveToThread(self.thread)
        # Custom signals connected to own functions for progress dialog
        self.show_steps_thread = threading.Thread(target=self.show_steps,
                                                  args=(progress, ))
        self.show_steps_thread.start()
        # Thread start and stop signals connected with slots
        self.thread.started.connect(self.worker.run)
        self.thread.finished.connect(self.remove_processes)
        # Start thread and force to show progress dialog
        self.thread.start()
        progress.forceShow()

    def closeEvent(self, event: PySide2.QtGui.QCloseEvent):
        event.ignore()
        super(MyWidget, self).closeEvent(event)
        # Indicate end of program
        if self.thread:
            self.thread.quit()
            self.thread.wait()
        for process in self.processes:
            if process:
                if os.name == 'nt':
                    process.send_signal(signal.CTRL_C_EVENT)
                else:
                    process.send_signal(signal.SIGINT)
Example #27
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)
Example #28
0
    def setUpMenus(self) -> None:
        menuBar = QMenuBar()
        fileMenu = menuBar.addMenu('File')
        importMenu = fileMenu.addMenu('Import')
        exportMenu = fileMenu.addMenu('Export')
        flowMenu = menuBar.addMenu('Flow')
        viewMenu = menuBar.addMenu('View')
        helpMenu = menuBar.addMenu('Help')
        aAppendEmpty = QAction('Add frame', fileMenu)
        aAppendEmpty.setStatusTip('Create an empty dataframe in the workbench')
        aQuit = QAction('Quit', fileMenu)
        aLoadCsv = OperationAction(CsvLoader, fileMenu, 'From csv',
                                   self.rect().center(),
                                   self.centralWidget().workbenchModel)
        self.aWriteCsv = OperationAction(CsvWriter,
                                         fileMenu,
                                         'To csv',
                                         self.rect().center(),
                                         w=self.centralWidget().workbenchModel)
        aLoadPickle = OperationAction(PickleLoader, fileMenu, 'From pickle',
                                      self.rect().center(),
                                      self.centralWidget().workbenchModel)
        self.aWritePickle = OperationAction(
            PickleWriter,
            fileMenu,
            'To pickle',
            self.mapToGlobal(self.rect().center()),
            w=self.centralWidget().workbenchModel)
        aCompareFrames = QAction('Compare dataframes', viewMenu)
        aLogDir = QAction('Open log directory', helpMenu)
        aClearLogs = QAction('Delete old logs', helpMenu)
        fileMenu.addActions([aAppendEmpty, aQuit])
        exportMenu.addActions([self.aWriteCsv, self.aWritePickle])
        importMenu.addActions([aLoadCsv, aLoadPickle])

        self._aStartFlow = QAction('Execute', flowMenu)
        self._aResetFlow = QAction('Reset', flowMenu)
        aSaveFlow = QAction('Save', flowMenu)
        aLoadFlow = QAction('Load', flowMenu)
        flowMenu.addActions(
            [self._aStartFlow, self._aResetFlow, aSaveFlow, aLoadFlow])
        viewMenu.addAction(aCompareFrames)
        helpMenu.addActions([aLogDir, aClearLogs])

        self.setMenuBar(menuBar)

        # Tips
        aLoadCsv.setStatusTip('Load a csv file in the workbench')
        aLoadPickle.setStatusTip('Load a Pickle file in the workbench')
        self.aWriteCsv.setStatusTip('Write a dataframe to a csv file')
        self.aWritePickle.setStatusTip(
            'Serializes a dataframe into a pickle file')
        aCompareFrames.setStatusTip('Open two dataframes side by side')
        self._aStartFlow.setStatusTip('Start flow-graph execution')
        self._aResetFlow.setStatusTip('Reset the node status in flow-graph')
        aLogDir.setStatusTip('Open the folder containing all logs')
        aClearLogs.setStatusTip('Delete older logs and keep the last 5')

        # Connect
        aAppendEmpty.triggered.connect(
            self.centralWidget().workbenchModel.appendEmptyRow)
        aQuit.triggered.connect(self.close)
        self._aStartFlow.triggered.connect(
            self.centralWidget().controller.executeFlow)
        self._aResetFlow.triggered.connect(
            self.centralWidget().controller.resetFlowStatus)
        aCompareFrames.triggered.connect(self.openComparePanel)
        aLogDir.triggered.connect(self.openLogDirectory)
        aClearLogs.triggered.connect(self.clearLogDir)
        aSaveFlow.triggered.connect(self.saveFlow)
        aLoadFlow.triggered.connect(self.readFlow)

        aLoadCsv.stateChanged.connect(self.operationStateChanged)
        aLoadPickle.stateChanged.connect(self.operationStateChanged)
        self.aWriteCsv.stateChanged.connect(self.operationStateChanged)
        self.aWritePickle.stateChanged.connect(self.operationStateChanged)
Example #29
0
class MainWindow(QWidget):

    # noinspection PyUnresolvedReferences
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Cobaya input generator for Cosmology")
        self.setStyleSheet("* {font-size:%s;}" % font_size)
        # Menu bar for defaults
        self.menubar = QMenuBar()
        defaults_menu = self.menubar.addMenu(
            '&Show defaults and bibliography for a component...')
        menu_actions = {}
        for kind in kinds:
            submenu = defaults_menu.addMenu(subfolders[kind])
            components = get_available_internal_class_names(kind)
            menu_actions[kind] = {}
            for component in components:
                menu_actions[kind][component] = QAction(component, self)
                menu_actions[kind][component].setData((kind, component))
                menu_actions[kind][component].triggered.connect(
                    self.show_defaults)
                submenu.addAction(menu_actions[kind][component])
        # Main layout
        self.menu_layout = QVBoxLayout()
        self.menu_layout.addWidget(self.menubar)
        self.setLayout(self.menu_layout)
        self.layout = QHBoxLayout()
        self.menu_layout.addLayout(self.layout)
        self.layout_left = QVBoxLayout()
        self.layout.addLayout(self.layout_left)
        self.layout_output = QVBoxLayout()
        self.layout.addLayout(self.layout_output)
        # LEFT: Options
        self.options = QWidget()
        self.layout_options = QVBoxLayout()
        self.options.setLayout(self.layout_options)
        self.options_scroll = QScrollArea()
        self.options_scroll.setWidget(self.options)
        self.options_scroll.setWidgetResizable(True)
        self.layout_left.addWidget(self.options_scroll)
        self.combos = dict()
        for group, fields in _combo_dict_text:
            group_box = QGroupBox(group)
            self.layout_options.addWidget(group_box)
            group_layout = QVBoxLayout(group_box)
            for a, desc in fields:
                self.combos[a] = QComboBox()
                # Combo box label only if not single element in group
                if len(fields) > 1:
                    label = QLabel(desc)
                    group_layout.addWidget(label)
                group_layout.addWidget(self.combos[a])
                self.combos[a].addItems([
                    text(k, v) for k, v in getattr(input_database, a).items()
                ])
        # PLANCK NAMES CHECKBOX TEMPORARILY DISABLED
        #                if a == "theory":
        #                    # Add Planck-naming checkbox
        #                    self.planck_names = QCheckBox(
        #                        "Keep common parameter names "
        #                        "(useful for fast CLASS/CAMB switching)")
        #                    group_layout.addWidget(self.planck_names)
        # Connect to refreshers -- needs to be after adding all elements
        for field, combo in self.combos.items():
            if field == "preset":
                combo.currentIndexChanged.connect(self.refresh_preset)
            else:
                combo.currentIndexChanged.connect(self.refresh)
        #        self.planck_names.stateChanged.connect(self.refresh_keep_preset)
        # RIGHT: Output + buttons
        self.display_tabs = QTabWidget()
        self.display = {}
        for k in ["yaml", "python", "bibliography"]:
            self.display[k] = QTextEdit()
            self.display[k].setLineWrapMode(QTextEdit.NoWrap)
            self.display[k].setFontFamily("mono")
            self.display[k].setCursorWidth(0)
            self.display[k].setReadOnly(True)
            self.display_tabs.addTab(self.display[k], k)
        self.display["covmat"] = QWidget()
        covmat_tab_layout = QVBoxLayout()
        self.display["covmat"].setLayout(covmat_tab_layout)
        self.covmat_text = QLabel()
        self.covmat_text.setWordWrap(True)
        self.covmat_table = QTableWidget(0, 0)
        self.covmat_table.setEditTriggers(
            QAbstractItemView.NoEditTriggers)  # ReadOnly!
        covmat_tab_layout.addWidget(self.covmat_text)
        covmat_tab_layout.addWidget(self.covmat_table)
        self.display_tabs.addTab(self.display["covmat"], "covariance matrix")
        self.layout_output.addWidget(self.display_tabs)
        # Buttons
        self.buttons = QHBoxLayout()
        self.save_button = QPushButton('Save as...', self)
        self.copy_button = QPushButton('Copy to clipboard', self)
        self.buttons.addWidget(self.save_button)
        self.buttons.addWidget(self.copy_button)
        self.save_button.released.connect(self.save_file)
        self.copy_button.released.connect(self.copy_clipb)
        self.layout_output.addLayout(self.buttons)
        self.save_dialog = QFileDialog()
        self.save_dialog.setFileMode(QFileDialog.AnyFile)
        self.save_dialog.setAcceptMode(QFileDialog.AcceptSave)
        self.read_settings()
        self.show()

    def read_settings(self):
        settings = get_settings()
        # noinspection PyArgumentList
        screen = QApplication.desktop().screenGeometry()
        h = min(screen.height() * 5 / 6., 900)
        size = QSize(min(screen.width() * 5 / 6., 1200), h)
        pos = settings.value("pos", None)
        savesize = settings.value("size", size)
        if savesize.width() > screen.width():
            savesize.setWidth(size.width())
        if savesize.height() > screen.height():
            savesize.setHeight(size.height())
        self.resize(savesize)
        if ((pos is None or pos.x() + savesize.width() > screen.width()
             or pos.y() + savesize.height() > screen.height())):
            self.move(screen.center() - self.rect().center())
        else:
            self.move(pos)

    def write_settings(self):
        settings = get_settings()
        settings.setValue("pos", self.pos())
        settings.setValue("size", self.size())

    def closeEvent(self, event):
        self.write_settings()
        event.accept()

    def create_input(self):
        return create_input(
            get_comments=True,
            #           planck_names=self.planck_names.isChecked(),
            **{
                field: list(getattr(input_database,
                                    field))[combo.currentIndex()]
                for field, combo in self.combos.items() if field != "preset"
            })

    @Slot()
    def refresh_keep_preset(self):
        self.refresh_display(self.create_input())

    @Slot()
    def refresh(self):
        self.combos["preset"].blockSignals(True)
        self.combos["preset"].setCurrentIndex(0)
        self.combos["preset"].blockSignals(False)
        self.refresh_display(self.create_input())

    @Slot()
    def refresh_preset(self):
        preset = list(getattr(input_database,
                              "preset"))[self.combos["preset"].currentIndex()]
        if preset is input_database._none:
            return
        info = create_input(
            get_comments=True,
            #            planck_names=self.planck_names.isChecked(),
            preset=preset)
        self.refresh_display(info)
        # Update combo boxes to reflect the preset values, without triggering update
        for k, v in input_database.preset[preset].items():
            if k in [input_database._desc]:
                continue
            self.combos[k].blockSignals(True)
            self.combos[k].setCurrentIndex(self.combos[k].findText(
                text(v,
                     getattr(input_database, k).get(v))))
            self.combos[k].blockSignals(False)

    def refresh_display(self, info):
        QApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            comments = info.pop(input_database._comment, None)
            comments_text = "\n# " + "\n# ".join(comments)
        except (
                TypeError,  # No comments
                AttributeError
        ):  # Failed to generate info (returned str instead)
            comments_text = ""
        self.display["python"].setText("info = " + pformat(info) +
                                       comments_text)
        self.display["yaml"].setText(
            yaml_dump(sort_cosmetic(info)) + comments_text)
        self.display["bibliography"].setText(
            prettyprint_bib(*get_bib_info(info)))
        # Display covmat
        packages_path = resolve_packages_path()
        if not packages_path:
            self.covmat_text.setText(
                "\nIn order to find a covariance matrix, you need to define an external "
                "packages installation path, e.g. via the env variable %r.\n" %
                _packages_path_env)
        elif any(not os.path.isdir(d.format(**{_packages_path: packages_path}))
                 for d in covmat_folders):
            self.covmat_text.setText(
                "\nThe external cosmological packages appear not to be installed where "
                "expected: %r\n" % packages_path)
        else:
            covmat_data = get_best_covmat(info, packages_path=packages_path)
            self.current_params_in_covmat = covmat_data["params"]
            self.current_covmat = covmat_data["covmat"]
            _, corrmat = cov_to_std_and_corr(self.current_covmat)
            self.covmat_text.setText(
                "\nCovariance file: %r\n\n"
                "NB: you do *not* need to save or copy this covariance matrix: "
                "it will be selected automatically.\n" % covmat_data["name"])
            self.covmat_table.setRowCount(len(self.current_params_in_covmat))
            self.covmat_table.setColumnCount(len(
                self.current_params_in_covmat))
            self.covmat_table.setHorizontalHeaderLabels(
                list(self.current_params_in_covmat))
            self.covmat_table.setVerticalHeaderLabels(
                list(self.current_params_in_covmat))
            for i, pi in enumerate(self.current_params_in_covmat):
                for j, pj in enumerate(self.current_params_in_covmat):
                    self.covmat_table.setItem(
                        i, j,
                        QTableWidgetItem("%g" % self.current_covmat[i, j]))
                    if i != j:
                        color = [
                            256 * c
                            for c in cmap_corr(corrmat[i, j] / 2 + 0.5)[:3]
                        ]
                    else:
                        color = [255.99] * 3
                    self.covmat_table.item(i, j).setBackground(QColor(*color))
                    self.covmat_table.item(i, j).setForeground(QColor(0, 0, 0))
        QApplication.restoreOverrideCursor()

    def save_covmat_txt(self, file_handle=None):
        """
        Saved covmat to given file_handle. If none given, returns the text to be saved.
        """
        return_txt = False
        if not file_handle:
            file_handle = io.BytesIO()
            return_txt = True
        np.savetxt(file_handle,
                   self.current_covmat,
                   header=" ".join(self.current_params_in_covmat))
        if return_txt:
            return file_handle.getvalue().decode()

    @Slot()
    def save_file(self):
        ftype = next(k for k, w in self.display.items()
                     if w is self.display_tabs.currentWidget())
        ffilter = {
            "yaml": "Yaml files (*.yaml *.yml)",
            "python": "(*.py)",
            "bibliography": "(*.txt)",
            "covmat": "(*.covmat)"
        }[ftype]
        fsuffix = {
            "yaml": ".yaml",
            "python": ".py",
            "bibliography": ".txt",
            "covmat": ".covmat"
        }[ftype]
        fname, path = self.save_dialog.getSaveFileName(self.save_dialog,
                                                       "Save input file",
                                                       fsuffix, ffilter,
                                                       os.getcwd())
        if not fname.endswith(fsuffix):
            fname += fsuffix
        with open(fname, "w+", encoding="utf-8") as f:
            if self.display_tabs.currentWidget() == self.display["covmat"]:
                self.save_covmat_txt(f)
            else:
                f.write(self.display_tabs.currentWidget().toPlainText())

    @Slot()
    def copy_clipb(self):
        if self.display_tabs.currentWidget() == self.display["covmat"]:
            self.clipboard.setText(self.save_covmat_txt())
        else:
            self.clipboard.setText(
                self.display_tabs.currentWidget().toPlainText())

    def show_defaults(self):
        kind, component = self.sender().data()
        self.current_defaults_diag = DefaultsDialog(kind,
                                                    component,
                                                    parent=self)
Example #30
0
class MainWindow(QMainWindow):
    def __init__(self,*args,**kwargs):
        super(MainWindow,self).__init__(*args,**kwargs)
        self.ventanaHelp = HelpContentWindow()
        self.ventana = AddProductWindow(self)
        self.menuBar = QMenuBar(self)
        self.setMenuBar(self.menuBar)
        help_menu = self.menuBar.addMenu('&Ayuda')
        help_content = QAction('&Contenido',self)
        help_acerca = QAction('&Acerca de',self)
        help_menu.addAction(help_content)
        help_menu.addAction(help_acerca)
        help_content.triggered.connect(self.help_content_triggered)
        focus_in_signal = Signal()
        self.majorLayout = QHBoxLayout()
        self.layout = QVBoxLayout()
        self.table = QTableView()
        self.marco = QFrame()
        self.marco.setFrameStyle(QFrame.Box)
        self.marco.setLayout(self.layout)
        self.inputCommands = LineEdit()
        self.inputCommands.setText('Ingrese un comando')
        self.inputCommands.focus_in_signal.connect(self.focus_in_command)
        self.layout.addWidget(self.inputCommands)
        self.inputCommands.returnPressed.connect(self.command_agrega_producto)
        self.inputCommands.hide()
        self.input = QLineEdit()
        self.layout.addWidget(self.table)
        self.layout.addWidget(self.input)
        self.majorLayout.addWidget(self.marco)
        self.total = QLabel()
        self.total.setText('Total: 0.00')
        self.total.setStyleSheet("{padding:0 50; margin:0 100;}")
        self.majorLayout.addWidget(self.total)
        widget = QWidget()
        widget.setLayout(self.majorLayout)
        self.datos =[
            ['ABCZ-1234', 'Paño esponja', 130.50],
            ['XYZC-2345', 'Escoba', 140.30],
            ]
        self.datosAnexos = [
            ['ABCZ-1234', 'Paño esponja', 130.50],
            ['XYZC-2345', 'Escoba', 140.30],
            ['WXYZ-1234', 'Limpiador de pisos', 150.00],
            ['ABCD-1234', 'Bote de basura grande', 1000.00]
            ]
        self.model = TableModel(self.datos, ['SKU', 'Artículo', 'Precio'])
        self.table.setModel(self.model)
        self.table.setColumnWidth(1,315)
        self.setCentralWidget(widget)
        self.input.returnPressed.connect(self.add_datos)
        self.calculate_total()

    def help_content_triggered(self):
        self.ventanaHelp.display_help()

    def add_datos(self):
        texto = self.input.text()
        valor = self.method_in(self.datosAnexos, texto)
        if(valor is None):
            self.marco.setStyleSheet("QFrame{border: 1px solid red;}")
            self.input.setStyleSheet("border: 1px solid red;")
            self.inputCommands.setText('Ingrese un comando')
            self.inputCommands.show()
        else:
            self.marco.setStyleSheet("QFrame{border: 1px solid black;}")
            self.input.setStyleSheet("border: 1px solid black;")
            self.datos.append(valor)
            self.table.model().layoutChanged.emit()
            self.calculate_total()
            self.inputCommands.hide()

    def calculate_total(self):
        agregado = 0.0
        for dato in self.datos:
            agregado += dato[2]
        self.total.setText('Total: ' + '{:.2f}'.format(agregado))

    def method_in(self, data, text):
        for element in data:
            if element[0].casefold() == text.casefold():
                return element
        return None
        
    def focus_in_command(self):
        self.inputCommands.setText('')

    def command_agrega_producto(self):
        valor = self.elige_comando(1)
        print(valor)
        if(valor == self.inputCommands.text()):
            self.ventana.display_info()
        else:
            print('Comando incorrecto')

    def comando_agregar(self):
        return 'A'

    def elige_comando(self, argument):
        return {
            1: lambda: self.comando_agregar(),
        }.get(argument, lambda: 'Opción inválida')()