def __init__(self):
        super().__init__()

        self.setWindowTitle("My App")

        label = QLabel("Hello!")
        label.setAlignment(Qt.AlignCenter)

        self.setCentralWidget(label)

        toolbar = QToolBar("My main toolbar")
        toolbar.setIconSize(QSize(16, 16))
        self.addToolBar(toolbar)

        button_action = QAction(QIcon("bug.png"), "Your button", self)
        button_action.setStatusTip("This is your button")
        button_action.triggered.connect(self.onMyToolBarButtonClick)
        button_action.setCheckable(True)
        toolbar.addAction(button_action)

        toolbar.addSeparator()

        button_action2 = QAction(QIcon("bug.png"), "Your button2", self)
        button_action2.setStatusTip("This is your button2")
        button_action2.triggered.connect(self.onMyToolBarButtonClick)
        button_action2.setCheckable(True)
        toolbar.addAction(button_action2)

        toolbar.addWidget(QLabel("Hello"))
        toolbar.addWidget(QCheckBox())

        self.setStatusBar(QStatusBar(self))
Beispiel #2
0
    def __init__(self):
        super().__init__()

        self.setWindowTitle("My App")

        label = QLabel("Hello!")

        # The `Qt` namespace has a lot of attributes to customize
        # widgets. See: http://doc.qt.io/qt-5/qt.html
        label.setAlignment(Qt.AlignCenter)

        # Set the central widget of the Window. Widget will expand
        # to take up all the space in the window by default.
        self.setCentralWidget(label)

        toolbar = QToolBar("My main toolbar")
        toolbar.setIconSize(QSize(16, 16))
        self.addToolBar(toolbar)

        button_action = QAction(QIcon("bug.png"), "&Your button", self)
        button_action.setStatusTip("This is your button")
        button_action.triggered.connect(self.onMyToolBarButtonClick)
        button_action.setCheckable(True)
        # You can enter keyboard shortcuts using key names (e.g. Ctrl+p)
        # Qt.namespace identifiers (e.g. Qt.CTRL + Qt.Key_P)
        # or system agnostic identifiers (e.g. QKeySequence.Print)
        button_action.setShortcut(QKeySequence("Ctrl+p"))
        toolbar.addAction(button_action)

        toolbar.addSeparator()

        button_action2 = QAction(QIcon("bug.png"), "Your &button2", self)
        button_action2.setStatusTip("This is your button2")
        button_action2.triggered.connect(self.onMyToolBarButtonClick)
        button_action2.setCheckable(True)
        toolbar.addAction(button_action)

        toolbar.addWidget(QLabel("Hello"))
        toolbar.addWidget(QCheckBox())

        self.setStatusBar(QStatusBar(self))

        menu = self.menuBar()

        file_menu = menu.addMenu("&File")
        file_menu.addAction(button_action)

        file_menu.addSeparator()

        file_submenu = file_menu.addMenu("Submenu")

        file_submenu.addAction(button_action2)
def _add_tool_bar_items(
    tool_bar: QToolBar,
    items: List[Union[str, QAction]],
) -> None:
    for item in items:
        if item == _TOOL_BAR_SEPARATOR:
            tool_bar.addSeparator()
        elif item == _TOOL_BAR_SPACER:
            spacer = QWidget(tool_bar)
            spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            tool_bar.addWidget(spacer)
        elif isinstance(item, QAction):
            tool_bar.addAction(item)
Beispiel #4
0
    def createToolBar(self):  #Ok
        """
        Criar barra de ferramentas para editor de fotos
        """
        tool_bar = QToolBar("Barra de Ferramentas do Editor de Fotos")
        tool_bar.setIconSize(QSize(24, 24))
        self.addToolBar(tool_bar)

        tool_bar.addAction(self.abre_act)
        tool_bar.addAction(self.salv_act)
        tool_bar.addAction(self.prnt_act)
        tool_bar.addAction(self.limp_act)
        tool_bar.addSeparator()
        tool_bar.addAction(self.sair_act)
Beispiel #5
0
class MainWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setWindowTitle("AxiGUI")
        self._config_dialog = ConfigDialog()
        self._plot_control = PlotControlWidget()

        # setup toolbar
        self._toolbar = QToolBar()
        self._toolbar.setIconSize(QSize(64, 64))
        load_act = self._toolbar.addAction(QIcon("images/icons_open.png"),
                                           "Load")
        load_act.triggered.connect(lambda: self.load_svg())
        config_act = self._toolbar.addAction(
            QIcon("images/icons_settings.png"), "Config")
        config_act.triggered.connect(lambda: self._config_dialog.exec_())
        self._toolbar.addSeparator()
        self._plot_control.add_actions(self._toolbar)
        empty = QWidget()
        empty.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred))
        self._toolbar.addWidget(empty)
        quit_act = self._toolbar.addAction(QIcon("images/icons_exit.png"),
                                           "Quit")
        quit_act.triggered.connect(lambda: QCoreApplication.quit())

        # setup layout
        layout = QVBoxLayout()
        layout.setSpacing(0)
        layout.setMargin(0)
        layout.addWidget(self._toolbar)
        layout.addWidget(self._plot_control)
        self.setLayout(layout)

    def load_svg(self):
        # TODO: remember last folder opened in the session
        path = QFileDialog.getOpenFileName(self, "Choose SVG file:",
                                           "/Users/hhip/Drive/axidraw",
                                           "SVG (*.svg)")
        if path[0]:
            self._plot_control.load_svg(path[0])
Beispiel #6
0
    def qtoolbar(self):
        toolbar = QToolBar(self.name, self.window)

        for action in self.actions:
            if isinstance(action, ToolbarSplitter):
                toolbar.addSeparator()
            else:
                if action.icon is not None:
                    act = QAction(action.icon, action.name, toolbar)
                else:
                    act = QAction(action.name, toolbar)
                if action.triggered is not None:
                    act.triggered.connect(action.triggered)
                if action.tooltip:
                    act.setToolTip(action.tooltip)
                toolbar.addAction(act)

        toolbar.setIconSize(QSize(16, 16))

        return toolbar
Beispiel #7
0
class Ui_FE14ChapterEditor(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.toolbar = QToolBar()
        self.addToolBar(self.toolbar)
        self.add_chapter_action = QAction("Add Chapter")
        self.hide_selector_action = QAction("Toggle Selection Pane")
        self.toolbar.addAction(self.add_chapter_action)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.hide_selector_action)

        self.selector_layout = QVBoxLayout()
        self.chapter_search_bar = QLineEdit()
        self.chapter_search_bar.setPlaceholderText("Search...")
        self.chapter_list_view = QListView()
        self.selector_layout.addWidget(self.chapter_search_bar)
        self.selector_layout.addWidget(self.chapter_list_view)
        self.selector_widget = QWidget()
        self.selector_widget.setLayout(self.selector_layout)
        self.selector_widget.setFixedWidth(225)

        self.config_tab = FE14ChapterConfigTab()
        self.map_tab = FE14MapEditor()
        self.characters_tab = FE14CharacterEditor(is_person=True)
        self.conversation_tab = FE14ConversationEditor()
        self.tab_widget = QTabWidget()
        self.tab_widget.addTab(self.config_tab, "Config")
        self.tab_widget.addTab(self.map_tab, "Map")
        self.tab_widget.addTab(self.characters_tab, "Characters")
        self.tab_widget.addTab(self.conversation_tab, "Text")

        self.main_layout = QHBoxLayout()
        self.main_widget = QWidget()
        self.visual_splitter = QFrame()
        self.visual_splitter.setFrameShape(QFrame.VLine)
        self.visual_splitter.setFrameShadow(QFrame.Sunken)
        self.main_widget.setLayout(self.main_layout)
        self.main_layout.addWidget(self.selector_widget)
        self.main_layout.addWidget(self.visual_splitter)
        self.main_layout.addWidget(self.tab_widget)
        self.setCentralWidget(self.main_widget)
Beispiel #8
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_()
Beispiel #9
0
    def initUI(self):
        # ----------------
        #  Create toolbar
        toolbar = QToolBar()
        self.addToolBar(toolbar)

        # Add buttons to toolbar
        btn_before: QToolButton = QToolButton()
        btn_before.setIcon(QIcon(self.icons.LEFT))
        btn_before.setStyleSheet("QToolButton {margin: 0 5px;}")
        btn_before.setStatusTip('goto previous PARAMETER')
        btn_before.clicked.connect(self.prev_chart)
        toolbar.addWidget(btn_before)

        # Add buttons to toolbar
        btn_after: QToolButton = QToolButton()
        btn_after.setIcon(QIcon(self.icons.RIGHT))
        btn_after.setStyleSheet("QToolButton {margin: 0 5px;}")
        btn_after.setStatusTip('go to next PARAMETER')
        btn_after.clicked.connect(self.next_chart)
        toolbar.addWidget(btn_after)

        toolbar.addSeparator()

        self.check_update = QCheckBox('Hide Spec Limit(s)', self)
        self.check_update.setStyleSheet("QCheckBox {margin: 0 5px;}")
        self.checkbox_state()
        self.check_update.stateChanged.connect(self.update_status)
        toolbar.addWidget(self.check_update)

        # spacer to expand
        spacer: QWidget = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        toolbar.addWidget(spacer)

        # ComboBox to choose PowerPoint format
        self.ppt_format = bwidget.BComboBox(self)
        self.ppt_format.setText('PPT Format')
        self.ppt_format.addItems(['Default', 'Custom'])
        self.ppt_format.currentIndexChanged(self.selectionComboChange)
        toolbar.addWidget(self.ppt_format)

        toolbar.addSeparator()

        self.check_all_slides = QCheckBox('All parameters', self)
        toolbar.addWidget(self.check_all_slides)

        # PowerPoint
        but_ppt: QToolButton = QToolButton()
        but_ppt.setIcon(QIcon(self.icons.PPT))
        but_ppt.setStatusTip('generate PowerPoint slide(s)')
        but_ppt.clicked.connect(self.OnPPT)
        toolbar.addWidget(but_ppt)

        # ------------
        #  Status Bar
        self.statusbar = QStatusBar()
        self.setStatusBar(self.statusbar)

        self.create_chart()

        self.show()
Beispiel #10
0
    def __init__(self):
        super().__init__()

        self.browser = QWebEngineView()
        self.browser.setUrl(QUrl("http://google.com"))
        self.setCentralWidget(self.browser)

        # tag::navigationSignals[]
        self.browser.urlChanged.connect(self.update_urlbar)
        self.browser.loadFinished.connect(self.update_title)
        # end::navigationSignals[]

        # tag::navigation1[]
        navtb = QToolBar("Navigation")
        navtb.setIconSize(QSize(16, 16))
        self.addToolBar(navtb)

        back_btn = QAction(QIcon(os.path.join("icons", "arrow-180.png")),
                           "Back", self)
        back_btn.setStatusTip("Back to previous page")
        back_btn.triggered.connect(self.browser.back)
        navtb.addAction(back_btn)
        # end::navigation1[]

        # tag::navigation2[]
        next_btn = QAction(QIcon(os.path.join("icons", "arrow-000.png")),
                           "Forward", self)
        next_btn.setStatusTip("Forward to next page")
        next_btn.triggered.connect(self.browser.forward)
        navtb.addAction(next_btn)

        reload_btn = QAction(
            QIcon(os.path.join("icons", "arrow-circle-315.png")), "Reload",
            self)
        reload_btn.setStatusTip("Reload page")
        reload_btn.triggered.connect(self.browser.reload)
        navtb.addAction(reload_btn)

        home_btn = QAction(QIcon(os.path.join("icons", "home.png")), "Home",
                           self)
        home_btn.setStatusTip("Go home")
        home_btn.triggered.connect(self.navigate_home)
        navtb.addAction(home_btn)
        # end::navigation2[]

        navtb.addSeparator()

        # tag::navigation3[]
        self.httpsicon = QLabel()  # Yes, really!
        self.httpsicon.setPixmap(
            QPixmap(os.path.join("icons", "lock-nossl.png")))
        navtb.addWidget(self.httpsicon)

        self.urlbar = QLineEdit()
        self.urlbar.returnPressed.connect(self.navigate_to_url)
        navtb.addWidget(self.urlbar)

        stop_btn = QAction(QIcon(os.path.join("icons", "cross-circle.png")),
                           "Stop", self)
        stop_btn.setStatusTip("Stop loading current page")
        stop_btn.triggered.connect(self.browser.stop)
        navtb.addAction(stop_btn)
        # end::navigation3[]

        self.menuBar().setNativeMenuBar(False)
        self.statusBar()

        # tag::menuFile[]
        file_menu = self.menuBar().addMenu("&File")

        open_file_action = QAction(
            QIcon(os.path.join("icons", "disk--arrow.png")), "Open file...",
            self)
        open_file_action.setStatusTip("Open from file")
        open_file_action.triggered.connect(self.open_file)
        file_menu.addAction(open_file_action)

        save_file_action = QAction(
            QIcon(os.path.join("icons", "disk--pencil.png")),
            "Save Page As...", self)
        save_file_action.setStatusTip("Save current page to file")
        save_file_action.triggered.connect(self.save_file)
        file_menu.addAction(save_file_action)
        # end::menuFile[]

        # tag::menuPrint[]
        print_action = QAction(QIcon(os.path.join("icons", "printer.png")),
                               "Print...", self)
        print_action.setStatusTip("Print current page")
        print_action.triggered.connect(self.print_page)
        file_menu.addAction(print_action)

        # Create our system printer instance.
        self.printer = QPrinter()
        # end::menuPrint[]

        # tag::menuHelp[]
        help_menu = self.menuBar().addMenu("&Help")

        about_action = QAction(
            QIcon(os.path.join("icons", "question.png")),
            "About Mozzarella Ashbadger",
            self,
        )
        about_action.setStatusTip(
            "Find out more about Mozzarella Ashbadger")  # Hungry!
        about_action.triggered.connect(self.about)
        help_menu.addAction(about_action)

        navigate_mozzarella_action = QAction(
            QIcon(os.path.join("icons", "lifebuoy.png")),
            "Mozzarella Ashbadger Homepage",
            self,
        )
        navigate_mozzarella_action.setStatusTip(
            "Go to Mozzarella Ashbadger Homepage")
        navigate_mozzarella_action.triggered.connect(self.navigate_mozzarella)
        help_menu.addAction(navigate_mozzarella_action)
        # end::menuHelp[]

        self.show()

        self.setWindowIcon(QIcon(os.path.join("icons", "ma-icon-64.png")))
Beispiel #11
0
class USBFrame(QWidget):

    # --- Init methods ---

    def __init__(self, config):
        """
        USB control frame

        :param config: application configuration file
        """
        QWidget.__init__(self)

        self.setFixedSize(QSize(600, 200))

        self.config = config
        self.setWindowTitle("DigiQt - USB Control")

        self.sig_button_pressed = None  # signal configured by serialControler
        self.sig_firmware_update = None  #

        # Firmware update output
        self.out = ConsoleOutput()
        # Buttons
        self.to_dr_btn = ToDigiruleButton(config)
        self.to_dr_btn.to_digirule = lambda: self.sig_button_pressed.emit(0)

        self.from_dr_btn = FromDigiruleButton(config)
        self.from_dr_btn.from_digirule = lambda: self.sig_button_pressed.emit(1
                                                                              )

        # Firmware
        self.firmware_btn = FirmwareUpdate(config)
        self.firmware_btn.firmware_update = self.firmware_update
        # Port selection
        self.lab_port = QLabel("Port:")
        self.usb_combo = UsbPortCombo()
        self.refresh_btn = RefreshPortButton(config)
        self.refresh_btn.on_refresh = lambda: self.sig_button_pressed.emit(2)

        self._init_tool_bar()
        self._set_layout()
        self._set_stylesheet()

    def _init_tool_bar(self):
        """
        Creates the main toolbar with all its content
        """
        self.toolbar = QToolBar()
        self.toolbar.setFixedHeight(70)

        self.toolbar.addWidget(self.to_dr_btn)
        self.toolbar.addWidget(self.from_dr_btn)

        self.toolbar.addSeparator()
        self.toolbar.addWidget(self.firmware_btn)

        self.toolbar.addSeparator()
        self.toolbar.addWidget(self.lab_port)
        self.toolbar.addWidget(self.usb_combo)
        self.toolbar.addWidget(self.refresh_btn)

    def _set_layout(self):
        """
        Creates this Widget's Layout
        """
        box = QGridLayout()
        box.setContentsMargins(0, 0, 0, 0)

        box.addWidget(self.toolbar, 0, 0)
        box.addWidget(self.out, 1, 0)

        self.setLayout(box)

    def _set_stylesheet(self):
        self.toolbar.setStyleSheet(style.get_stylesheet("qtoolbar"))
        self.setStyleSheet(style.get_stylesheet("common"))
        self.lab_port.setStyleSheet(
            "background-color: transparent; color: #75BA6D; font-weight: bold;"
        )
        self.out.setStyleSheet("background-color: #505050; color: white;")

    def firmware_update(self):
        dlg = QFileDialog()
        dlg.setWindowTitle("Choose a digirule Firmware")
        dlg.setFileMode(QFileDialog.AnyFile)
        dlg.setNameFilter("HEX files (*.hex)")
        if dlg.exec_():
            file_path = dlg.selectedFiles()[0]
            # Call the controller method for update
            self.sig_firmware_update.emit(file_path)

    # --- Close handler ---

    def closeEvent(self, event):
        """
        Event called upon a red-cross click.
        """
        self.on_close()

    def on_close(self):
        """
        Reroute this method in the Main Frame in order to Updates the execution frame's open editor icon and tooltip
        """
        pass
Beispiel #12
0
class MainWindow(QMainWindow):
    def __init__(self, path_to_rom=""):
        super(MainWindow, self).__init__()

        self.setWindowIcon(icon("foundry.ico"))

        file_menu = QMenu("File")

        open_rom_action = file_menu.addAction("&Open ROM")
        open_rom_action.triggered.connect(self.on_open_rom)
        self.open_m3l_action = file_menu.addAction("&Open M3L")
        self.open_m3l_action.triggered.connect(self.on_open_m3l)

        file_menu.addSeparator()

        self.save_rom_action = file_menu.addAction("&Save ROM")
        self.save_rom_action.triggered.connect(self.on_save_rom)
        self.save_rom_as_action = file_menu.addAction("&Save ROM as ...")
        self.save_rom_as_action.triggered.connect(self.on_save_rom_as)
        """
        file_menu.AppendSeparator()
        """
        self.save_m3l_action = file_menu.addAction("&Save M3L")
        self.save_m3l_action.triggered.connect(self.on_save_m3l)
        """
        file_menu.Append(ID_SAVE_LEVEL_TO, "&Save Level to", "")
        file_menu.AppendSeparator()
        file_menu.Append(ID_APPLY_IPS_PATCH, "&Apply IPS Patch", "")
        file_menu.AppendSeparator()
        file_menu.Append(ID_ROM_PRESET, "&ROM Preset", "")
        """
        file_menu.addSeparator()
        settings_action = file_menu.addAction("&Settings")
        settings_action.triggered.connect(show_settings)
        file_menu.addSeparator()
        exit_action = file_menu.addAction("&Exit")
        exit_action.triggered.connect(lambda _: self.close())

        self.menuBar().addMenu(file_menu)
        """
        edit_menu = wx.Menu()

        edit_menu.Append(ID_EDIT_LEVEL, "&Edit Level", "")
        edit_menu.Append(ID_EDIT_OBJ_DEFS, "&Edit Object Definitions", "")
        edit_menu.Append(ID_EDIT_PALETTE, "&Edit Palette", "")
        edit_menu.Append(ID_EDIT_GRAPHICS, "&Edit Graphics", "")
        edit_menu.Append(ID_EDIT_MISC, "&Edit Miscellaneous", "")
        edit_menu.AppendSeparator()
        edit_menu.Append(ID_FREE_FORM_MODE, "&Free form Mode", "")
        edit_menu.Append(ID_LIMIT_SIZE, "&Limit Size", "")
        """

        self.level_menu = QMenu("Level")

        self.select_level_action = self.level_menu.addAction("&Select Level")
        self.select_level_action.triggered.connect(self.open_level_selector)

        self.reload_action = self.level_menu.addAction("&Reload Level")
        self.reload_action.triggered.connect(self.reload_level)
        self.level_menu.addSeparator()
        self.edit_header_action = self.level_menu.addAction("&Edit Header")
        self.edit_header_action.triggered.connect(self.on_header_editor)
        self.edit_autoscroll = self.level_menu.addAction("Edit Autoscrolling")
        self.edit_autoscroll.triggered.connect(self.on_edit_autoscroll)

        self.menuBar().addMenu(self.level_menu)

        self.object_menu = QMenu("Objects")

        view_blocks_action = self.object_menu.addAction("&View Blocks")
        view_blocks_action.triggered.connect(self.on_block_viewer)
        view_objects_action = self.object_menu.addAction("&View Objects")
        view_objects_action.triggered.connect(self.on_object_viewer)
        self.object_menu.addSeparator()
        view_palettes_action = self.object_menu.addAction(
            "View Object Palettes")
        view_palettes_action.triggered.connect(self.on_palette_viewer)

        self.menuBar().addMenu(self.object_menu)

        self.view_menu = QMenu("View")
        self.view_menu.triggered.connect(self.on_menu)

        action = self.view_menu.addAction("Mario")
        action.setProperty(ID_PROP, ID_MARIO)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_mario"])

        action = self.view_menu.addAction("&Jumps on objects")
        action.setProperty(ID_PROP, ID_JUMP_OBJECTS)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_jump_on_objects"])

        action = self.view_menu.addAction("Items in blocks")
        action.setProperty(ID_PROP, ID_ITEM_BLOCKS)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_items_in_blocks"])

        action = self.view_menu.addAction("Invisible items")
        action.setProperty(ID_PROP, ID_INVISIBLE_ITEMS)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_invisible_items"])

        action = self.view_menu.addAction("Autoscroll Path")
        action.setProperty(ID_PROP, ID_AUTOSCROLL)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_autoscroll"])

        self.view_menu.addSeparator()

        action = self.view_menu.addAction("Jump Zones")
        action.setProperty(ID_PROP, ID_JUMPS)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_jumps"])

        action = self.view_menu.addAction("&Grid lines")
        action.setProperty(ID_PROP, ID_GRID_LINES)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_grid"])

        action = self.view_menu.addAction("Resize Type")
        action.setProperty(ID_PROP, ID_RESIZE_TYPE)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_expansion"])

        self.view_menu.addSeparator()

        action = self.view_menu.addAction("&Block Transparency")
        action.setProperty(ID_PROP, ID_TRANSPARENCY)
        action.setCheckable(True)
        action.setChecked(SETTINGS["block_transparency"])

        self.view_menu.addSeparator()
        self.view_menu.addAction(
            "&Save Screenshot of Level").triggered.connect(self.on_screenshot)
        """
        self.view_menu.Append(ID_BACKGROUND_FLOOR, "&Background & Floor", "")
        self.view_menu.Append(ID_TOOLBAR, "&Toolbar", "")
        self.view_menu.AppendSeparator()
        self.view_menu.Append(ID_ZOOM, "&Zoom", "")
        self.view_menu.AppendSeparator()
        self.view_menu.Append(ID_USE_ROM_GRAPHICS, "&Use ROM Graphics", "")
        self.view_menu.Append(ID_PALETTE, "&Palette", "")
        self.view_menu.AppendSeparator()
        self.view_menu.Append(ID_MORE, "&More", "")
        """

        self.menuBar().addMenu(self.view_menu)

        help_menu = QMenu("Help")
        """
        help_menu.Append(ID_ENEMY_COMPATIBILITY, "&Enemy Compatibility", "")
        help_menu.Append(ID_TROUBLESHOOTING, "&Troubleshooting", "")
        help_menu.AppendSeparator()
        help_menu.Append(ID_PROGRAM_WEBSITE, "&Program Website", "")
        help_menu.Append(ID_MAKE_A_DONATION, "&Make a Donation", "")
        help_menu.AppendSeparator()
        """
        update_action = help_menu.addAction("Check for updates")
        update_action.triggered.connect(self.on_check_for_update)

        help_menu.addSeparator()

        video_action = help_menu.addAction("Feature Video on YouTube")
        video_action.triggered.connect(lambda: open_url(feature_video_link))

        github_action = help_menu.addAction("Github Repository")
        github_action.triggered.connect(lambda: open_url(github_link))

        discord_action = help_menu.addAction("SMB3 Rom Hacking Discord")
        discord_action.triggered.connect(lambda: open_url(discord_link))

        help_menu.addSeparator()

        about_action = help_menu.addAction("&About")
        about_action.triggered.connect(self.on_about)

        self.menuBar().addMenu(help_menu)

        self.block_viewer = None
        self.object_viewer = None

        self.level_ref = LevelRef()
        self.level_ref.data_changed.connect(self._on_level_data_changed)

        self.context_menu = ContextMenu(self.level_ref)
        self.context_menu.triggered.connect(self.on_menu)

        self.level_view = LevelView(self, self.level_ref, self.context_menu)

        self.scroll_panel = QScrollArea()
        self.scroll_panel.setWidgetResizable(True)
        self.scroll_panel.setWidget(self.level_view)

        self.setCentralWidget(self.scroll_panel)

        self.spinner_panel = SpinnerPanel(self, self.level_ref)
        self.spinner_panel.zoom_in_triggered.connect(self.level_view.zoom_in)
        self.spinner_panel.zoom_out_triggered.connect(self.level_view.zoom_out)
        self.spinner_panel.object_change.connect(self.on_spin)

        self.object_list = ObjectList(self, self.level_ref, self.context_menu)

        self.object_dropdown = ObjectDropdown(self)
        self.object_dropdown.object_selected.connect(
            self._on_placeable_object_selected)

        self.level_size_bar = LevelSizeBar(self, self.level_ref)
        self.enemy_size_bar = EnemySizeBar(self, self.level_ref)

        self.jump_list = JumpList(self, self.level_ref)
        self.jump_list.add_jump.connect(self.on_jump_added)
        self.jump_list.edit_jump.connect(self.on_jump_edit)
        self.jump_list.remove_jump.connect(self.on_jump_removed)

        splitter = QSplitter(self)
        splitter.setOrientation(Qt.Vertical)

        splitter.addWidget(self.object_list)
        splitter.setStretchFactor(0, 1)
        splitter.addWidget(self.jump_list)

        splitter.setChildrenCollapsible(False)

        level_toolbar = QToolBar("Level Info Toolbar", self)
        level_toolbar.setContextMenuPolicy(Qt.PreventContextMenu)
        level_toolbar.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        level_toolbar.setOrientation(Qt.Horizontal)
        level_toolbar.setFloatable(False)

        level_toolbar.addWidget(self.spinner_panel)
        level_toolbar.addWidget(self.object_dropdown)
        level_toolbar.addWidget(self.level_size_bar)
        level_toolbar.addWidget(self.enemy_size_bar)
        level_toolbar.addWidget(splitter)

        level_toolbar.setAllowedAreas(Qt.LeftToolBarArea | Qt.RightToolBarArea)

        self.addToolBar(Qt.RightToolBarArea, level_toolbar)

        self.object_toolbar = ObjectToolBar(self)
        self.object_toolbar.object_selected.connect(
            self._on_placeable_object_selected)

        object_toolbar = QToolBar("Object Toolbar", self)
        object_toolbar.setContextMenuPolicy(Qt.PreventContextMenu)
        object_toolbar.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        object_toolbar.setFloatable(False)

        object_toolbar.addWidget(self.object_toolbar)
        object_toolbar.setAllowedAreas(Qt.LeftToolBarArea
                                       | Qt.RightToolBarArea)

        self.addToolBar(Qt.LeftToolBarArea, object_toolbar)

        self.menu_toolbar = QToolBar("Menu Toolbar", self)
        self.menu_toolbar.setOrientation(Qt.Horizontal)
        self.menu_toolbar.setIconSize(QSize(20, 20))

        self.menu_toolbar.addAction(
            icon("settings.svg"),
            "Editor Settings").triggered.connect(show_settings)
        self.menu_toolbar.addSeparator()
        self.menu_toolbar.addAction(
            icon("folder.svg"), "Open ROM").triggered.connect(self.on_open_rom)
        self.menu_toolbar.addAction(
            icon("save.svg"), "Save Level").triggered.connect(self.on_save_rom)
        self.menu_toolbar.addSeparator()

        self.undo_action = self.menu_toolbar.addAction(icon("rotate-ccw.svg"),
                                                       "Undo Action")
        self.undo_action.triggered.connect(self.level_ref.undo)
        self.undo_action.setEnabled(False)
        self.redo_action = self.menu_toolbar.addAction(icon("rotate-cw.svg"),
                                                       "Redo Action")
        self.redo_action.triggered.connect(self.level_ref.redo)
        self.redo_action.setEnabled(False)

        self.menu_toolbar.addSeparator()
        play_action = self.menu_toolbar.addAction(icon("play-circle.svg"),
                                                  "Play Level")
        play_action.triggered.connect(self.on_play)
        play_action.setWhatsThis(
            "Opens an emulator with the current Level set to 1-1.\nSee Settings."
        )
        self.menu_toolbar.addSeparator()
        self.menu_toolbar.addAction(icon("zoom-out.svg"),
                                    "Zoom Out").triggered.connect(
                                        self.level_view.zoom_out)
        self.menu_toolbar.addAction(icon("zoom-in.svg"),
                                    "Zoom In").triggered.connect(
                                        self.level_view.zoom_in)
        self.menu_toolbar.addSeparator()
        header_action = self.menu_toolbar.addAction(icon("tool.svg"),
                                                    "Edit Level Header")
        header_action.triggered.connect(self.on_header_editor)
        header_action.setWhatsThis(
            "<b>Header Editor</b><br/>"
            "Many configurations regarding the level are done in its header, like the length of "
            "the timer, or where and how Mario enters the level.<br/>")

        self.jump_destination_action = self.menu_toolbar.addAction(
            icon("arrow-right-circle.svg"), "Go to Jump Destination")
        self.jump_destination_action.triggered.connect(
            self._go_to_jump_destination)
        self.jump_destination_action.setWhatsThis(
            "Opens the level, that can be reached from this one, e.g. by entering a pipe."
        )

        self.menu_toolbar.addSeparator()

        whats_this_action = QWhatsThis.createAction()
        whats_this_action.setWhatsThis(
            "Click on parts of the editor, to receive help information.")
        whats_this_action.setIcon(icon("help-circle.svg"))
        whats_this_action.setText("Starts 'What's this?' mode")
        self.menu_toolbar.addAction(whats_this_action)

        self.menu_toolbar.addSeparator()
        self.warning_list = WarningList(self, self.level_ref)

        warning_action = self.menu_toolbar.addAction(
            icon("alert-triangle.svg"), "Warning Panel")
        warning_action.setWhatsThis("Shows a list of warnings.")
        warning_action.triggered.connect(self.warning_list.show)
        warning_action.setDisabled(True)

        self.warning_list.warnings_updated.connect(warning_action.setEnabled)

        self.addToolBar(Qt.TopToolBarArea, self.menu_toolbar)

        self.status_bar = ObjectStatusBar(self, self.level_ref)
        self.setStatusBar(self.status_bar)

        self.delete_shortcut = QShortcut(QKeySequence(Qt.Key_Delete), self,
                                         self.remove_selected_objects)

        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_X), self, self._cut_objects)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_C), self, self._copy_objects)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_V), self, self._paste_objects)

        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Z), self, self.level_ref.undo)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Y), self, self.level_ref.redo)
        QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Z), self,
                  self.level_ref.redo)

        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Plus), self,
                  self.level_view.zoom_in)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Minus), self,
                  self.level_view.zoom_out)

        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_A), self,
                  self.level_view.select_all)

        self.on_open_rom(path_to_rom)

        self.showMaximized()

    def _on_level_data_changed(self):
        self.undo_action.setEnabled(self.level_ref.undo_stack.undo_available)
        self.redo_action.setEnabled(self.level_ref.undo_stack.redo_available)

        self.jump_destination_action.setEnabled(
            self.level_ref.level.has_next_area)

    def _go_to_jump_destination(self):
        if not self.safe_to_change():
            return

        level_address = self.level_ref.level.next_area_objects
        enemy_address = self.level_ref.level.next_area_enemies + 1
        object_set = self.level_ref.level.next_area_object_set

        world, level = world_and_level_for_level_address(level_address)

        self.update_level(f"Level {world}-{level}", level_address,
                          enemy_address, object_set)

    def on_play(self):
        """
        Copies the ROM, including the current level, to a temporary directory, saves the current level as level 1-1 and
        opens the rom in an emulator.
        """
        temp_dir = pathlib.Path(tempfile.gettempdir()) / "smb3foundry"
        temp_dir.mkdir(parents=True, exist_ok=True)

        path_to_temp_rom = temp_dir / "instaplay.rom"

        ROM().save_to(path_to_temp_rom)

        if not self._put_current_level_to_level_1_1(path_to_temp_rom):
            return

        if not self._set_default_powerup(path_to_temp_rom):
            return

        arguments = SETTINGS["instaplay_arguments"].replace(
            "%f", str(path_to_temp_rom))
        arguments = shlex.split(arguments, posix=False)

        emu_path = pathlib.Path(SETTINGS["instaplay_emulator"])

        if emu_path.is_absolute():
            if emu_path.exists():
                emulator = str(emu_path)
            else:
                QMessageBox.critical(
                    self, "Emulator not found",
                    f"Check it under File > Settings.\nFile {emu_path} not found."
                )
                return
        else:
            emulator = SETTINGS["instaplay_emulator"]

        try:
            subprocess.run([emulator, *arguments])
        except Exception as e:
            QMessageBox.critical(self, "Emulator command failed.",
                                 f"Check it under File > Settings.\n{str(e)}")

    def _open_rom(self, path_to_rom):
        with open(path_to_rom, "rb") as smb3_rom:
            data = smb3_rom.read()

        rom = SMB3Rom(bytearray(data))
        return rom

    def _put_current_level_to_level_1_1(self, path_to_rom) -> bool:
        rom = self._open_rom(path_to_rom)

        # load world-1 data
        world_1 = SMB3World.from_world_number(rom, 1)

        # find position of "level 1" tile in world map
        for position in world_1.gen_positions():
            if position.tile() == TILE_LEVEL_1:
                break
        else:
            QMessageBox.critical(
                self, "Couldn't place level",
                "Could not find a level 1 tile in World 1 to put your level at."
            )
            return False

        if not self.level_ref.level.attached_to_rom:
            QMessageBox.critical(
                self,
                "Couldn't place level",
                "The Level is not part of the rom yet (M3L?). Try saving it into the ROM first.",
            )
            return False

        # write level and enemy data of current level
        (layout_address,
         layout_bytes), (enemy_address,
                         enemy_bytes) = self.level_ref.level.to_bytes()
        rom.write(layout_address, layout_bytes)
        rom.write(enemy_address, enemy_bytes)

        # replace level information with that of current level
        object_set_number = self.level_ref.object_set_number

        world_1.replace_level_at_position(
            (layout_address, enemy_address - 1, object_set_number), position)

        # save rom
        rom.save_to(path_to_rom)

        return True

    def _set_default_powerup(self, path_to_rom) -> bool:
        rom = self._open_rom(path_to_rom)

        *_, powerup, hasPWing = POWERUPS[SETTINGS["default_powerup"]]

        rom.write(Title_PrepForWorldMap + 0x1, bytes([powerup]))

        nop = 0xEA
        rts = 0x60
        lda = 0xA9
        staAbsolute = 0x8D

        # If a P-wing powerup is selected, another variable needs to be set with the P-wing value
        # This piece of code overwrites a part of Title_DebugMenu
        if hasPWing:
            Map_Power_DispHigh = 0x03
            Map_Power_DispLow = 0xF3

            # We need to start one byte before Title_DebugMenu to remove the RTS of Title_PrepForWorldMap
            # The assembly code below reads as follows:
            # LDA 0x08
            # STA $03F3
            # RTS
            rom.write(
                Title_DebugMenu - 0x1,
                bytes([
                    lda,
                    0x8,
                    staAbsolute,
                    Map_Power_DispLow,
                    Map_Power_DispHigh,
                    # The RTS to get out of the now extended Title_PrepForWorldMap
                    rts,
                ]),
            )

            # Remove code that resets the powerup value by replacing it with no-operations
            # Otherwise this code would copy the value of the normal powerup here
            # (So if the powerup would be Raccoon Mario, Map_Power_Disp would also be
            # set as Raccoon Mario instead of P-wing
            Map_Power_DispResetLocation = 0x3C5A2
            rom.write(Map_Power_DispResetLocation, bytes([nop, nop, nop]))

        rom.save_to(path_to_rom)
        return True

    def on_screenshot(self, _) -> bool:
        if self.level_view is None:
            return False

        recommended_file = f"{os.path.expanduser('~')}/{ROM.name} - {self.level_view.level_ref.name}.png"

        pathname, _ = QFileDialog.getSaveFileName(self,
                                                  caption="Save Screenshot",
                                                  dir=recommended_file,
                                                  filter=IMG_FILE_FILTER)

        if not pathname:
            return False

        # Proceed loading the file chosen by the user
        self.level_view.make_screenshot().save(pathname)

        return True

    def update_title(self):
        if self.level_view.level_ref is not None and ROM is not None:
            title = f"{self.level_view.level_ref.name} - {ROM.name}"
        else:
            title = "SMB3Foundry"

        self.setWindowTitle(title)

    def on_open_rom(self, path_to_rom="") -> bool:
        if not self.safe_to_change():
            return False

        if not path_to_rom:
            # otherwise ask the user what new file to open
            path_to_rom, _ = QFileDialog.getOpenFileName(
                self, caption="Open ROM", filter=ROM_FILE_FILTER)

            if not path_to_rom:
                self._enable_disable_gui_elements()
                return False

        # Proceed loading the file chosen by the user
        try:
            ROM.load_from_file(path_to_rom)

            return self.open_level_selector(None)

        except IOError as exp:
            QMessageBox.warning(self,
                                type(exp).__name__,
                                f"Cannot open file '{path_to_rom}'.")
            return False
        finally:
            self._enable_disable_gui_elements()

    def on_open_m3l(self, _) -> bool:
        if not self.safe_to_change():
            return False

        # otherwise ask the user what new file to open
        pathname, _ = QFileDialog.getOpenFileName(self,
                                                  caption="Open M3L file",
                                                  filter=M3L_FILE_FILTER)

        if not pathname:
            return False

        # Proceed loading the file chosen by the user
        try:
            with open(pathname, "rb") as m3l_file:

                self.level_view.from_m3l(bytearray(m3l_file.read()))
        except IOError as exp:
            QMessageBox.warning(self,
                                type(exp).__name__,
                                f"Cannot open file '{pathname}'.")

            return False

        self.level_view.level_ref.name = os.path.basename(pathname)

        self.update_gui_for_level()

        return True

    def safe_to_change(self) -> bool:
        if not self.level_ref:
            return True

        if self.level_ref.level.changed:
            answer = QMessageBox.question(
                self,
                "Please confirm",
                "Current content has not been saved! Proceed?",
                QMessageBox.No | QMessageBox.Yes,
                QMessageBox.No,
            )

            return answer == QMessageBox.Yes
        else:
            return True

    def on_save_rom(self, _):
        self.save_rom(False)

    def on_save_rom_as(self, _):
        self.save_rom(True)

    def save_rom(self, is_save_as):
        safe_to_save, reason, additional_info = self.level_view.level_safe_to_save(
        )

        if not safe_to_save:
            answer = QMessageBox.warning(
                self,
                reason,
                f"{additional_info}\n\nDo you want to proceed?",
                QMessageBox.No | QMessageBox.Yes,
                QMessageBox.No,
            )

            if answer == QMessageBox.No:
                return

        if not self.level_ref.attached_to_rom:
            QMessageBox.information(
                self,
                "Importing M3L into ROM",
                "Please select the positions in the ROM you want the level objects and enemies/items to be stored.",
                QMessageBox.Ok,
            )

            level_selector = LevelSelector(self)

            answer = level_selector.exec_()

            if answer == QMessageBox.Accepted:
                self.level_view.level_ref.attach_to_rom(
                    level_selector.object_data_offset,
                    level_selector.enemy_data_offset)

                if is_save_as:
                    # if we save to another rom, don't consider the level
                    # attached (to the current rom)
                    self.level_view.level_ref.attached_to_rom = False
            else:
                return

        if is_save_as:
            pathname, _ = QFileDialog.getSaveFileName(self,
                                                      caption="Save ROM as",
                                                      filter=ROM_FILE_FILTER)
            if not pathname:
                return  # the user changed their mind
        else:
            pathname = ROM.path

        level = self.level_ref.level

        for offset, data in level.to_bytes():
            ROM().bulk_write(data, offset)

        try:
            ROM().save_to_file(pathname)
        except IOError as exp:
            QMessageBox.warning(self, f"{type(exp).__name__}",
                                f"Cannot save ROM data to file '{pathname}'.")

        self.update_title()

        if not is_save_as:
            level.changed = False

    def on_save_m3l(self, _):
        suggested_file = self.level_view.level_ref.name

        if not suggested_file.endswith(".m3l"):
            suggested_file += ".m3l"

        pathname, _ = QFileDialog.getSaveFileName(self,
                                                  caption="Save M3L as",
                                                  filter=M3L_FILE_FILTER)

        if not pathname:
            return

        level = self.level_view.level_ref

        try:
            with open(pathname, "wb") as m3l_file:
                m3l_file.write(level.to_m3l())
        except IOError as exp:
            QMessageBox.warning(self,
                                type(exp).__name__,
                                f"Couldn't save level to '{pathname}'.")

    def on_check_for_update(self):
        self.setCursor(Qt.WaitCursor)

        current_version = get_current_version_name()

        try:
            latest_version = get_latest_version_name()
        except ValueError as ve:
            QMessageBox.critical(self, "Error while checking for updates",
                                 f"Error: {ve}")
            return

        if current_version != latest_version:
            latest_release_url = f"{releases_link}/tag/{latest_version}"

            go_to_github_button = QPushButton(icon("external-link.svg"),
                                              "Go to latest release")
            go_to_github_button.clicked.connect(
                lambda: open_url(latest_release_url))

            info_box = QMessageBox(
                QMessageBox.Information, "New release available",
                f"New Version {latest_version} is available.")

            info_box.addButton(QMessageBox.Cancel)
            info_box.addButton(go_to_github_button, QMessageBox.AcceptRole)

            info_box.exec_()
        else:
            QMessageBox.information(
                self, "No newer release",
                f"Version {current_version} is up to date.")

        self.setCursor(Qt.ArrowCursor)

    def on_menu(self, action: QAction):
        item_id = action.property(ID_PROP)

        if item_id in CHECKABLE_MENU_ITEMS:
            self.on_menu_item_checked(action)
            self.level_view.update()

            # if setting a checkbox, keep the menu open
            menu_of_action: QMenu = self.sender()
            menu_of_action.exec_()

        elif item_id in self.context_menu.get_all_menu_item_ids():
            x, y = self.context_menu.get_position()

            if item_id == CMAction.REMOVE:
                self.remove_selected_objects()
            elif item_id == CMAction.ADD_OBJECT:
                selected_object = self.object_dropdown.currentIndex()

                if selected_object != -1:
                    self.place_object_from_dropdown((x, y))
                else:
                    self.create_object_at(x, y)

            elif item_id == CMAction.CUT:
                self._cut_objects()
            elif item_id == CMAction.COPY:
                self._copy_objects()
            elif item_id == CMAction.PASTE:
                self._paste_objects(x, y)
            elif item_id == CMAction.FOREGROUND:
                self.bring_objects_to_foreground()
            elif item_id == CMAction.BACKGROUND:
                self.bring_objects_to_background()

        self.level_view.update()

    def reload_level(self):
        if not self.safe_to_change():
            return

        level_name = self.level_view.level_ref.name
        object_data = self.level_view.level_ref.header_offset
        enemy_data = self.level_view.level_ref.enemy_offset
        object_set = self.level_view.level_ref.object_set_number

        self.update_level(level_name, object_data, enemy_data, object_set)

    def _on_placeable_object_selected(self, level_object: Union[LevelObject,
                                                                EnemyObject]):
        if self.sender() is self.object_toolbar:
            self.object_dropdown.select_object(level_object)
        else:
            self.object_toolbar.select_object(level_object)

    @undoable
    def bring_objects_to_foreground(self):
        self.level_ref.level.bring_to_foreground(
            self.level_ref.selected_objects)

    @undoable
    def bring_objects_to_background(self):
        self.level_ref.level.bring_to_background(
            self.level_ref.selected_objects)

    @undoable
    def create_object_at(self, x, y):
        self.level_view.create_object_at(x, y)

    @undoable
    def create_enemy_at(self, x, y):
        self.level_view.create_enemy_at(x, y)

    def _cut_objects(self):
        self._copy_objects()
        self.remove_selected_objects()

    def _copy_objects(self):
        selected_objects = self.level_view.get_selected_objects().copy()

        if selected_objects:
            self.context_menu.set_copied_objects(selected_objects)

    @undoable
    def _paste_objects(self, x=None, y=None):
        self.level_view.paste_objects_at(
            self.context_menu.get_copied_objects(), x, y)

    @undoable
    def remove_selected_objects(self):
        self.level_view.remove_selected_objects()
        self.level_view.update()
        self.spinner_panel.disable_all()

    def on_menu_item_checked(self, action: QAction):
        item_id = action.property(ID_PROP)

        checked = action.isChecked()

        if item_id == ID_GRID_LINES:
            self.level_view.draw_grid = checked
        elif item_id == ID_TRANSPARENCY:
            self.level_view.transparency = checked
        elif item_id == ID_JUMPS:
            self.level_view.draw_jumps = checked
        elif item_id == ID_MARIO:
            self.level_view.draw_mario = checked
        elif item_id == ID_RESIZE_TYPE:
            self.level_view.draw_expansions = checked
        elif item_id == ID_JUMP_OBJECTS:
            self.level_view.draw_jumps_on_objects = checked
        elif item_id == ID_ITEM_BLOCKS:
            self.level_view.draw_items_in_blocks = checked
        elif item_id == ID_INVISIBLE_ITEMS:
            self.level_view.draw_invisible_items = checked
        elif item_id == ID_AUTOSCROLL:
            self.level_view.draw_autoscroll = checked

        SETTINGS["draw_mario"] = self.level_view.draw_mario
        SETTINGS["draw_jumps"] = self.level_view.draw_jumps
        SETTINGS["draw_grid"] = self.level_view.draw_grid
        SETTINGS["draw_expansion"] = self.level_view.draw_expansions
        SETTINGS[
            "draw_jump_on_objects"] = self.level_view.draw_jumps_on_objects
        SETTINGS["draw_items_in_blocks"] = self.level_view.draw_items_in_blocks
        SETTINGS["draw_invisible_items"] = self.level_view.draw_invisible_items
        SETTINGS["draw_autoscroll"] = self.level_view.draw_autoscroll
        SETTINGS["block_transparency"] = self.level_view.transparency

        save_settings()

    @undoable
    def on_spin(self, _):
        selected_objects = self.level_ref.selected_objects

        if len(selected_objects) != 1:
            logging.error(selected_objects, RuntimeWarning)
            return

        selected_object = selected_objects[0]

        obj_type = self.spinner_panel.get_type()

        if isinstance(selected_object, LevelObject):
            domain = self.spinner_panel.get_domain()

            if selected_object.is_4byte:
                length = self.spinner_panel.get_length()
            else:
                length = None

            self.level_view.replace_object(selected_object, domain, obj_type,
                                           length)
        else:
            self.level_view.replace_enemy(selected_object, obj_type)

        self.level_ref.data_changed.emit()

    def fill_object_list(self):
        self.object_list.Clear()

        self.object_list.SetItems(self.level_view.get_object_names())

    def open_level_selector(self, _):
        if not self.safe_to_change():
            return

        level_selector = LevelSelector(self)

        level_was_selected = level_selector.exec_() == QDialog.Accepted

        if level_was_selected:
            self.update_level(
                level_selector.level_name,
                level_selector.object_data_offset,
                level_selector.enemy_data_offset,
                level_selector.object_set,
            )

        return level_was_selected

    def on_block_viewer(self, _):
        if self.block_viewer is None:
            self.block_viewer = BlockViewer(parent=self)

        if self.level_ref.level is not None:
            self.block_viewer.object_set = self.level_ref.object_set.number
            self.block_viewer.palette_group = self.level_ref.object_palette_index

        self.block_viewer.show()

    def on_object_viewer(self, _):
        if self.object_viewer is None:
            self.object_viewer = ObjectViewer(parent=self)

        if self.level_ref.level is not None:
            object_set = self.level_ref.object_set.number
            graphics_set = self.level_ref.graphic_set

            self.object_viewer.set_object_and_graphic_set(
                object_set, graphics_set)

            if len(self.level_view.get_selected_objects()) == 1:
                selected_object = self.level_view.get_selected_objects()[0]

                if isinstance(selected_object, LevelObject):
                    self.object_viewer.set_object(selected_object.domain,
                                                  selected_object.obj_index,
                                                  selected_object.length)

        self.object_viewer.show()

    def on_palette_viewer(self, _):
        PaletteViewer(self, self.level_ref).exec_()

    def on_edit_autoscroll(self, _):
        AutoScrollEditor(self, self.level_ref).exec_()

    def on_header_editor(self, _):
        HeaderEditor(self, self.level_ref).exec_()

    def update_level(self, level_name: str, object_data_offset: int,
                     enemy_data_offset: int, object_set: int):
        try:
            self.level_ref.load_level(level_name, object_data_offset,
                                      enemy_data_offset, object_set)
        except IndexError:
            QMessageBox.critical(
                self, "Please confirm",
                "Failed loading level. The level offsets don't match.")

            return

        self.update_gui_for_level()

    def update_gui_for_level(self):
        self._enable_disable_gui_elements()

        self.update_title()
        self.jump_list.update()

        is_a_world_map = isinstance(self.level_ref.level, WorldMap)

        self.save_m3l_action.setEnabled(not is_a_world_map)
        self.edit_header_action.setEnabled(not is_a_world_map)

        if is_a_world_map:
            self.object_dropdown.Clear()
            self.object_dropdown.setEnabled(False)

            self.jump_list.setEnabled(False)
            self.jump_list.Clear()
        else:
            self.object_dropdown.setEnabled(True)
            self.object_dropdown.set_object_set(
                self.level_ref.object_set_number, self.level_ref.graphic_set)

            self.jump_list.setEnabled(True)

        self.object_toolbar.set_object_set(self.level_ref.object_set_number,
                                           self.level_ref.graphic_set)

        self.level_view.update()

    def _enable_disable_gui_elements(self):
        rom_elements = [
            # entries in file menu
            self.open_m3l_action,
            self.save_rom_action,
            self.save_rom_as_action,
            # entry in level menu
            self.select_level_action,
        ]

        level_elements = [
            # entry in file menu
            self.save_m3l_action,
            # top toolbar
            self.menu_toolbar,
            # other gui elements
            self.level_view,
            self.spinner_panel,
            self.object_toolbar,
            self.level_size_bar,
            self.enemy_size_bar,
            self.object_list,
            self.jump_list,
            self.object_toolbar,
        ]

        level_elements.extend(self.level_menu.actions())
        level_elements.remove(self.select_level_action)

        level_elements.extend(self.object_menu.actions())
        level_elements.extend(self.view_menu.actions())

        for gui_element in rom_elements:
            gui_element.setEnabled(ROM.is_loaded())

        for gui_element in level_elements:
            gui_element.setEnabled(ROM.is_loaded()
                                   and self.level_ref.level is not None)

    def on_jump_edit(self):
        index = self.jump_list.currentIndex().row()

        updated_jump = JumpEditor.edit_jump(
            self, self.level_view.level_ref.jumps[index])

        self.on_jump_edited(updated_jump)

    @undoable
    def on_jump_added(self):
        self.level_view.add_jump()

    @undoable
    def on_jump_removed(self):
        self.level_view.remove_jump(self.jump_list.currentIndex().row())

    @undoable
    def on_jump_edited(self, jump):
        index = self.jump_list.currentIndex().row()

        assert index >= 0

        if isinstance(self.level_ref.level, Level):
            self.level_view.level_ref.jumps[index] = jump
            self.jump_list.item(index).setText(str(jump))

    def on_jump_list_change(self, event):
        self.jump_list.set_jumps(event)

    def mouseReleaseEvent(self, event: QMouseEvent):
        if event.button() == Qt.MiddleButton:
            pos = self.level_view.mapFromGlobal(self.mapToGlobal(
                event.pos())).toTuple()

            self.place_object_from_dropdown(pos)

    @undoable
    def place_object_from_dropdown(self, pos: Tuple[int, int]) -> None:
        # the dropdown is synchronized with the toolbar, so it doesn't matter where to take it from
        level_object = self.object_dropdown.currentData(Qt.UserRole)

        self.object_toolbar.add_recent_object(level_object)

        if isinstance(level_object, LevelObject):
            self.level_view.create_object_at(*pos, level_object.domain,
                                             level_object.obj_index)
        elif isinstance(level_object, EnemyObject):
            self.level_view.add_enemy(level_object.obj_index, *pos, -1)

    def on_about(self, _):
        about = AboutDialog(self)

        about.show()

    def closeEvent(self, event: QCloseEvent):
        if not self.safe_to_change():
            event.ignore()

            return

        super(MainWindow, self).closeEvent(event)
Beispiel #13
0
class ExecutionFrame(QWidget):

    # --- Init methods ---

    def __init__(self, config, sig_update_config):
        """
        Main application frame. Contains the MenuBar, main toolbar, DR canvas and status bar.

        :param config: application configuration file
        """
        QWidget.__init__(self)

        self.config = config
        self.is_quitting = False

        app_version = self.config.get('main', 'APP_VERSION')
        self.setWindowTitle("DigiQt - Emulator for Digirule - " +
                            str(app_version))
        window_width = int(self.config.get('main', 'WINDOW_WIDTH'))
        self.setFixedSize(window_width, 320)

        self.current_digirule_model = self.config.get('digirule', 'DR_MODEL')

        sliderbar_width = 200
        bottom_widget_height = 26

        self.statusbar = StatusBar(window_width - sliderbar_width,
                                   bottom_widget_height, config)
        self.dr_canvas = DRCanvas(self.statusbar.sig_temp_message,
                                  window_width, self.current_digirule_model,
                                  config)
        self.slider = SpeedSlider(sliderbar_width, bottom_widget_height,
                                  config)

        # Buttons open/hide frames
        self.editor_frame = EditorFrame(config,
                                        self.statusbar.sig_temp_message)
        self.open_editor_btn = OpenEditorButton(self.editor_frame, config)
        self.editor_frame.on_close = lambda: self.open_editor_btn.show_editor_frame(
            False)

        self.ram_frame = RAMFrame(config)
        self.open_ram_btn = OpenRamButton(self.ram_frame, config)
        self.ram_frame.on_close = lambda: self.open_ram_btn.show_ram_frame(
            False)

        self.monitor_frame = TerminalFrame(config)
        self.open_monitor_btn = OpenTerminalButton(self.monitor_frame, config)
        self.monitor_frame.on_close = lambda: self.open_monitor_btn.show_terminal_frame(
            False)

        self.usb_frame = USBFrame(config)
        self.open_usb_btn = OpenUSBButton(self.usb_frame, config)
        self.usb_frame.on_close = lambda: self.open_usb_btn.show_usb_frame(
            False)

        self.open_monitor_btn.is_opened = lambda b: self.open_usb_btn.setEnabled(
            not b)
        self.open_usb_btn.is_opened = lambda b: self.open_monitor_btn.setEnabled(
            not b)

        self.symbol_frame = SymbolViewFrame(config)
        self.open_symbol_btn = OpenSymbolButton(self.symbol_frame, config)
        self.symbol_frame.on_close = lambda: self.open_symbol_btn.show_symbol_frame(
            False)
        self.symbol_frame.place_search_text = self.editor_frame.do_search

        self.about_frame = AboutFrame(self.config)
        self.open_about_btn = AboutButton(self.about_frame, config)
        self.about_frame.on_close = lambda: self.open_about_btn.show_about_frame(
            False)

        self._init_tool_bar()
        self._set_layout()
        self._set_stylesheets()

        self.sig_update_config = sig_update_config

    def _init_tool_bar(self):
        """
        Creates the main toolbar with all its content
        """
        self.toolbar = QToolBar()
        self.toolbar.setFixedHeight(70)

        # Open/hide buttons
        self.toolbar.addWidget(self.open_editor_btn)
        self.toolbar.addWidget(self.open_ram_btn)
        self.toolbar.addWidget(self.open_usb_btn)
        self.toolbar.addWidget(self.open_monitor_btn)
        self.toolbar.addWidget(self.open_symbol_btn)

        # Digirule model selection
        self.toolbar.addSeparator()
        self.digimodel_dropdown = DigiruleModelDropdown(
            self.on_digimodel_dropdown_changed)
        self.toolbar.addWidget(self.digimodel_dropdown)

        # Empty space to align the about button to the right
        spacer = QWidget()
        spacer.setStyleSheet("background-color: transparent;")
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolbar.addWidget(spacer)

        # About button
        self.toolbar.addWidget(self.open_about_btn)

    def _set_layout(self):
        """
        Creates this Widget's Layout
        """
        box = QVBoxLayout()
        box.setContentsMargins(0, 0, 0, 0)

        box.addWidget(self.toolbar)
        box.setAlignment(self.toolbar, Qt.AlignTop)

        box.addWidget(self.dr_canvas)
        box.setAlignment(self.dr_canvas, Qt.AlignTop)

        bottom_box = QHBoxLayout()
        bottom_box.setContentsMargins(0, 0, 0, 0)

        bottom_box.addWidget(self.statusbar)
        bottom_box.addWidget(self.slider)

        box.addLayout(bottom_box)
        box.setAlignment(bottom_box, Qt.AlignBottom)

        self.setLayout(box)

    def _set_stylesheets(self):
        self.toolbar.setStyleSheet(style.get_stylesheet("qtoolbar"))

        # Execution Frame
        self.setStyleSheet(style.get_stylesheet("common"))

    # --- Callbacks methods ---

    def on_digimodel_dropdown_changed(self):
        """
        Handles the Digirule's model-combo-box-selection-changed process. Calls the canvas redraw.
        """
        self.sig_update_config.emit(
            self.digimodel_dropdown.get_digirule_model())

        self.dr_canvas.digirule_changed(self.config.get(
            'digirule', 'DR_MODEL'))

    # --- Close handler ---
    def do_quit(self):
        pass

    def closeEvent(self, event):
        """
        Event called upon a red-cross click
        """
        if self.ask_quit_confirmation():
            self.is_quitting = True
            self.do_quit()

            # Reset status bar
            self.statusbar.sig_persistent_message.emit("")

            # Call the secondary frames close methods as well
            self.editor_frame.on_close()
            self.ram_frame.on_close()
            self.monitor_frame.on_close()
            self.usb_frame.on_close()
            self.symbol_frame.on_close()
            self.about_frame.on_close()

            event.accept()
        else:
            event.ignore()

    def ask_quit_confirmation(self):
        """
        Asks a quit confirmation message
        :return: True if the user wants to quit the app
        """
        return DialogQuitConfirmation().exec_()
Beispiel #14
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        #window setup
        resolution = QDesktopWidget().screenGeometry()
        self.screen_w = resolution.width()
        self.screen_h = resolution.height()
        self.setGeometry(0, 0, 650, 550)
        self.setWindowTitle('MARS_v1_8')
        self.setWindowIcon(QIcon('icons/mouse.png'))
        self.queue = Queue()
        self.queue_list = []
        self.str_proc = ''
        self.fname = ''

        #center window
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
        #adjust size
        self.resize(self.screen_w / 2, self.screen_h / 2)
        self.Menu()
        self.Layout()

        central_widget = QWidget()
        central_widget.setLayout(self.main_layout)
        self.setCentralWidget(central_widget)

    def Menu(self):
        #this creates an action exit, a shortcut and status tip
        exitAction = QAction(QIcon('icons/exit.png'), '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(self.close)

        openFile = QAction(QIcon('icons/open.png'), '&Open', self)
        openFile.setShortcut('Ctrl+O')
        openFile.setStatusTip('Open new File')
        openFile.triggered.connect(self.browse)

        runAction = QAction(QIcon('icons/run.png'), '&Run', self)
        runAction.setShortcut('Ctrl+R')
        runAction.setStatusTip('Run Mars')
        runAction.triggered.connect(self.run_event)

        resetAction = QAction(QIcon('icons/reset.png'), '&Reset', self)
        resetAction.setShortcut('Ctrl+X')
        resetAction.setStatusTip('Reset Mars')
        resetAction.triggered.connect(self.reset)

        #create status bar to show tooltip
        statusbar = QStatusBar(self)
        self.setStatusBar(statusbar)

        #create menu
        self.menu_File = QMenu('&File', self)
        self.menuBar().addMenu(self.menu_File)
        self.menu_File.addAction(openFile)
        self.menu_File.addAction(runAction)
        self.menu_File.addAction(resetAction)
        self.menu_File.addSeparator()
        self.menu_File.addAction(exitAction)

        #create toolbar
        self.toolbar = QToolBar("Toolbar", self)
        self.toolbar.addAction(openFile)
        self.toolbar.addAction(runAction)
        self.toolbar.addAction(resetAction)
        self.toolbar.addSeparator()
        # self.toolbar.move(5, 5)
        self.toolbar2 = QToolBar("ToolbarExit", self)
        self.toolbar2.addAction(exitAction)

        self.toto = QFrame(self)
        self.toto.setFrameShape(QFrame.HLine)
        self.toto.setFrameShadow(QFrame.Sunken)
        self.toto.setLineWidth(2)

    def Layout(self):
        #LAYOUT
        self.select_video = QLabel(self)
        self.select_video.setText("Folder Selected:")
        self.select_video.setVisible(False)

        self.browse_btn = QPushButton("Browse", self)
        self.browse_btn.setStatusTip(" Browse Folder")
        # self.browse_btn.setStyleSheet("background-color: rgb(186, 186, 186); border-radius: 15px;border-style: solid;border-width: 2px;border-color: black;");
        self.browse_btn.clicked.connect(self.browse)

        self.VideoName = QLabel(self)

        self.todo = QLabel(self)
        self.todo.setText("What do you want to do?")
        self.todo.setVisible(False)

        ## Various checkboxes for activities to perform within MARS.
        self.doPose = False
        self.pose_chbox = QCheckBox('[Pose]', self)
        self.pose_chbox.stateChanged.connect(self.checkDoPose)
        self.pose_chbox.setVisible(False)

        self.doFeats = False
        self.feat_chbox = QCheckBox('[Features]', self)
        self.feat_chbox.stateChanged.connect(self.checkDoFeat)
        self.feat_chbox.setVisible(False)

        self.doActions = False
        self.actions_chbox = QCheckBox('[Classify Actions]', self)
        self.actions_chbox.stateChanged.connect(self.checkDoActions)
        self.actions_chbox.setVisible(False)

        # self.ddlist_label = QLabel(self)
        # self.ddlist_label.setText("Classifier:")
        # self.ddlist_label.move(200, 150)
        # self.ddlist_label.resize(150, 30)
        # self.ddlist_label.setVisible(False)
        #
        # self.ddlist = QComboBox(self)
        # self.ddlist.setVisible(False)
        # self.ddlist.setStatusTip('Choose the classifier you\'d like to use.')
        # self.ddlist.move(220, 120)
        # self.ddlist.resize(150, 50)
        # self.ddlist.setSizeAdjustPolicy(QComboBox.AdjustToContents)

        self.doVideo = False
        self.video_chbox = QCheckBox('[Produce Video]', self)
        self.video_chbox.stateChanged.connect(self.checkDoVideo)
        self.video_chbox.setVisible(False)

        self.doOverwrite = False
        self.overwrite_chbox = QCheckBox('[Overwrite]', self)
        self.overwrite_chbox.setStyleSheet("background-color: #ff7a7a")
        self.overwrite_chbox.stateChanged.connect(self.checkDoOverwrite)
        self.overwrite_chbox.setVisible(False)

        ## Checkboxes that pick which view(s) to use, as well as the internal values they represent.
        self.doTop = False
        self.top_chbox = QCheckBox('[Top]', self)
        self.top_chbox.stateChanged.connect(self.checkDoTop)
        self.top_chbox.setVisible(False)

        self.doToppcf = False
        # self.toppcf_chbox = QCheckBox('[Top (w/ Front pixel features)]', self)
        # self.toppcf_chbox.stateChanged.connect(self.checkDoToppcf)
        # self.toppcf_chbox.setVisible(False)

        self.doFront = False
        self.front_chbox = QCheckBox('[Front]', self)
        self.front_chbox.stateChanged.connect(self.checkDoFront)
        self.front_chbox.setVisible(False)

        # Button to run MARS.
        self.run_mars = QPushButton("[Run MARS]", self)
        self.run_mars.setVisible(False)
        self.run_mars.setStatusTip('Run detection and actions classification')
        self.run_mars.setStyleSheet(
            "background-color: rgb(142, 229, 171); border-radius: 15px;")
        self.run_mars.clicked.connect(self.run_event)

        # Button to reset the form for MARS.
        self.reset_btn = QPushButton("[Reset]", self)
        self.reset_btn.setVisible(False)
        self.reset_btn.setStatusTip('Reset buttons')
        self.reset_btn.setStyleSheet(
            "background-color: rgb(229, 200, 142);border-radius: 15px")
        self.reset_btn.clicked.connect(self.reset)

        # Button for adding things to queue.
        self.add2queue_btn = QPushButton("[Enqueue]", self)
        self.add2queue_btn.setVisible(False)
        self.add2queue_btn.setStyleSheet(
            "background-color: rgb(216,191,216);border-radius: 50px")
        self.add2queue_btn.clicked.connect(self.addToQueue)

        self.progress = QLabel(self)
        self.progress.setVisible(True)

        # Progress bar above the global progress, shows the progress on the current task.
        self.progbar = QProgressBar(self)
        self.progbar.setStyleSheet(
            "background-color: #FFA07A; border: 3px solid #000000;")
        self.progbar.setVisible(True)
        self.progbar.setAlignment(QtCore.Qt.AlignCenter)
        # Label for progress bar.
        self.progbar_label = QLabel(self)
        self.progbar_label.setText("Current Task Progress:")

        # Big progress bar at the bottom. Global progress.
        self.big_progbar = QProgressBar(self)
        self.big_progbar.setVisible(True)
        self.big_progbar.setStyleSheet(
            "background-color: #add8e6; border: 3px solid #FFFFFF;")
        self.big_progbar.setAlignment(QtCore.Qt.AlignCenter)
        # Label for big progress bar.
        self.big_progbar_label = QLabel(self)
        self.big_progbar_label.setText("Global Video Progress:")

        # Layout for the browsing span.
        self.button_layout = QHBoxLayout()
        self.button_layout.addWidget(self.browse_btn)
        self.button_layout.addWidget(self.select_video)
        self.button_layout.addWidget(self.VideoName)
        self.button_layout.addWidget(self.add2queue_btn)
        self.button_layout.addStretch(0.5)

        # Layout for the menu at the top.
        self.menu_layout = QHBoxLayout()
        self.menu_layout.addWidget(self.toolbar)
        self.menu_layout.addStretch()
        self.menu_layout.addWidget(self.toolbar2)

        # Layout for the view selection (Top, Toppcf, Front)
        self.view_layout = QHBoxLayout()
        self.view_layout.addWidget(self.top_chbox)
        # self.view_layout.addWidget(self.toppcf_chbox)
        self.view_layout.addWidget(self.front_chbox)
        self.view_layout.addStretch()

        # Layout for the checkboxes.
        self.chbox_layout = QHBoxLayout()
        self.chbox_layout.setSpacing(10)
        self.chbox_layout.addWidget(self.pose_chbox)
        self.chbox_layout.addWidget(self.feat_chbox)
        self.chbox_layout.addWidget(self.actions_chbox)
        self.chbox_layout.addWidget(self.video_chbox)
        self.chbox_layout.addWidget(self.overwrite_chbox)
        self.chbox_layout.addStretch(1)

        # Layout for the activity buttons, RUN and RESET.
        self.active_layout = QHBoxLayout()
        self.active_layout.addWidget(self.run_mars, stretch=2)
        self.active_layout.addWidget(self.reset_btn, stretch=1)

        # # Layout for the task progress bar.
        # self.task_progbar_layout = QtGui.QHBoxLayout()
        # self.task_progbar_layout.addWidget(self.progbar_label)
        # self.task_progbar_layout.addWidget(self.progbar, stretch=1)
        #
        # # Layout for the global progress bar.
        # self.global_progbar_layout = QtGui.QHBoxLayout()
        # self.global_progbar_layout.addWidget(self.big_progbar_label)
        # self.global_progbar_layout.addWidget(self.big_progbar)

        # Layout for the labels, to get ther vertically-aligned.
        self.progbar_label_layout = QVBoxLayout()
        self.progbar_label_layout.addWidget(self.progbar_label)
        self.progbar_label_layout.addWidget(self.big_progbar_label)

        # Layout for the progress bars themselves, to get them vertically-aligned.
        self.progbar_bar_layout = QVBoxLayout()
        self.progbar_bar_layout.addWidget(self.progbar)
        self.progbar_bar_layout.addWidget(self.big_progbar)

        # Layout for the combined progress bars and labels.
        self.progbar_layout = QHBoxLayout()
        self.progbar_layout.addLayout(self.progbar_label_layout)
        self.progbar_layout.addLayout(self.progbar_bar_layout, stretch=1)

        # This layout puts everything on the screen.
        self.main_layout = QVBoxLayout()
        self.main_layout.addLayout(self.menu_layout)
        self.main_layout.addWidget(self.toto)
        self.main_layout.addLayout(self.button_layout)
        self.main_layout.addWidget(self.todo)
        self.main_layout.addLayout(self.view_layout)
        self.main_layout.addLayout(self.chbox_layout)
        self.main_layout.addLayout(self.active_layout)
        self.main_layout.addWidget(self.progress)

        self.main_layout.addStretch()
        self.main_layout.addLayout(self.progbar_layout)
#        self.main_layout.addLayout(self.task_progbar_layout)
#        self.main_layout.addLayout(self.global_progbar_layout)

    def addToQueue(self):
        self.queue.put(self.fname)
        self.queue_list.append(self.fname)
        barMsg = self.fname + " added to the list!\n"
        msg = barMsg
        self.updateProgess(barMsg, msg)

    def browse(self):
        # sender = self.sender()
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.Directory)
        dialog.setOption(QFileDialog.ShowDirsOnly)
        if os.path.exists(self.fname):
            dir_to_use = self.fname
        else:
            dir_to_use = os.path.curdir

        self.fname = dialog.getExistingDirectory(self, 'Choose Directory',
                                                 dir_to_use)
        self.statusBar().showMessage(self.fname + ' selected ')
        if os.path.exists(self.fname) and os.path.isdir(
                self.fname) and self.fname != '':
            files = os.listdir(self.fname)
            seq_files = [
                f for f in files if f.endswith('.seq') or f.endswith('.avi')
                or f.endswith('.mp4') or f.endswith('.mpg')
            ]
            self.vid_name = self.fname.split('/')[-1]
            #if len(seq_files) >= 2:
            self.VideoName.setText(self.fname)
            self.todo.setVisible(True)

            self.select_video.setVisible(True)
            self.add2queue_btn.setVisible(True)
            # self.ddlist_label.setVisible(True)
            # self.ddlist.setVisible(True)

            self.pose_chbox.setVisible(True)
            self.feat_chbox.setVisible(True)
            self.actions_chbox.setVisible(True)
            self.video_chbox.setVisible(True)

            self.front_chbox.setVisible(True)
            self.top_chbox.setVisible(True)
            # self.toppcf_chbox.setVisible(True)

            self.run_mars.setVisible(True)
            self.reset_btn.setVisible(True)
            self.overwrite_chbox.setVisible(True)
            #else:
            #    QMessageBox.information(self, "Not all needed files exists", "Select a folder containing .seq files!")
        else:
            QMessageBox.information(
                self, " Wrong file selected",
                "No compatible movie files found! Supported formats: .seq, .avi, .mp4, .mpg"
            )
            self.fname = dir_to_use

    def checkDoPose(self, state):
        self.doPose = (state == QtCore.Qt.Checked)

    def checkDoFeat(self, state):
        self.doFeats = (state == QtCore.Qt.Checked)

    def checkDoActions(self, state):
        self.doActions = (state == QtCore.Qt.Checked)

    def checkDoVideo(self, state):
        self.doVideo = (state == QtCore.Qt.Checked)

    def checkDoOverwrite(self, state):
        self.doOverwrite = (state == QtCore.Qt.Checked)

    def checkDoTop(self, state):
        self.doTop = (state == QtCore.Qt.Checked)
        # if self.doTop:
        #     self.ddlist.addItem("top mlp")
        #     self.ddlist.addItem("top xgb")
        #     self.ddlist.addItem("top mlp wnd")
        #     self.ddlist.addItem("top xgb wnd")
        # else:
        #     self.ddlist.clear()

    def checkDoToppcf(self, state):
        self.doToppcf = (state == QtCore.Qt.Checked)
        # if self.doToppcf:
        #     self.ddlist.addItem("top pcf mlp")
        #     self.ddlist.addItem("top pcf xgb")
        #     self.ddlist.addItem("top pcf mlp wnd")
        #     self.ddlist.addItem("top pcf xgb wnd")
        # else:
        #     self.ddlist.clear()

    def checkDoFront(self, state):
        self.doFront = (state == QtCore.Qt.Checked)
        # if self.doFront:
        #     self.ddlist.addItem("topfront mlp")
        #     self.ddlist.addItem("topfront xgb")
        #     self.ddlist.addItem("topfront mlp wnd")
        #     self.ddlist.addItem("topfront xgb wnd")
        # else:
        #     self.ddlist.clear()

    def reset(self):
        todo = [self.doPose, self.doFeats, self.doActions]
        # if not self.todo.isVisible() or  sum(todo)== 0:
        #     QMessageBox.information(self, "Reset", "Nothing to reset")
        # else:
        self.doPose = False
        self.doFeats = False
        self.doActions = False
        self.doVideo = False
        self.doOverwrite = False

        self.doFront = False
        self.doTop = False
        self.doToppcf = False

        self.pose_chbox.setCheckState(QtCore.Qt.Unchecked)
        self.feat_chbox.setCheckState(QtCore.Qt.Unchecked)
        self.actions_chbox.setCheckState(QtCore.Qt.Unchecked)
        self.video_chbox.setCheckState(QtCore.Qt.Unchecked)
        self.overwrite_chbox.setCheckState(QtCore.Qt.Unchecked)

        self.front_chbox.setCheckState(QtCore.Qt.Unchecked)
        self.top_chbox.setCheckState(QtCore.Qt.Unchecked)
        # self.toppcf_chbox.setCheckState(QtCore.Qt.Unchecked)

        self.str_proc = ''
        self.progress.setText(self.str_proc)

        self.VideoName.setText('')
        self.fname = ''

        self.statusBar().showMessage('')
        self.changeEnable_wdj(True)
        self.clearProgress()

    def changeEnable_wdj(self, b=False):
        self.run_mars.setEnabled(b)
        self.reset_btn.setEnabled(b)

        self.pose_chbox.setEnabled(b)
        self.feat_chbox.setEnabled(b)
        self.actions_chbox.setEnabled(b)
        self.video_chbox.setEnabled(b)
        self.overwrite_chbox.setEnabled(b)

        # self.add2queue_btn.setEnabled(b)
        # self.ddlist.setEnabled(b)

        self.front_chbox.setEnabled(b)
        self.top_chbox.setEnabled(b)
        # self.toppcf_chbox.setEnabled(b)

    # def stop_event(self):
    #     print('Stopped')
    #     # self.genericThread.stop()
    #     # self.genericThread.wait()
    #     self.statusBar().showMessage('Stopped processing')
    #     self.changeEnable_wdj(True)
    #     # self.stop_run.setVisible(False)

    def update_thread(self, prog):
        if prog == 1:
            print('Thread pose done')
        if prog == 2:
            print('Thread features done')
        if prog == 3:
            print('Thread actions done')
        if prog == 4:
            print('Thread video done')

    def thread_done(self):
        print('Thread ended')
        # self.changeEnable_wdj(True)
        # self.stop_run.setVisible(False)

    def queue_done(self):
        print('Queue ended')
        self.changeEnable_wdj(True)

    def updateProgess(self, barMsg, msg):
        self.statusBar().showMessage(barMsg)
        self.str_proc += msg
        self.progress.setText(self.str_proc)
        self.scrollText()

    def updateProgbar(self, value, set_max):
        if set_max != 0:
            self.progbar.setMaximum(set_max)
        self.progbar.setValue(value)

    def updateBigProgbar(self, value, set_max):
        if set_max != 0:
            self.big_progbar.setMaximum(set_max)
        self.big_progbar.setValue(value)

    def clearProgress(self):
        self.str_proc = 'Console cleared. \n'
        self.progress.setText(self.str_proc)
        self.resize(self.screen_w / 2, self.screen_h / 2)
        # self.adjustSize()
        # self.changeEnable_wdj(True)

    def scrollText(self):
        MAX_LINES = 20
        all_lines = self.str_proc.splitlines()
        if len(all_lines) > MAX_LINES:
            renewed_lines = all_lines[-MAX_LINES:]
            self.str_proc = '\n'.join(renewed_lines) + '\n'

    def run_event(self):
        todo = [self.doPose, self.doFeats, self.doActions, self.doVideo]
        if not self.todo.isVisible():
            QMessageBox.information(self, "Empty selection",
                                    "Select a folder to process.")
        elif sum(todo) == 0:
            QMessageBox.information(self, "Empty selection",
                                    "Select at least one task to do.")
        else:
            self.str_proc = ''
            self.progress.setVisible(True)
            self.genericThread = GenericThread(self.doPose, self.doFeats,
                                               self.doActions, self.doVideo,
                                               self.doOverwrite, self.doFront,
                                               self.doTop, self.doToppcf,
                                               self.queue, self.fname)
            self.genericThread.update_th.connect(self.update_thread)
            self.genericThread.done_th.connect(self.thread_done)
            self.genericThread.done_queue.connect(self.queue_done)

            self.genericThread.update_progbar_sig.connect(self.updateProgbar)
            self.genericThread.update_big_progbar_sig.connect(
                self.updateBigProgbar)
            self.genericThread.update_progress.connect(self.updateProgess)

            # self.genericThread.classifier_to_use = self.ddlist.currentText()
            self.genericThread.clear_sig.connect(self.clearProgress)

            self.genericThread.start()
            # self.stop_run.setVisible(True)
            self.changeEnable_wdj(False)
Beispiel #15
0
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.browser = QWebEngineView()
        self.browser.setUrl(QUrl("http://google.com"))

        self.browser.urlChanged.connect(self.update_urlbar)
        self.browser.loadFinished.connect(self.update_title)
        self.setCentralWidget(self.browser)

        self.status = QStatusBar()
        self.setStatusBar(self.status)

        navtb = QToolBar("Navigation")
        navtb.setIconSize(QSize(16, 16))
        self.addToolBar(navtb)

        back_btn = QAction(QIcon(os.path.join('images', 'arrow-180.png')),
                           "Back", self)
        back_btn.setStatusTip("Back to previous page")
        back_btn.triggered.connect(self.browser.back)
        navtb.addAction(back_btn)

        next_btn = QAction(QIcon(os.path.join('images', 'arrow-000.png')),
                           "Forward", self)
        next_btn.setStatusTip("Forward to next page")
        next_btn.triggered.connect(self.browser.forward)
        navtb.addAction(next_btn)

        reload_btn = QAction(
            QIcon(os.path.join('images', 'arrow-circle-315.png')), "Reload",
            self)
        reload_btn.setStatusTip("Reload page")
        reload_btn.triggered.connect(self.browser.reload)
        navtb.addAction(reload_btn)

        home_btn = QAction(QIcon(os.path.join('images', 'home.png')), "Home",
                           self)
        home_btn.setStatusTip("Go home")
        home_btn.triggered.connect(self.navigate_home)
        navtb.addAction(home_btn)

        navtb.addSeparator()

        self.httpsicon = QLabel()  # Yes, really!
        self.httpsicon.setPixmap(
            QPixmap(os.path.join('images', 'lock-nossl.png')))
        navtb.addWidget(self.httpsicon)

        self.urlbar = QLineEdit()
        self.urlbar.returnPressed.connect(self.navigate_to_url)
        navtb.addWidget(self.urlbar)

        stop_btn = QAction(QIcon(os.path.join('images', 'cross-circle.png')),
                           "Stop", self)
        stop_btn.setStatusTip("Stop loading current page")
        stop_btn.triggered.connect(self.browser.stop)
        navtb.addAction(stop_btn)

        # Uncomment to disable native menubar on Mac
        # self.menuBar().setNativeMenuBar(False)

        file_menu = self.menuBar().addMenu("&File")

        open_file_action = QAction(
            QIcon(os.path.join('images', 'disk--arrow.png')), "Open file...",
            self)
        open_file_action.setStatusTip("Open from file")
        open_file_action.triggered.connect(self.open_file)
        file_menu.addAction(open_file_action)

        save_file_action = QAction(
            QIcon(os.path.join('images', 'disk--pencil.png')),
            "Save Page As...", self)
        save_file_action.setStatusTip("Save current page to file")
        save_file_action.triggered.connect(self.save_file)
        file_menu.addAction(save_file_action)

        print_action = QAction(QIcon(os.path.join('images', 'printer.png')),
                               "Print...", self)
        print_action.setStatusTip("Print current page")
        print_action.triggered.connect(self.print_page)
        file_menu.addAction(print_action)

        help_menu = self.menuBar().addMenu("&Help")

        about_action = QAction(QIcon(os.path.join('images', 'question.png')),
                               "About MooseAche", self)
        about_action.setStatusTip("Find out more about MooseAche")  # Hungry!
        about_action.triggered.connect(self.about)
        help_menu.addAction(about_action)

        navigate_mozarella_action = QAction(
            QIcon(os.path.join('images', 'lifebuoy.png')),
            "MooseAche Homepage", self)
        navigate_mozarella_action.setStatusTip("Go to MooseAche Homepage")
        navigate_mozarella_action.triggered.connect(self.navigate_mozarella)
        help_menu.addAction(navigate_mozarella_action)

        self.show()

        self.setWindowIcon(QIcon(os.path.join('images', 'ma-icon-64.png')))
Beispiel #16
0
    def __init__(self):
        super().__init__()

        # tag::tabWidget[]
        self.tabs = QTabWidget()
        self.tabs.setDocumentMode(True)
        self.tabs.tabBarDoubleClicked.connect(self.tab_open_doubleclick)
        self.tabs.currentChanged.connect(self.current_tab_changed)
        self.tabs.setTabsClosable(True)
        self.tabs.tabCloseRequested.connect(self.close_current_tab)

        self.setCentralWidget(self.tabs)
        # end::tabWidget[]

        navtb = QToolBar("Navigation")
        navtb.setIconSize(QSize(16, 16))
        self.addToolBar(navtb)

        back_btn = QAction(QIcon(os.path.join("icons", "arrow-180.png")),
                           "Back", self)
        back_btn.setStatusTip("Back to previous page")
        back_btn.triggered.connect(lambda: self.tabs.currentWidget().back())
        navtb.addAction(back_btn)

        next_btn = QAction(QIcon(os.path.join("icons", "arrow-000.png")),
                           "Forward", self)
        next_btn.setStatusTip("Forward to next page")
        next_btn.triggered.connect(lambda: self.tabs.currentWidget().forward())
        navtb.addAction(next_btn)

        reload_btn = QAction(
            QIcon(os.path.join("icons", "arrow-circle-315.png")), "Reload",
            self)
        reload_btn.setStatusTip("Reload page")
        reload_btn.triggered.connect(
            lambda: self.tabs.currentWidget().reload())
        navtb.addAction(reload_btn)

        home_btn = QAction(QIcon(os.path.join("icons", "home.png")), "Home",
                           self)
        home_btn.setStatusTip("Go home")
        home_btn.triggered.connect(self.navigate_home)
        navtb.addAction(home_btn)

        navtb.addSeparator()

        self.httpsicon = QLabel()  # Yes, really!
        self.httpsicon.setPixmap(
            QPixmap(os.path.join("icons", "lock-nossl.png")))
        navtb.addWidget(self.httpsicon)

        self.urlbar = QLineEdit()
        self.urlbar.returnPressed.connect(self.navigate_to_url)
        navtb.addWidget(self.urlbar)

        stop_btn = QAction(QIcon(os.path.join("icons", "cross-circle.png")),
                           "Stop", self)
        stop_btn.setStatusTip("Stop loading current page")
        stop_btn.triggered.connect(lambda: self.tabs.currentWidget().stop())
        navtb.addAction(stop_btn)

        self.menuBar().setNativeMenuBar(False)
        self.statusBar()

        file_menu = self.menuBar().addMenu("&File")

        new_tab_action = QAction(
            QIcon(os.path.join("icons", "ui-tab--plus.png")), "New Tab", self)
        new_tab_action.setStatusTip("Open a new tab")
        new_tab_action.triggered.connect(lambda _: self.add_new_tab())
        file_menu.addAction(new_tab_action)

        open_file_action = QAction(
            QIcon(os.path.join("icons", "disk--arrow.png")), "Open file...",
            self)
        open_file_action.setStatusTip("Open from file")
        open_file_action.triggered.connect(self.open_file)
        file_menu.addAction(open_file_action)

        save_file_action = QAction(
            QIcon(os.path.join("icons", "disk--pencil.png")),
            "Save Page As...", self)
        save_file_action.setStatusTip("Save current page to file")
        save_file_action.triggered.connect(self.save_file)
        file_menu.addAction(save_file_action)

        print_action = QAction(QIcon(os.path.join("icons", "printer.png")),
                               "Print...", self)
        print_action.setStatusTip("Print current page")
        print_action.triggered.connect(self.print_page)
        file_menu.addAction(print_action)

        # Create our system printer instance.
        self.printer = QPrinter()

        help_menu = self.menuBar().addMenu("&Help")

        about_action = QAction(
            QIcon(os.path.join("icons", "question.png")),
            "About Mozzarella Ashbadger",
            self,
        )
        about_action.setStatusTip(
            "Find out more about Mozzarella Ashbadger")  # Hungry!
        about_action.triggered.connect(self.about)
        help_menu.addAction(about_action)

        navigate_mozarella_action = QAction(
            QIcon(os.path.join("icons", "lifebuoy.png")),
            "Mozzarella Ashbadger Homepage",
            self,
        )
        navigate_mozarella_action.setStatusTip(
            "Go to Mozzarella Ashbadger Homepage")
        navigate_mozarella_action.triggered.connect(self.navigate_mozarella)
        help_menu.addAction(navigate_mozarella_action)

        self.add_new_tab(QUrl("http://www.google.com"), "Homepage")

        self.show()

        self.setWindowTitle("Mozzarella Ashbadger")
        self.setWindowIcon(QIcon(os.path.join("icons", "ma-icon-64.png")))
Beispiel #17
0
    def __init__(self, config):
        assertMainThread()
        super().__init__(config)

        # state
        self.preventSeek = False
        self.beginTime = None
        self.timeRatio = 1.0

        # gui
        srv = Services.getService("MainWindow")
        config.configLoaded.connect(self.restoreState)
        config.configAboutToSave.connect(self.saveState)
        self.config = config
        playbackMenu = srv.menuBar().addMenu("&Playback")

        style = QApplication.style()
        self.actStart = QAction(QIcon.fromTheme("media-playback-start", style.standardIcon(QStyle.SP_MediaPlay)),
                                "Start Playback", self)
        self.actPause = QAction(QIcon.fromTheme("media-playback-pause", style.standardIcon(QStyle.SP_MediaPause)),
                                "Pause Playback", self)
        self.actPause.setEnabled(False)
        self.actStepFwd = QAction(QIcon.fromTheme("media-seek-forward",
                                                  style.standardIcon(QStyle.SP_MediaSeekForward)),
                                  "Step Forward", self)
        self.actStepBwd = QAction(QIcon.fromTheme("media-seek-backward",
                                                  style.standardIcon(QStyle.SP_MediaSeekBackward)),
                                  "Step Backward", self)
        self.actSeekEnd = QAction(QIcon.fromTheme("media-skip-forward",
                                                  style.standardIcon(QStyle.SP_MediaSkipForward)),
                                  "Seek End", self)
        self.actSeekBegin = QAction(QIcon.fromTheme("media-skip-backward",
                                                    style.standardIcon(QStyle.SP_MediaSkipBackward)),
                                    "Seek Begin", self)
        self.actSetTimeFactor = {r : QAction("x 1/%d" % (1/r), self) if r < 1 else QAction("x %d" % r, self)
                                 for r in (1/8, 1/4, 1/2, 1, 2, 4, 8)}

        # pylint: disable=unnecessary-lambda
        # let's stay on the safe side and do not use emit as a slot...
        self.actStart.triggered.connect(lambda: self._startPlayback.emit())
        self.actPause.triggered.connect(lambda: self._pausePlayback.emit())
        self.actStepFwd.triggered.connect(lambda: self._stepForward.emit(self.selectedStream()))
        self.actStepBwd.triggered.connect(lambda: self._stepBackward.emit(self.selectedStream()))
        self.actSeekEnd.triggered.connect(lambda: self._seekEnd.emit())
        self.actSeekBegin.triggered.connect(lambda: self._seekBeginning.emit())
        # pylint: enable=unnecessary-lambda

        def setTimeFactor(newFactor):
            logger.debug("new time factor %f", newFactor)
            self._setTimeFactor.emit(newFactor)

        for r in self.actSetTimeFactor:
            logger.debug("adding action for time factor %f", r)
            self.actSetTimeFactor[r].triggered.connect(functools.partial(setTimeFactor, r))

        self.dockWidget = srv.newDockWidget("PlaybackControl", None, Qt.LeftDockWidgetArea)
        self.dockWidgetContents = QWidget(self.dockWidget)
        self.dockWidget.setWidget(self.dockWidgetContents)
        toolLayout = QBoxLayout(QBoxLayout.TopToBottom, self.dockWidgetContents)
        toolLayout.setContentsMargins(0, 0, 0, 0)
        toolBar = QToolBar()
        toolLayout.addWidget(toolBar)
        toolBar.addAction(self.actSeekBegin)
        toolBar.addAction(self.actStepBwd)
        toolBar.addAction(self.actStart)
        toolBar.addAction(self.actPause)
        toolBar.addAction(self.actStepFwd)
        toolBar.addAction(self.actSeekEnd)
        playbackMenu.addAction(self.actSeekBegin)
        playbackMenu.addAction(self.actStepBwd)
        playbackMenu.addAction(self.actStart)
        playbackMenu.addAction(self.actPause)
        playbackMenu.addAction(self.actStepFwd)
        playbackMenu.addAction(self.actSeekEnd)
        playbackMenu.addSeparator()
        for r in self.actSetTimeFactor:
            playbackMenu.addAction(self.actSetTimeFactor[r])
        self.timeRatioLabel = QLabel("x 1")
        self.timeRatioLabel.addActions(list(self.actSetTimeFactor.values()))
        self.timeRatioLabel.setContextMenuPolicy(Qt.ActionsContextMenu)
        toolBar.addSeparator()
        toolBar.addWidget(self.timeRatioLabel)
        contentsLayout = QGridLayout()
        toolLayout.addLayout(contentsLayout, 10)
        # now we add a position view
        self.positionSlider = QSlider(Qt.Horizontal, self.dockWidgetContents)
        self.beginLabel = QLabel(parent=self.dockWidgetContents)
        self.beginLabel.setAlignment(Qt.AlignLeft|Qt.AlignCenter)
        self.currentLabel = QLabel(parent=self.dockWidgetContents)
        self.currentLabel.setAlignment(Qt.AlignHCenter|Qt.AlignCenter)
        self.endLabel = QLabel(parent=self.dockWidgetContents)
        self.endLabel.setAlignment(Qt.AlignRight|Qt.AlignCenter)
        contentsLayout.addWidget(self.beginLabel, 0, 0, alignment=Qt.AlignLeft)
        contentsLayout.addWidget(self.currentLabel, 0, 1, alignment=Qt.AlignHCenter)
        contentsLayout.addWidget(self.endLabel, 0, 2, alignment=Qt.AlignRight)
        contentsLayout.addWidget(self.positionSlider, 1, 0, 1, 3)
        self.positionSlider.setTracking(False)
        self.positionSlider.valueChanged.connect(self.onSliderValueChanged, Qt.DirectConnection)
        self.positionSlider.sliderMoved.connect(self.displayPosition)

        # file browser
        self.browser = BrowserWidget(self.dockWidget)
        self.nameFiltersChanged.connect(self._onNameFiltersChanged, Qt.QueuedConnection)
        contentsLayout.addWidget(self.browser, 3, 0, 1, 3)
        contentsLayout.setRowStretch(3, 100)
        self.browser.activated.connect(self.browserActivated)

        self.actShowAllFiles = QAction("Show all files")
        self.actShowAllFiles.setCheckable(True)
        self.actShowAllFiles.setChecked(False)
        self.actShowAllFiles.toggled.connect(self._onShowAllFiles)
        playbackMenu.addSeparator()
        playbackMenu.addAction(self.actShowAllFiles)

        self.actGroupStream = QActionGroup(self)
        self.actGroupStream.setExclusionPolicy(QActionGroup.ExclusionPolicy.ExclusiveOptional)
        playbackMenu.addSeparator()
        self.actGroupStreamMenu = playbackMenu.addMenu("Step Stream")
        self._selectedStream = None

        self.recentSeqs = [QAction() for i in range(10)]
        playbackMenu.addSeparator()
        recentMenu = playbackMenu.addMenu("Recent")
        for a in self.recentSeqs:
            a.setVisible(False)
            a.triggered.connect(self.openRecent)
            recentMenu.addAction(a)

        self._supportedFeaturesChanged(set(), set())
Beispiel #18
0
class EditorFrame(QWidget):

    # --- Init methods ---

    def __init__(self, config, sig_message):
        """
        Editor frame. Contains a toolbar and an editor widget

        :param config: application configuration file
        :param sig_message: signal to emit to display a message in the main frame's status bar
        """
        QWidget.__init__(self)

        self.setMinimumSize(QSize(630, 500))

        self.config = config

        # Widgets
        self.editor = CodeEditor(config)
        self.editor.setMinimumSize(QSize(600, 430))

        self.open_file_btn = OpenFileButton(config)
        self.open_file_btn.set_content = self.editor.setPlainText  # Reroute text set method directly to the text editor widget
        self.open_file_btn.set_new_file_name = self.__init_title

        self.save_as_btn = SaveAsFileButton(config, sig_message)
        self.save_as_btn.get_content_to_save = self.retrieve_text  # Bind the text retrieve method in order to get the text to save
        self.save_as_btn.set_new_file_name = self.__init_title

        self.save_btn = SaveFileButton(config, sig_message)
        self.save_btn.get_content_to_save = self.retrieve_text

        self.assemble_btn = AssembleButton(config)

        self.search_field = QLineEdit()
        self.search_field.setPlaceholderText("Search (press return)")
        self.search_field.returnPressed.connect(self.do_search)

        # Editor's shortcuts binding
        self.editor.on_ctrl_o_activated = self.open_file_btn.on_open  # Open action
        self.editor.on_ctrl_s_activated = self.do_save
        self.editor.on_ctrl_f_activated = self.do_search

        # Final initialization
        self.__init_title()
        self._init_tool_bar()
        self._set_layout()
        self._connect_all()
        self._set_stylesheet()

        self.editor.setFocus()  # Set the default focus on the Editor

    def __init_title(self, file_name=""):
        """
        Sets the currently edited file in this frame's title

        :param file_name: full file path
        """
        if file_name:
            self.setWindowTitle("DigiQt - Editing '" +
                                file_name.split("/")[-1] + "'")
        else:
            # In the case no file name is specified, we have an empty editor, we display default text
            self.setWindowTitle("DigiQt - Assemble Editor")

        self.save_btn.setEnabled(file_name != "")
        self.save_btn.set_file_path(file_name)

    def _init_tool_bar(self):
        """
        Creates the main toolbar with all its content
        """
        self.toolbar = QToolBar()
        self.toolbar.setFixedHeight(70)

        self.toolbar.addWidget(self.open_file_btn)
        self.toolbar.addWidget(self.save_btn)
        self.toolbar.addWidget(self.save_as_btn)

        self.toolbar.addSeparator()
        self.toolbar.addWidget(self.search_field)

        # Empty space to align the assemble button to the right
        spacer = QWidget()
        spacer.setStyleSheet("background-color: transparent;")
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolbar.addWidget(spacer)

        self.toolbar.addWidget(self.assemble_btn)

    def _set_layout(self):
        """
        Creates this Widget's Layout
        """
        box = QGridLayout()
        box.setContentsMargins(0, 0, 0, 0)

        box.addWidget(self.toolbar, 0, 0)

        box.addWidget(self.editor, 1, 0)

        self.setLayout(box)

    def _connect_all(self):
        """
        Connects all the buttons to methods
        """

    def _set_stylesheet(self):
        self.toolbar.setStyleSheet(style.get_stylesheet("qtoolbar"))
        self.editor.setStyleSheet(
            "background-color: " + self.config.get('colors', 'editor_bg') +
            "; color: " + self.config.get('colors', 'asm_text_default') + ";")

        self.search_field.setStyleSheet(
            "border: 2px solid gray; border-radius: 10px; padding: 0 8px; background: #585858; color: white"
        )

        # Execution Frame
        self.setStyleSheet(style.get_stylesheet("common"))

    # --- Buttons callbacks methods ---

    def retrieve_text(self):
        """
        Gets the content of the code editor widget
        :return: the code
        """
        return self.editor.toPlainText()

    def do_save(self):
        """
        Delegating method triggered upon Ctrl+S action. Performs a Save if a file is opened, or a SaveAs if not.
        """
        if self.save_btn.file_path:
            self.save_btn.on_save()
        else:
            self.save_as_btn.on_save_as()

    def do_search(self, text=None):
        """
        Searches the value present in the search field, or the places the specified text if there is one as search
        value, but does not triggers the search.

        :param text: Text to search (None will trigger a search on the field content)
        """
        if text:
            self.search_field.setText(text)
        else:
            self.editor.selectNext(self.search_field.text())

    # --- Close handler ---

    def closeEvent(self, event):
        """
        Event called upon a red-cross click.
        """
        self.on_close()

    def on_close(self):
        """
        Reroot this method in the Main Frame in order to Updates the execution frame's open editor icon and tooltip
        :return:
        """
        pass
Beispiel #19
0
class Ui_FE14MapEditor(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.toolbar = QToolBar()
        self.toggle_coordinate_type_action = QAction("Toggle Coordinate Type")
        self.refresh_action = QAction("Refresh")
        self.refresh_action.setShortcut(QKeySequence("Ctrl+R"))
        self.copy_spawn_action = QAction("Copy Spawn")
        self.copy_spawn_action.setShortcut(QKeySequence("Ctrl+C"))
        self.paste_spawn_action = QAction("Paste Spawn")
        self.paste_spawn_action.setShortcut(QKeySequence("Ctrl+V"))
        self.add_spawn_action = QAction("Add Spawn")
        self.delete_spawn_action = QAction("Delete Spawn")
        self.add_group_action = QAction("Add Group")
        self.delete_group_action = QAction("Delete Group")
        self.add_tile_action = QAction("Add Tile")
        self.toggle_mode_action = QAction("Toggle Mode")
        self.undo_action = QAction("Undo")
        self.undo_action.setShortcut(QKeySequence("Ctrl+Z"))
        self.redo_action = QAction("Redo")
        self.redo_action.setShortcut(QKeySequence("Ctrl+Shift+Z"))
        self.toolbar.addActions(
            [self.toggle_coordinate_type_action, self.refresh_action])
        self.toolbar.addSeparator()
        self.toolbar.addActions([
            self.copy_spawn_action, self.paste_spawn_action,
            self.add_spawn_action, self.delete_spawn_action,
            self.add_group_action, self.delete_group_action
        ])
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.add_tile_action)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.toggle_mode_action)
        self.toolbar.addSeparator()
        self.toolbar.addActions([self.undo_action, self.redo_action])
        self.addToolBar(self.toolbar)

        self.model_view = QTreeView()
        self.model_view.setHeaderHidden(True)
        self.grid = FE14MapGrid()
        self.grid_scroll = QScrollArea()
        self.grid_scroll.setWidgetResizable(True)
        self.grid_scroll.setWidget(self.grid)
        self.tile_list = QListView()
        self.terrain_pane = FE14TerrainEditorPane()
        self.spawn_pane = FE14SpawnEditorPane()

        self.model_view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.model_view_context_menu = QMenu()
        self.model_view_context_menu.addActions(
            [self.toggle_coordinate_type_action, self.refresh_action])
        self.model_view_context_menu.addSeparator()
        self.model_view_context_menu.addActions([
            self.copy_spawn_action, self.paste_spawn_action,
            self.add_spawn_action, self.delete_spawn_action,
            self.add_group_action, self.delete_group_action
        ])
        self.model_view_context_menu.addSeparator()
        self.model_view_context_menu.addAction(self.add_tile_action)
        self.model_view_context_menu.addSeparator()
        self.model_view_context_menu.addAction(self.toggle_mode_action)
        self.model_view_context_menu.addSeparator()
        self.model_view_context_menu.addActions(
            [self.undo_action, self.redo_action])

        self.status_bar = QStatusBar()
        self.coordinate_type_label = QLabel()
        self.status_bar.addPermanentWidget(self.coordinate_type_label)
        self.setStatusBar(self.status_bar)

        self.main_widget = QSplitter()
        self.main_widget.setOrientation(QtCore.Qt.Horizontal)
        self.main_widget.addWidget(self.model_view)
        self.main_widget.addWidget(self.grid_scroll)
        self.main_widget.addWidget(self.spawn_pane)
        self.main_widget.addWidget(self.terrain_pane)
        self.setCentralWidget(self.main_widget)
Beispiel #20
0
    def __init__(self, path_to_rom=""):
        super(MainWindow, self).__init__()

        self.setWindowIcon(icon("foundry.ico"))

        file_menu = QMenu("File")

        open_rom_action = file_menu.addAction("&Open ROM")
        open_rom_action.triggered.connect(self.on_open_rom)
        self.open_m3l_action = file_menu.addAction("&Open M3L")
        self.open_m3l_action.triggered.connect(self.on_open_m3l)

        file_menu.addSeparator()

        save_rom_action = file_menu.addAction("&Save ROM")
        save_rom_action.triggered.connect(self.on_save_rom)
        save_rom_as_action = file_menu.addAction("&Save ROM as ...")
        save_rom_as_action.triggered.connect(self.on_save_rom_as)
        """
        file_menu.AppendSeparator()
        """
        self.save_m3l_action = file_menu.addAction("&Save M3L")
        self.save_m3l_action.triggered.connect(self.on_save_m3l)
        """
        file_menu.Append(ID_SAVE_LEVEL_TO, "&Save Level to", "")
        file_menu.AppendSeparator()
        file_menu.Append(ID_APPLY_IPS_PATCH, "&Apply IPS Patch", "")
        file_menu.AppendSeparator()
        file_menu.Append(ID_ROM_PRESET, "&ROM Preset", "")
        """
        file_menu.addSeparator()
        settings_action = file_menu.addAction("&Settings")
        settings_action.triggered.connect(show_settings)
        file_menu.addSeparator()
        exit_action = file_menu.addAction("&Exit")
        exit_action.triggered.connect(lambda _: self.close())

        self.menuBar().addMenu(file_menu)
        """
        edit_menu = wx.Menu()

        edit_menu.Append(ID_EDIT_LEVEL, "&Edit Level", "")
        edit_menu.Append(ID_EDIT_OBJ_DEFS, "&Edit Object Definitions", "")
        edit_menu.Append(ID_EDIT_PALETTE, "&Edit Palette", "")
        edit_menu.Append(ID_EDIT_GRAPHICS, "&Edit Graphics", "")
        edit_menu.Append(ID_EDIT_MISC, "&Edit Miscellaneous", "")
        edit_menu.AppendSeparator()
        edit_menu.Append(ID_FREE_FORM_MODE, "&Free form Mode", "")
        edit_menu.Append(ID_LIMIT_SIZE, "&Limit Size", "")
        """

        level_menu = QMenu("Level")

        select_level_action = level_menu.addAction("&Select Level")
        select_level_action.triggered.connect(self.open_level_selector)
        """
        level_menu.Append(ID_GOTO_NEXT_AREA, "&Go to next Area", "")
        level_menu.AppendSeparator()
        """
        self.reload_action = level_menu.addAction("&Reload Level")
        self.reload_action.triggered.connect(self.reload_level)
        level_menu.addSeparator()
        self.edit_header_action = level_menu.addAction("&Edit Header")
        self.edit_header_action.triggered.connect(self.on_header_editor)
        """
        level_menu.Append(ID_EDIT_POINTERS, "&Edit Pointers", "")
        """

        self.menuBar().addMenu(level_menu)

        object_menu = QMenu("Objects")

        view_blocks_action = object_menu.addAction("&View Blocks")
        view_blocks_action.triggered.connect(self.on_block_viewer)
        view_objects_action = object_menu.addAction("&View Objects")
        view_objects_action.triggered.connect(self.on_object_viewer)
        """
        object_menu.AppendSeparator()
        object_menu.Append(ID_CLONE_OBJECT_ENEMY, "&Clone Object/Enemy", "")
        object_menu.AppendSeparator()
        object_menu.Append(ID_ADD_3_BYTE_OBJECT, "&Add 3 Byte Object", "")
        object_menu.Append(ID_ADD_4_BYTE_OBJECT, "&Add 4 Byte Object", "")
        object_menu.Append(ID_ADD_ENEMY, "&Add Enemy", "")
        object_menu.AppendSeparator()
        object_menu.Append(ID_DELETE_OBJECT_ENEMY, "&Delete Object/Enemy", "")
        object_menu.Append(ID_DELETE_ALL, "&Delete All", "")
        """

        self.menuBar().addMenu(object_menu)

        view_menu = QMenu("View")
        view_menu.triggered.connect(self.on_menu)

        action = view_menu.addAction("Mario")
        action.setProperty(ID_PROP, ID_MARIO)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_mario"])

        action = view_menu.addAction("&Jumps on objects")
        action.setProperty(ID_PROP, ID_JUMP_OBJECTS)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_jump_on_objects"])

        action = view_menu.addAction("Items in blocks")
        action.setProperty(ID_PROP, ID_ITEM_BLOCKS)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_items_in_blocks"])

        action = view_menu.addAction("Invisible items")
        action.setProperty(ID_PROP, ID_INVISIBLE_ITEMS)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_invisible_items"])

        view_menu.addSeparator()

        action = view_menu.addAction("Jump Zones")
        action.setProperty(ID_PROP, ID_JUMPS)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_jumps"])

        action = view_menu.addAction("&Grid lines")
        action.setProperty(ID_PROP, ID_GRID_LINES)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_grid"])

        action = view_menu.addAction("Resize Type")
        action.setProperty(ID_PROP, ID_RESIZE_TYPE)
        action.setCheckable(True)
        action.setChecked(SETTINGS["draw_expansion"])

        view_menu.addSeparator()

        action = view_menu.addAction("&Block Transparency")
        action.setProperty(ID_PROP, ID_TRANSPARENCY)
        action.setCheckable(True)
        action.setChecked(SETTINGS["block_transparency"])

        view_menu.addSeparator()
        view_menu.addAction("&Save Screenshot of Level").triggered.connect(
            self.on_screenshot)
        """
        view_menu.Append(ID_BACKGROUND_FLOOR, "&Background & Floor", "")
        view_menu.Append(ID_TOOLBAR, "&Toolbar", "")
        view_menu.AppendSeparator()
        view_menu.Append(ID_ZOOM, "&Zoom", "")
        view_menu.AppendSeparator()
        view_menu.Append(ID_USE_ROM_GRAPHICS, "&Use ROM Graphics", "")
        view_menu.Append(ID_PALETTE, "&Palette", "")
        view_menu.AppendSeparator()
        view_menu.Append(ID_MORE, "&More", "")
        """

        self.menuBar().addMenu(view_menu)

        help_menu = QMenu("Help")
        """
        help_menu.Append(ID_ENEMY_COMPATIBILITY, "&Enemy Compatibility", "")
        help_menu.Append(ID_TROUBLESHOOTING, "&Troubleshooting", "")
        help_menu.AppendSeparator()
        help_menu.Append(ID_PROGRAM_WEBSITE, "&Program Website", "")
        help_menu.Append(ID_MAKE_A_DONATION, "&Make a Donation", "")
        help_menu.AppendSeparator()
        """
        update_action = help_menu.addAction("Check for updates")
        update_action.triggered.connect(self.on_check_for_update)

        help_menu.addSeparator()

        video_action = help_menu.addAction("Feature Video on YouTube")
        video_action.triggered.connect(lambda: open_url(feature_video_link))

        discord_action = help_menu.addAction("SMB3 Rom Hacking Discord")
        discord_action.triggered.connect(lambda: open_url(discord_link))

        help_menu.addSeparator()

        about_action = help_menu.addAction("&About")
        about_action.triggered.connect(self.on_about)

        self.menuBar().addMenu(help_menu)

        self.level_selector = LevelSelector(parent=self)

        self.block_viewer = None
        self.object_viewer = None

        self.level_ref = LevelRef()
        self.level_ref.data_changed.connect(self._on_level_data_changed)

        self.context_menu = ContextMenu(self.level_ref)
        self.context_menu.triggered.connect(self.on_menu)

        self.level_view = LevelView(self, self.level_ref, self.context_menu)

        self.scroll_panel = QScrollArea()
        self.scroll_panel.setWidgetResizable(True)
        self.scroll_panel.setWidget(self.level_view)

        self.setCentralWidget(self.scroll_panel)

        self.spinner_panel = SpinnerPanel(self, self.level_ref)
        self.spinner_panel.zoom_in_triggered.connect(self.level_view.zoom_in)
        self.spinner_panel.zoom_out_triggered.connect(self.level_view.zoom_out)
        self.spinner_panel.object_change.connect(self.on_spin)

        self.object_list = ObjectList(self, self.level_ref, self.context_menu)

        self.object_dropdown = ObjectDropdown(self)
        self.object_dropdown.object_selected.connect(
            self._on_placeable_object_selected)

        self.level_size_bar = LevelSizeBar(self, self.level_ref)
        self.enemy_size_bar = EnemySizeBar(self, self.level_ref)

        self.jump_list = JumpList(self, self.level_ref)
        self.jump_list.add_jump.connect(self.on_jump_added)
        self.jump_list.edit_jump.connect(self.on_jump_edit)
        self.jump_list.remove_jump.connect(self.on_jump_removed)

        splitter = QSplitter(self)
        splitter.setOrientation(Qt.Vertical)

        splitter.addWidget(self.object_list)
        splitter.setStretchFactor(0, 1)
        splitter.addWidget(self.jump_list)

        splitter.setChildrenCollapsible(False)

        level_toolbar = QToolBar("Level Info Toolbar", self)
        level_toolbar.setContextMenuPolicy(Qt.PreventContextMenu)
        level_toolbar.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        level_toolbar.setOrientation(Qt.Horizontal)
        level_toolbar.setFloatable(False)

        level_toolbar.addWidget(self.spinner_panel)
        level_toolbar.addWidget(self.object_dropdown)
        level_toolbar.addWidget(self.level_size_bar)
        level_toolbar.addWidget(self.enemy_size_bar)
        level_toolbar.addWidget(splitter)

        level_toolbar.setAllowedAreas(Qt.LeftToolBarArea | Qt.RightToolBarArea)

        self.addToolBar(Qt.RightToolBarArea, level_toolbar)

        self.object_toolbar = ObjectToolBar(self)
        self.object_toolbar.object_selected.connect(
            self._on_placeable_object_selected)

        object_toolbar = QToolBar("Object Toolbar", self)
        object_toolbar.setContextMenuPolicy(Qt.PreventContextMenu)
        object_toolbar.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        object_toolbar.setFloatable(False)

        object_toolbar.addWidget(self.object_toolbar)
        object_toolbar.setAllowedAreas(Qt.LeftToolBarArea
                                       | Qt.RightToolBarArea)

        self.addToolBar(Qt.LeftToolBarArea, object_toolbar)

        menu_toolbar = QToolBar("Menu Toolbar", self)
        menu_toolbar.setOrientation(Qt.Horizontal)
        menu_toolbar.setIconSize(QSize(20, 20))

        menu_toolbar.addAction(
            icon("settings.svg"),
            "Editor Settings").triggered.connect(show_settings)
        menu_toolbar.addSeparator()
        menu_toolbar.addAction(icon("folder.svg"),
                               "Open ROM").triggered.connect(self.on_open_rom)
        menu_toolbar.addAction(
            icon("save.svg"), "Save Level").triggered.connect(self.on_save_rom)
        menu_toolbar.addSeparator()

        self.undo_action = menu_toolbar.addAction(icon("rotate-ccw.svg"),
                                                  "Undo Action")
        self.undo_action.triggered.connect(self.level_ref.undo)
        self.undo_action.setEnabled(False)
        self.redo_action = menu_toolbar.addAction(icon("rotate-cw.svg"),
                                                  "Redo Action")
        self.redo_action.triggered.connect(self.level_ref.redo)
        self.redo_action.setEnabled(False)

        menu_toolbar.addSeparator()
        menu_toolbar.addAction(icon("play-circle.svg"),
                               "Play Level").triggered.connect(self.on_play)
        menu_toolbar.addSeparator()
        menu_toolbar.addAction(icon("zoom-out.svg"),
                               "Zoom Out").triggered.connect(
                                   self.level_view.zoom_out)
        menu_toolbar.addAction(icon("zoom-in.svg"),
                               "Zoom In").triggered.connect(
                                   self.level_view.zoom_in)
        menu_toolbar.addSeparator()
        menu_toolbar.addAction(icon("tool.svg"),
                               "Edit Level Header").triggered.connect(
                                   self.on_header_editor)
        self.jump_destination_action = menu_toolbar.addAction(
            icon("arrow-right-circle.svg"), "Go to Jump Destination")
        self.jump_destination_action.triggered.connect(
            self._go_to_jump_destination)
        menu_toolbar.addSeparator()
        # menu_toolbar.addAction(icon("help-circle.svg"), "What's this?")

        self.addToolBar(Qt.TopToolBarArea, menu_toolbar)

        self.status_bar = ObjectStatusBar(self, self.level_ref)
        self.setStatusBar(self.status_bar)

        self.delete_shortcut = QShortcut(QKeySequence(Qt.Key_Delete), self,
                                         self.remove_selected_objects)

        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_X), self, self._cut_objects)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_C), self, self._copy_objects)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_V), self, self._paste_objects)

        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Z), self, self.level_ref.undo)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Y), self, self.level_ref.redo)
        QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Z), self,
                  self.level_ref.redo)

        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Plus), self,
                  self.level_view.zoom_in)
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Minus), self,
                  self.level_view.zoom_out)

        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_A), self,
                  self.level_view.select_all)

        if not self.on_open_rom(path_to_rom):
            self.deleteLater()

        self.showMaximized()
Beispiel #21
0
class MainWindow(QMainWindow):
    def __init__(self, app: QApplication):
        super().__init__()

        self.current_file = None

        self.console_dock: QDockWidget = None
        self.tools_dock: QDockWidget = None

        self.toolbar: QToolBar = None

        self.graph_widget: GraphWidget = None
        self.log_console_widget: LogConsoleWidget = None
        self.tools_widget: ToolsWidget = None

        self.file_menu: QMenu = None
        self.help_menu: QMenu = None
        self.view_menu: QMenu = None
        self.docks_menu: QMenu = None

        self.about_action: QAction = None
        self.new_action: QAction = None
        self.open_action: QAction = None
        self.save_action: QAction = None
        self.save_as_action: QAction = None
        self.exit_action: QAction = None
        self.toggle_tools_dock: QAction = None
        self.toggle_console_dock: QAction = None

        self.create_actions(app)
        self.create_widgets()
        self.create_docks()
        self.create_menus()
        self.create_toolbar()
        self.create_statusbar()

        self.setCentralWidget(self.graph_widget)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.console_dock)
        self.addDockWidget(Qt.RightDockWidgetArea, self.tools_dock)
        self.addToolBar(self.toolbar)
        self.setWindowTitle(self.tr("Proofy"))

        self.read_settings()

    def create_statusbar(self):
        self.statusBar().showMessage(self.tr("Welcome to Proofy!"))

    def create_docks(self):
        self.console_dock = QDockWidget(self.tr("Console"))
        self.console_dock.setWidget(self.log_console_widget)

        self.tools_dock = QDockWidget(self.tr("Tools"))
        self.tools_dock.setWidget(self.tools_widget)

    def create_toolbar(self):
        self.toolbar = QToolBar(self.tr("Tools"), self)
        self.toolbar.setStatusTip(self.tr("Tools"))
        self.toolbar.addActions([
            self.new_action,
            self.open_action,
            self.save_action,
            self.save_as_action,
            self.exit_action,
        ])
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.about_action)

    def create_widgets(self):
        self.log_console_widget = LogConsoleWidget()
        self.log_console_widget.add_loggers(logger)
        self.graph_widget = GraphWidget(self.log_console_widget)
        self.tools_widget = ToolsWidget(graph_widget=self.graph_widget)

    def create_menus(self):
        self.file_menu = self.menuBar().addMenu("File")
        self.file_menu.setStatusTip(self.tr("File operations"))
        self.file_menu.addActions([
            self.new_action,
            self.open_action,
            self.save_action,
            self.save_as_action,
            self.exit_action,
        ])

        self.view_menu = self.menuBar().addMenu("View")
        self.view_menu.setStatusTip(self.tr("View settings"))
        self.docks_menu = self.view_menu.addMenu("Docks")
        self.docks_menu.addAction(self.toggle_tools_dock)
        self.docks_menu.addAction(self.toggle_console_dock)

        self.help_menu = self.menuBar().addMenu("Help")
        self.help_menu.setStatusTip(self.tr("Help"))
        self.help_menu.addAction(self.about_action)

    def create_actions(self, app):

        self.about_action = QAction(
            app.style().standardIcon(
                QtWidgets.QStyle.SP_MessageBoxInformation),
            "About",
            self,
        )
        self.about_action.setStatusTip("Show information about Proofy")
        self.about_action.triggered.connect(self.about)

        self.new_action = QAction(
            app.style().standardIcon(QtWidgets.QStyle.SP_FileIcon), "New...",
            self)
        self.new_action.setStatusTip(self.tr("Create a new file"))
        self.new_action.setShortcuts(QKeySequence.New)
        self.new_action.triggered.connect(self.new)

        self.open_action = QAction(
            app.style().standardIcon(QtWidgets.QStyle.SP_DialogOpenButton),
            "Open...",
            self,
        )
        self.open_action.setStatusTip(self.tr("Open file"))
        self.open_action.setShortcuts(QKeySequence.Open)
        self.open_action.triggered.connect(self.open)

        self.save_action = QAction(
            app.style().standardIcon(QtWidgets.QStyle.SP_DialogSaveButton),
            "Save...",
            self,
        )
        self.save_action.setStatusTip(self.tr("Save file"))
        self.save_action.setShortcuts(QKeySequence.Save)
        self.save_action.triggered.connect(self.save)

        self.save_as_action = QAction(
            app.style().standardIcon(QtWidgets.QStyle.SP_DriveFDIcon),
            "Save As...",
            self,
        )
        self.save_as_action.setStatusTip(self.tr("Save to file"))
        self.save_as_action.setShortcuts(QKeySequence.SaveAs)
        self.save_as_action.triggered.connect(self.save_as)

        self.exit_action = QAction(
            app.style().standardIcon(QtWidgets.QStyle.SP_DialogCloseButton),
            "Exit",
            self,
        )
        self.exit_action.setStatusTip(self.tr("Exit Proofy"))
        self.exit_action.setShortcuts(QKeySequence.Quit)
        self.exit_action.triggered.connect(self.exit)

        self.toggle_console_dock = QAction("Toggle Console Dock", self)
        self.toggle_console_dock.setStatusTip(
            "Toggle visibility of the console dock")
        self.toggle_console_dock.triggered.connect(
            lambda _: self.console_dock.setVisible(not self.console_dock.
                                                   isVisible()))

        self.toggle_tools_dock = QAction("Toggle Tools Dock", self)
        self.toggle_tools_dock.setStatusTip(
            "Toggle visibility of the tools dock")
        self.toggle_tools_dock.triggered.connect(
            lambda _: self.tools_dock.setVisible(not self.tools_dock.isVisible(
            )))

    @Slot()
    def about(self):
        logger.debug(locals())
        QMessageBox.about(
            self,
            "About Proofy",
            self.tr(f"""
                <h1>Proofy {__version__}</h1>
                <p>
                <b>Proofy is a formal proof system GUI.</b>
                </p>
                <p>
                Oh, it looks like Proofy wants to talk!
                <blockquote>Proofy likes Sequent Calculus! And circles! And edges! And arrows! And ...</blockquote>
                </p>
                """),
        )

    def closeEvent(self, event: QCloseEvent):
        logger.debug(locals())
        if self.unsaved_check():
            self.write_settings()
            event.accept()
        else:
            event.ignore()

    @Slot()
    def exit(self):
        logger.debug(locals())
        if self.unsaved_check():
            QApplication.quit()

    @Slot()
    def new(self):
        logger.debug(locals())
        if self.unsaved_check():
            self.current_file = None

    def set_file_status(self, *, modified: bool):
        if self.current_file:
            file = pathlib.Path(self.current_file[0])
            self.setWindowTitle(f"{file.name}[*] [{file}] - Proofy")
            self.setWindowModified(modified)
        else:
            self.setWindowTitle(f"Proofy[*]")
            self.setWindowModified(modified)

    @Slot()
    def open(self):
        logger.debug(locals())
        if self.unsaved_check():
            if (path := QFileDialog.getOpenFileName(
                    self,
                    caption=self.tr("Open File"),
                    filter=self.graph_widget.get_open_file_extensions(),
            )):
                try:
                    QApplication.setOverrideCursor(Qt.WaitCursor)
                    self.graph_widget.open_file(*path)
                    self.statusBar().showMessage(f"Opened {path} successfully")
                    self.current_file = path
                    self.set_file_status(modified=False)
                except Exception as e:
                    logger.error(e)
                finally:
                    QApplication.restoreOverrideCursor()
Beispiel #22
0
        else:
            lbl.setText('')
            sim.cleanup()
            t.stop()
            benc_timer.stop()

    action.changed.connect(_handle_sim_action)
    toolbar = QToolBar()

    lbl = QLabel()

    benc_timer = QTimer(w)

    def _on_bench():
        global ticks
        lbl.setText(f'Frequency: {ticks} Hz')
        ticks = 0

    benc_timer.timeout.connect(_on_bench)

    toolbar.addAction(action)
    toolbar.addSeparator()
    toolbar.addWidget(lbl)
    w.addToolBar(toolbar)

    w.setCentralWidget(ed)

    w.setWindowTitle(make_title())
    w.show()
    app.exec_()
Beispiel #23
0
    def createToolBar(self):
        toolbar = QToolBar()

        act = toolbar.addAction(QIcon.fromTheme("document-new"),
                                "Create a new note", self.newNote)
        act.setShortcut(QKeySequence.New)
        toolbar.addAction(QIcon.fromTheme("folder-new"),
                          "Create a new notebook", self.newNotebook)
        toolbar.addSeparator()

        act = toolbar.addAction(QIcon.fromTheme("document-save"),
                                "Save changes to current note", self.saveNote)
        act.setShortcut(QKeySequence.Save)
        toolbar.addAction(QIcon.fromTheme("document-send"),
                          "Export current note")
        toolbar.addSeparator()

        toolbar.addAction(QIcon.fromTheme("format-text-bold"), "Bold")
        toolbar.addAction(QIcon.fromTheme("format-text-italic"), "Italic")
        toolbar.addAction(QIcon.fromTheme("format-text-underline"),
                          "Underline")

        self.headingsCombo = QComboBox()
        self.headingsCombo.addItem("H1")
        self.headingsCombo.addItem("H2")
        self.headingsCombo.addItem("H3")
        self.headingsCombo.addItem("H4")
        self.headingsCombo.addItem("H5")
        self.headingsCombo.addItem("H6")

        toolbar.addWidget(self.headingsCombo)
        toolbar.addSeparator()

        toolbar.addAction(QIcon.fromTheme("format-list-unordered"),
                          "Insert bulleted list")
        toolbar.addAction(QIcon.fromTheme("format-list-ordered"),
                          "Insert numbered list")
        toolbar.addAction(QIcon.fromTheme("insert-link"), "Inserts a link")
        toolbar.addSeparator()

        self.editableAction = toolbar.addAction(
            QIcon.fromTheme("edit"), "Toggle edit or markdown visualizer")
        self.editableAction.setCheckable(True)
        self.editableAction.setChecked(True)
        self.editableAction.setShortcut(QKeySequence("Ctrl+E"))
        QObject.connect(self.editableAction, SIGNAL('triggered(bool)'),
                        self.editTriggered)

        toolbar.addAction(QIcon.fromTheme("system-search"), "Search")

        self.notebooksCombo = QComboBox()
        self.notebooksCombo.setSizePolicy(QSizePolicy.Expanding,
                                          QSizePolicy.Preferred)
        self.notebooksCombo.addItem(QIcon.fromTheme("folder"),
                                    "Create new notebook")

        self.notesCombo = QComboBox()
        self.notesCombo.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Preferred)

        QObject.connect(self.notebooksCombo, SIGNAL("activated(QString)"),
                        self.switchNotebook)
        QObject.connect(self.notesCombo, SIGNAL("activated(QString)"),
                        self.switchNote)

        self.spacer = QWidget()
        self.spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

        toolbar.addWidget(self.spacer)
        toolbar.addWidget(self.notebooksCombo)
        toolbar.addWidget(self.notesCombo)

        return toolbar