示例#1
0
    def createDockWindows(self):
        dock = QDockWidget("Available Garments Types", self)
        #dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.availableItems = QListWidget(dock)
        self.availableItems.setMinimumWidth(350)
        self.availableItems.setMaximumWidth(350)
        #self.availableItems.addItems(("stuff"))
        self.availableItems.itemClicked.connect(self.itemClicked_Click)
        dock.setWidget(self.availableItems)
        self.addDockWidget(Qt.RightDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        dock.hide()

        self.dock = QDockWidget("Available Garment Sizes", self)
        self.orderItem = QTreeWidget(dock)
        #self.orderItem.setMinimumWidth(350)
        #self.orderItem.setMaximumWidth(350)
        #self.orderItem.insertText(("more stuff"))
        self.dock.setWidget(self.orderItem)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
        self.viewMenu.addAction(self.dock.toggleViewAction())
        self.dock.hide()
        
        #Create a tree widget for use when the t-shirt is clicked.
        self.treeDock = QDockWidget("Order Items", self)
        self.garmentTree = QTreeWidget(self.treeDock)
        self.garmentTree.setObjectName('garmentTree')
        self.garmentTree.itemClicked.connect(CSRWidgets.sumQuantity)
        self.garmentTree.itemClicked.connect(lambda: CSRWidgets.updateNameDesign(self))
            
        self.garmentTree.setMaximumWidth(480)
        self.garmentTree.setMinimumWidth(480)
   
        self.treeDock.hide()
    def __setup_sub_window_dock(self, window: QWidget, config: dict, sub_window_data: SimpleNamespace):
        dock_name = config.get('DockName', '')
        dock_area = config.get('DockArea', Qt.NoDockWidgetArea)
        dock_show = config.get('DockShow', False)
        dock_float = config.get('DockFloat', False)

        dock_wnd = QDockWidget(dock_name, self)
        dock_wnd.setAllowedAreas(
            Qt.RightDockWidgetArea | Qt.LeftDockWidgetArea | Qt.TopDockWidgetArea | Qt.BottomDockWidgetArea)
        # With this setting, the dock widget cannot be closed
        # dock_wnd.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)
        if dock_area != Qt.NoDockWidgetArea:
            if dock_area == Qt.AllDockWidgetAreas:
                self.addDockWidget(Qt.TopDockWidgetArea, dock_wnd)
                dock_wnd.setFloating(True)
                dock_wnd.move(QApplication.desktop().screen().rect().center() - self.rect().center())
            else:
                self.addDockWidget(dock_area, dock_wnd)
        else:
            self.addDockWidget(Qt.TopDockWidgetArea, dock_wnd)
            dock_wnd.setFloating(True)
            dock_wnd.setAllowedAreas(Qt.NoDockWidgetArea)
            dock_wnd.move(QApplication.desktop().screen().rect().center() - self.rect().center())

        dock_wnd.setWidget(window)
        if dock_float:
            dock_wnd.setFloating(True)
            # self.geometry().center() - dock_wnd.rect().center()
            # dock_wnd.move()
        if dock_show:
            dock_wnd.show()
        else:
            dock_wnd.hide()
        sub_window_data.dock_wnd = dock_wnd
class InteractiveConsolePlugin(Plugin):
    locals = None

    def __init__(self, main_window_plugin: MainWindowPlugin):
        super().__init__()

        self.main_window = main_window_plugin.main_window

        self.console_widget = InteractiveConsoleWidget()
        self.console_widget.command_entered.connect(self.on_command_entered)
        self.interactive_console = self.create_console()

        self.dock_widget = QDockWidget('Interactive Console')
        self.dock_widget.setWidget(self.console_widget)
        self.dock_widget.hide()

        self.shortcut = QShortcut(Qt.CTRL + Qt.Key_Greater, self.main_window)

    def _install(self):
        self.main_window.addDockWidget(Qt.BottomDockWidgetArea,
                                       self.dock_widget)
        self.shortcut.activated.connect(self.on_shortcut_activated)

    def _remove(self):
        self.shortcut.activated.disconnect(self.on_shortcut_activated)
        self.main_window.removeDockWidget(self.dock_widget)

        # Remove all created references (otherwise some plugins may not be deleted)
        self.interactive_console.reset_locals()

    def create_console(self):
        return InteractiveConsole(self.locals.copy(),
                                  self.console_widget.append_output)

    def reset_console(self):
        self.interactive_console = self.create_console()

    def on_command_entered(self, command_text):
        stdout = io.StringIO()
        with redirect_stdout(stdout):
            more_input_required = self.interactive_console.push(command_text)

        output_text = stdout.getvalue()
        if output_text.endswith(
                '\n'
        ):  # enter was redirected to stdout too, so we need to remove it
            output_text = output_text[:-1]
        if output_text:
            self.console_widget.append_output(output_text)
            print('InteractiveConsole >', output_text)

        self.console_widget.set_continue_input_prompt(more_input_required)

    def on_shortcut_activated(self):
        self.dock_widget.show()
        self.console_widget.focus_command_line()
示例#4
0
    def new_docked(self, widget, name, title, dock_area, hiden=False):
        dock = QDockWidget()
        dock.setWindowTitle(title)
        dock.setWidget(widget)

        if hiden:
            dock.hide()
        else:
            dock.show()

        self.main_window.addDockWidget(dock_area, dock)
        self.modules_dock[name] = dock

        return dock
示例#5
0
class Browser(Application):
    # pylint: disable=too-many-instance-attributes
    """The main browser"""
    url_scheme: QWebEngineUrlScheme
    bridge_initialized: bool
    dev_view: QWebEngineView
    dev_page: WebPage
    qdock: QDockWidget

    def __init__(self):
        super().__init__()
        self.init()
        # self.load()

    def init(self):
        """Initialize browser"""
        logger.debug("Initializing Browser Window")

        if web_greeter_config["config"]["greeter"]["debug_mode"]:
            os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = '12345'

        url_scheme = "web-greeter"
        self.url_scheme = QWebEngineUrlScheme(url_scheme.encode())
        self.url_scheme.setDefaultPort(QWebEngineUrlScheme.PortUnspecified)
        self.url_scheme.setFlags(QWebEngineUrlScheme.SecureScheme
                                 or QWebEngineUrlScheme.LocalScheme
                                 or QWebEngineUrlScheme.LocalAccessAllowed)
        QWebEngineUrlScheme.registerScheme(self.url_scheme)

        self.profile = QWebEngineProfile.defaultProfile()
        self.interceptor = QtUrlRequestInterceptor(url_scheme)
        self.url_scheme_handler = QtUrlSchemeHandler()

        self.view = QWebEngineView(parent=self.window)
        self.page = WebPage()
        self.view.setPage(self.page)
        self.page.setObjectName("WebG Page")
        self.view.setObjectName("WebG View")

        self.channel = QWebChannel(self.page)
        self.bridge_initialized = False

        self.profile.installUrlSchemeHandler(url_scheme.encode(),
                                             self.url_scheme_handler)

        self._initialize_page()

        if web_greeter_config["config"]["greeter"]["debug_mode"]:
            self._initialize_devtools()
        else:
            self.view.setContextMenuPolicy(Qt.PreventContextMenu)

        self._init_actions()
        if web_greeter_config["app"]["frame"]:
            self._init_menu_bar()
        else:
            self.window.setWindowFlags(self.window.windowFlags()
                                       | Qt.FramelessWindowHint)

        if web_greeter_config["config"]["greeter"]["secure_mode"]:
            if hasattr(QWebEngineProfile, "setUrlRequestInterceptor"):
                self.profile.setUrlRequestInterceptor(self.interceptor)
            else:  # Older Qt5 versions
                self.profile.setRequestInterceptor(self.interceptor)

        self.page.setBackgroundColor(QColor(0, 0, 0))
        self.window.setStyleSheet("""QMainWindow, QWebEngineView {
	                                background: #000000;
                                 }""")

        self.window.setCentralWidget(self.view)

        logger.debug("Browser Window created")

    def load(self):
        """Load theme and initialize bridge"""
        self.load_theme()

        self.bridge_objects = (self.greeter, self.greeter_config,
                               self.theme_utils)
        self.initialize_bridge_objects()
        self.load_script(':/_greeter/js/bundle.js', 'Web Greeter Bundle')

    def _initialize_devtools(self):
        self.dev_view = QWebEngineView(parent=self.window)
        self.dev_page = WebPage()
        self.dev_view.setPage(self.dev_page)
        self.page.setDevToolsPage(self.dev_page)
        self.dev_view.setObjectName("Devtools view")
        self.dev_page.setObjectName("Devtools page")

        self.dev_page.windowCloseRequested.connect(
            lambda: self.toggle_devtools_value(False))

        inspect_element_action = self.page.action(self.page.InspectElement)
        inspect_element_action.triggered.connect(
            lambda: self.toggle_devtools_value(True))

        self.qdock = QDockWidget()
        self.qdock.setWidget(self.dev_view)
        self.qdock.setFeatures(QDockWidget.DockWidgetMovable
                               or QDockWidget.DockWidgetClosable)

        self.window.addDockWidget(Qt.RightDockWidgetArea, self.qdock)
        self.qdock.hide()
        logger.debug("DevTools initialized")

    def toggle_devtools(self):
        """Toggle devtools"""
        if not web_greeter_config["config"]["greeter"]["debug_mode"]:
            return
        self.toggle_devtools_value(not self.qdock.isVisible())

    def toggle_devtools_value(self, value: bool):
        """Toggle devtools by value"""
        if not web_greeter_config["config"]["greeter"]["debug_mode"]:
            return

        if value:
            self.qdock.show()
            self.dev_view.setFocus()
        else:
            self.qdock.hide()
            self.view.setFocus()

    def _init_actions(self):
        """Init browser actions"""
        self.exit_action = QAction(QIcon("exit.png"), "&Quit", self.window)
        self.exit_action.setShortcut("Ctrl+Q")
        self.exit_action.setStatusTip("Exit application")
        self.exit_action.triggered.connect(qApp.quit)

        self.toggle_dev_action = QAction("Toggle Developer Tools", self.window)
        self.toggle_dev_action.setShortcut("Ctrl+Shift+I")
        self.toggle_dev_action.triggered.connect(self.toggle_devtools)

        self.fullscreen_action = QAction("Toggle Fullscreen", self.window)
        self.fullscreen_action.setShortcut("F11")
        self.fullscreen_action.triggered.connect(
            lambda: self.toggle_fullscreen(not self.window.isFullScreen()))

        self.inc_zoom_action = QAction("Zoom In", self.window)
        self.inc_zoom_action.setShortcut("Ctrl++")
        self.inc_zoom_action.triggered.connect(self._inc_zoom)
        self.dec_zoom_action = QAction("Zoom Out", self.window)
        self.dec_zoom_action.setShortcut("Ctrl+-")
        self.dec_zoom_action.triggered.connect(self._dec_zoom)
        self.reset_zoom_action = QAction("Actual Size", self.window)
        self.reset_zoom_action.setShortcut("Ctrl+0")
        self.reset_zoom_action.triggered.connect(self._reset_zoom)

        self.window.addAction(self.exit_action)
        self.window.addAction(self.toggle_dev_action)
        self.window.addAction(self.fullscreen_action)
        self.window.addAction(self.inc_zoom_action)
        self.window.addAction(self.dec_zoom_action)
        self.window.addAction(self.reset_zoom_action)

    def _inc_zoom(self):
        if self.view.hasFocus():
            self.page.increaseZoom()
        else:
            self.dev_page.increaseZoom()

    def _dec_zoom(self):
        if self.view.hasFocus():
            self.page.decreaseZoom()
        else:
            self.dev_page.decreaseZoom()

    def _reset_zoom(self):
        if self.view.hasFocus():
            self.page.setZoomFactor(1)
        else:
            self.dev_page.setZoomFactor(1)

    def _init_menu_bar(self):
        minimize_action = QAction("Minimize", self.window)
        minimize_action.setShortcut("Ctrl+M")
        minimize_action.triggered.connect(self.window.showMinimized)
        close_action = QAction("Close", self.window)
        close_action.setShortcut("Ctrl+W")
        close_action.triggered.connect(self.window.close)

        self.page.action(
            self.page.ReloadAndBypassCache).setText("Force Reload")

        self.page.fullScreenRequested.connect(self.accept_fullscreen)

        self.menu_bar = QMenuBar()

        file_menu = self.menu_bar.addMenu("&File")
        file_menu.addAction(self.exit_action)

        edit_menu = self.menu_bar.addMenu("&Edit")
        edit_menu.addAction(self.page.action(self.page.Undo))
        edit_menu.addAction(self.page.action(self.page.Redo))
        edit_menu.addSeparator()
        edit_menu.addAction(self.page.action(self.page.Cut))
        edit_menu.addAction(self.page.action(self.page.Copy))
        edit_menu.addAction(self.page.action(self.page.Paste))
        edit_menu.addSeparator()
        edit_menu.addAction(self.page.action(self.page.SelectAll))

        view_menu = self.menu_bar.addMenu("&View")
        view_menu.addAction(self.page.action(self.page.Reload))
        view_menu.addAction(self.page.action(self.page.ReloadAndBypassCache))
        view_menu.addAction(self.toggle_dev_action)
        view_menu.addSeparator()
        view_menu.addAction(self.reset_zoom_action)
        view_menu.addAction(self.inc_zoom_action)
        view_menu.addAction(self.dec_zoom_action)
        view_menu.addSeparator()
        view_menu.addAction(self.fullscreen_action)

        window_menu = self.menu_bar.addMenu("&Window")
        window_menu.addAction(minimize_action)
        window_menu.addAction(close_action)

        # help_menu = menu_bar.addMenu("&Help")

        self.window.setMenuBar(self.menu_bar)

    def accept_fullscreen(self, request):
        """Accepts fullscreen requests"""
        if web_greeter_config["config"]["greeter"]["debug_mode"]:
            request.reject()
            return
        if request.toggleOn():
            self.toggle_fullscreen(True)
        else:
            self.toggle_fullscreen(False)
        request.accept()

    def toggle_fullscreen(self, value: bool):
        """Toggle fullscreen"""
        if not web_greeter_config["config"]["greeter"]["debug_mode"]:
            return
        if value:
            state = self.states["FULLSCREEN"]
            self.window.setWindowFlags(self.window.windowFlags()
                                       or Qt.FramelessWindowHint)
            self.menu_bar.setParent(None)
            self.window.setMenuBar(None)
        else:
            state = self.states["NORMAL"]
            self.window.setWindowFlags(self.window.windowFlags()
                                       or not Qt.FramelessWindowHint)
            self.window.setMenuBar(self.menu_bar)
        try:
            self.window.windowHandle().setWindowState(state)
        except (AttributeError, TypeError):
            self.window.setWindowState(state)

    def _initialize_page(self):
        page_settings = self.page.settings().globalSettings()

        if not web_greeter_config["config"]["greeter"]["secure_mode"]:
            ENABLED_SETTINGS.append('LocalContentCanAccessRemoteUrls')
        else:
            DISABLED_SETTINGS.append('LocalContentCanAccessRemoteUrls')

        for setting in DISABLED_SETTINGS:
            try:
                page_settings.setAttribute(
                    getattr(QWebEngineSettings, setting), False)
            except AttributeError:
                pass

        for setting in ENABLED_SETTINGS:
            try:
                page_settings.setAttribute(
                    getattr(QWebEngineSettings, setting), True)
            except AttributeError:
                pass

        self.page.setView(self.view)

    def load_theme(self):
        """Load theme"""
        theme = web_greeter_config["config"]["greeter"]["theme"]
        dir_t = "/usr/share/web-greeter/themes/"
        path_to_theme = os.path.join(dir_t, theme, "index.html")
        def_theme = "gruvbox"

        if theme.startswith("/"):
            path_to_theme = theme
        elif theme.__contains__(".") or theme.__contains__("/"):
            path_to_theme = os.path.join(os.getcwd(), theme)
            path_to_theme = os.path.realpath(path_to_theme)

        if not path_to_theme.endswith(".html"):
            path_to_theme = os.path.join(path_to_theme, "index.html")

        if not os.path.exists(path_to_theme):
            print("Path does not exists", path_to_theme)
            path_to_theme = os.path.join(dir_t, def_theme, "index.html")

        web_greeter_config["config"]["greeter"]["theme"] = path_to_theme

        url = QUrl(f"web-greeter://app/{path_to_theme}")
        self.page.load(url)

        logger.debug("Theme loaded")

    @staticmethod
    def _create_webengine_script(path: Url, name: str) -> QWebEngineScript:
        script = QWebEngineScript()
        script_file = QFile(path)

        # print(script_file, path)

        if script_file.open(QFile.ReadOnly):
            script_string = str(script_file.readAll(), 'utf-8')

            script.setInjectionPoint(QWebEngineScript.DocumentCreation)
            script.setName(name)
            script.setWorldId(QWebEngineScript.MainWorld)
            script.setSourceCode(script_string)
            # print(script_string)

        return script

    def _get_channel_api_script(self) -> QWebEngineScript:
        return self._create_webengine_script(':/qtwebchannel/qwebchannel.js',
                                             'QWebChannel API')

    def _init_bridge_channel(self) -> None:
        self.page.setWebChannel(self.channel)
        self.bridge_initialized = True

    def initialize_bridge_objects(self) -> None:
        """Initialize bridge objects :D"""
        if not self.bridge_initialized:
            self._init_bridge_channel()
        registered_objects = self.channel.registeredObjects()

        for obj in self.bridge_objects:
            if obj not in registered_objects:
                # pylint: disable=protected-access
                self.channel.registerObject(obj._name, obj)
                # print("Registered", obj._name)

    def load_script(self, path: Url, name: str):
        """Loads a script in page"""
        qt_api = self._get_channel_api_script()
        qt_api_source = qt_api.sourceCode()
        script = self._create_webengine_script(path, name)
        script.setSourceCode(qt_api_source + "\n" + script.sourceCode())
        self.page.scripts().insert(script)
示例#6
0
class Kettle(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.filename = "untitled"

    def save_file(self):
        name = self.filename
        if not self.filename or self.filename == "untitled":
            name = QFileDialog.getSaveFileName(self, 'Save File')[0]
        file = open(name, 'wt')
        save_text = self.current_editor.toPlainText()
        file.write(save_text)
        file.close()
        self.current_editor.set_change_name(self.tab_widget, False)

    def save_file_as(self):
        name = QFileDialog.getSaveFileName(self, 'Save File')[0]
        file = open(name, 'wt')
        save_text = self.current_editor.toPlainText()
        file.write(save_text)
        file.close()
        self.current_editor.set_change_name(self.tab_widget, False)

    def open_file(self):
        name = QFileDialog.getOpenFileName(self, 'Open File')
        self.filename = name[0]
        file_image_type = imghdr.what(name[0])
        if file_image_type is not None:
            self.open_image(self.filename)
        else:
            file = open(name[0], 'r', encoding='utf-8', errors='ignore')

            with file:
                self.new_document(title=os.path.basename(self.filename))
                self.current_editor.setPlainText(file.read())
                self.current_editor.set_change_name(self.tab_widget, False)

    def open_image(self, filename):
        label = QLabel(self)
        pixmap = QPixmap(filename)
        label.setPixmap(pixmap)
        self.tab_widget.addTab(label, filename)
        self.tab_widget.setCurrentWidget(label)

    def run(self):
        run = subprocess.run([sys.executable, self.filename],
                             stdout=subprocess.PIPE)
        print(run.stdout)

    def view_projectview(self, state):
        if state:
            self.dock_widget.show()
            config.update_config('view', 'view_projectview', 'True')
        else:
            self.dock_widget.hide()
            config.update_config('view', 'view_projectview', 'False')

    def load_project_structure(self, startpath, tree):
        for element in os.listdir(startpath):
            path_info = startpath + "/" + element
            parent_itm = QTreeWidgetItem(
                tree,
                [os.path.basename(element),
                 os.path.join(startpath, element)])
            if os.path.isdir(path_info):
                self.load_project_structure(path_info, parent_itm)
                parent_itm.setIcon(0, QIcon(themes.get_icon('folder.png')))
            else:
                parent_itm.setIcon(0, QIcon(themes.get_icon('file.png')))
            if not utils.str2bool(
                    config.get_setting('General', 'show_hidden_items',
                                       'False')):
                if element.startswith('.'):
                    parent_itm.setHidden(True)

    def tree_clicked(self):
        self.filename = self.treeView.selectedItems()[0].text(1)
        if os.path.isdir(self.treeView.selectedItems()[0].text(1)):
            print("This is not a file, is a directory.")
        else:
            try:
                file_image_type = imghdr.what(
                    self.treeView.selectedItems()[0].text(1))
                if file_image_type is not None:
                    self.open_image(self.treeView.selectedItems()[0].text(1))
                else:
                    file = open(self.treeView.selectedItems()[0].text(1),
                                'r',
                                encoding='utf-8',
                                errors='ignore')

                    with file:
                        text = file.read()
                        self.new_document(title=os.path.basename(
                            self.treeView.selectedItems()[0].text(1)))
                        self.current_editor.setPlainText(text)
                        self.current_editor.set_change_name(
                            self.tab_widget, False)
            except FileNotFoundError as error:
                print("No such file found : " + str(error))
                QMessageBox.question(self, 'Error',
                                     'Error occured : ' + str(error),
                                     QMessageBox.Close)
        if self.filename.endswith('.html'):
            html_preview = HTMLPreview(self.filename, self.current_editor)
            self.addDockWidget(Qt.RightDockWidgetArea, html_preview)
        elif self.filename.endswith('.md'):
            markdown_preview = MarkdownPreview(self.filename,
                                               self.current_editor)
            self.addDockWidget(Qt.RightDockWidgetArea, markdown_preview)

    def open_prof(self):
        proj_folder = str(
            QFileDialog.getExistingDirectory(self, 'Select Directory'))
        self.treeView.clear()
        self.load_project_structure(proj_folder, self.treeView)
        self.treeView.setHeaderHidden(False)
        self.treeView.setHeaderLabel(
            os.path.basename(os.path.normpath(proj_folder)))
        config.update_config('General', 'last_opened_project', proj_folder)
        self.project_folder = proj_folder

    def open_settings(self):
        settings = Settings(self, themes)
        settings.show()

    def open_github_link(self):
        url = QUrl('https://github.com/Mozzo1000/kettle/')
        if not QDesktopServices.openUrl(url):
            QMessageBox.warning(self, 'Open URL', 'Could not open url')

    def open_about(self):
        about = About(self)
        about.show()

    def create_editor(self):
        text_editor = CodeEditor(config, themes)
        text_editor.textChanged.connect(self.on_text_changed)
        return text_editor

    def on_text_changed(self):
        self.current_editor.set_change_name(self.tab_widget)

    def remove_editor(self, index):
        if index is False:
            index = self.tab_widget.currentIndex()
        self.tab_widget.removeTab(index)
        if index < len(self.editors):
            del self.editors[index]

    def change_text_editor(self, index):
        if index < len(self.editors):
            self.current_editor = self.editors[index]

    def new_document(self, checked=False, title="Untitled"):
        self.current_editor = self.create_editor()
        self.current_editor.cursorPositionChanged.connect(
            self.statusbar.status_line_position)
        self.editors.append(self.current_editor)
        self.tab_widget.addTab(self.current_editor,
                               str(title) + " - " + str(len(self.editors)))
        self.tab_widget.setCurrentWidget(self.current_editor)

    def open_notes_graph(self):
        notes_graph = NotesGraph(self)
        self.addDockWidget(Qt.BottomDockWidgetArea, notes_graph)

    def create_notes_project(self):
        notes_project = CreateNotesProject(self)
        notes_project.show()

    def init_ui(self):
        self.resize(800, 600)
        self.setWindowTitle('Kettle')

        self.current_editor = self.create_editor()
        self.editors = []

        self.central_widget = QWidget(self)
        QFontDatabase.addApplicationFont('../assets/font/Monoid-Regular.ttf')

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)
        #self.statusbar = self.statusBar()
        self.statusbar = Statusbar(self)
        self.setStatusBar(self.statusbar)

        self.horizontal_layoutW = QWidget(self.central_widget)
        self.splitter = QSplitter(self.central_widget)

        self.tab_widget = QTabWidget(self.central_widget)
        self.tab_widget.setTabsClosable(True)
        self.tab_widget.currentChanged.connect(self.change_text_editor)
        self.tab_widget.tabCloseRequested.connect(self.remove_editor)
        self.new_document()

        self.dock_widget = QDockWidget('Project View', self.central_widget)

        print(self.sizeHint())
        self.horizontal_layout = QHBoxLayout(self.central_widget)
        self.horizontal_layout.setSizeConstraint(QLayout.SetMaximumSize)
        self.treeView = QTreeWidget(self.central_widget)
        self.treeView.header().hide()
        self.treeView.itemDoubleClicked.connect(self.tree_clicked)
        self.dock_widget.setWidget(self.treeView)
        self.splitter.addWidget(self.tab_widget)

        self.horizontal_layout.addWidget(self.splitter)
        self.setCentralWidget(self.central_widget)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_widget)
        if utils.str2bool(
                config.get_setting('view', 'view_projectview', 'True')):
            self.dock_widget.show()
        else:
            self.dock_widget.hide()

        self.statusbar.showMessage('Line 0 | Column 0')
        self.splitter.setSizes([5, 300])

        if config.get_setting('General', 'last_opened_project'):
            self.load_project_structure(
                config.get_setting('General', 'last_opened_project'),
                self.treeView)
            self.project_folder = config.get_setting('General',
                                                     'last_opened_project')

        exit_action = QAction(QIcon('exit.png'), '&Exit', self)
        exit_action.setShortcut('Ctrl+Q')
        exit_action.setStatusTip('Exit application')
        exit_action.triggered.connect(qApp.quit)

        new_action = QAction('New', self)
        new_action.triggered.connect(self.new_document)
        new_action.setShortcut('Ctrl+N')

        save_action = QAction('Save', self)
        save_action.triggered.connect(self.save_file)
        save_action.setShortcut('Ctrl+S')

        save_as_action = QAction("Save as..", self)
        save_as_action.triggered.connect(self.save_file_as)
        save_as_action.setShortcut('Ctrl+Alt+S')

        open_action = QAction('Open', self)
        open_action.triggered.connect(self.open_file)
        open_action.setShortcut('Ctrl+O')

        open_proj_action = QAction('Open Project', self)
        open_proj_action.triggered.connect(self.open_prof)

        settings_action = QAction('Settings', self)
        settings_action.triggered.connect(self.open_settings)

        undo_action = QAction('Undo', self)
        undo_action.triggered.connect(self.current_editor.undo)
        undo_action.setShortcut('Ctrl+Z')

        redo_action = QAction('Redo', self)
        redo_action.triggered.connect(self.current_editor.redo)
        redo_action.setShortcut('Ctrl+Y')

        cut_action = QAction('Cut', self)
        cut_action.triggered.connect(self.current_editor.cut)
        cut_action.setShortcut('Ctrl+X')

        copy_action = QAction('Copy', self)
        copy_action.triggered.connect(self.current_editor.copy)
        copy_action.setShortcut('Ctrl+C')

        paste_action = QAction('Paste', self)
        paste_action.triggered.connect(self.current_editor.paste)
        paste_action.setShortcut('Ctrl+V')

        select_all_action = QAction('Select all', self)
        select_all_action.triggered.connect(self.current_editor.selectAll)
        select_all_action.setShortcut('Ctrl+A')

        run_action = QAction('Run', self)
        run_action.triggered.connect(self.run)
        run_action.setShortcut('Ctrl+SPACE')

        view_status_action = QAction('View statusbar', self, checkable=True)
        view_status_action.setChecked(
            utils.str2bool(config.get_setting('view', 'view_statusbar')))
        view_status_action.triggered.connect(self.statusbar.view_status)
        view_projectview_action = QAction('View project view',
                                          self,
                                          checkable=True)
        view_projectview_action.setChecked(
            utils.str2bool(
                config.get_setting('view', 'view_projectview', 'True')))
        view_projectview_action.triggered.connect(self.view_projectview)

        github_link_action = QAction('Github', self)
        github_link_action.triggered.connect(self.open_github_link)

        about_action = QAction('About', self)
        about_action.triggered.connect(self.open_about)

        close_current_editor_action = QAction('Close current file', self)
        close_current_editor_action.triggered.connect(self.remove_editor)
        close_current_editor_action.setShortcut('Ctrl+W')

        open_notes_graph_action = QAction('Open graph', self)
        open_notes_graph_action.triggered.connect(self.open_notes_graph)

        create_new_notes_project_action = QAction('Create notes project', self)
        create_new_notes_project_action.triggered.connect(
            self.create_notes_project)

        menubar = self.menuBar()
        notes_menu = QMenu('Notes', self)

        file_menu = menubar.addMenu('&File')
        edit_menu = menubar.addMenu('&Edit')
        run_menu = menubar.addMenu('&Run')
        view_menu = menubar.addMenu('&View')
        help_menu = menubar.addMenu('&Help')

        notes_menu.addAction(open_notes_graph_action)
        notes_menu.addAction(create_new_notes_project_action)

        file_menu.addAction(new_action)
        file_menu.addAction(open_action)
        file_menu.addAction(open_proj_action)
        file_menu.addAction(save_action)
        file_menu.addAction(save_as_action)
        file_menu.addAction(close_current_editor_action)
        file_menu.addAction(settings_action)
        file_menu.addAction(exit_action)
        file_menu.addMenu(notes_menu)

        edit_menu.addAction(undo_action)
        edit_menu.addAction(redo_action)
        edit_menu.addAction(cut_action)
        edit_menu.addAction(copy_action)
        edit_menu.addAction(paste_action)

        edit_menu.addAction(select_all_action)

        run_menu.addAction(run_action)

        view_menu.addAction(view_status_action)
        view_menu.addAction(view_projectview_action)

        help_menu.addAction(github_link_action)
        help_menu.addAction(about_action)

        self.showMaximized()
        self.show()
示例#7
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)

        self.centralwidget.hide()

        self.parser = argparse.ArgumentParser("playground")
        self.parser.add_argument("-d", "--data-dir", type=str, help="data dir")
        self.parser.add_argument("-a", "--console-address", type=str, help="console address", default='localhost')
        self.parser.add_argument("-p", "--console-port", type=int, help="console port", default=2222)
        self.args = self.parser.parse_args()

        self.data_dir = self.args.data_dir
        self.console_port = self.args.console_port
        self.console_address = self.args.console_address

        self.project = CetechProject()

        self.api = QtConsoleAPI(self.console_address, self.console_port)

        self.setTabPosition(Qt.AllDockWidgetAreas, QTabWidget.North)

        self.script_editor_widget = ScriptEditor(project_manager=self.project, api=self.api)
        self.script_editor_dock_widget = QDockWidget(self)
        self.script_editor_dock_widget.setWindowTitle("Script editor")
        self.script_editor_dock_widget.hide()
        self.script_editor_dock_widget.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self.script_editor_dock_widget.setWidget(self.script_editor_widget)
        self.addDockWidget(Qt.TopDockWidgetArea, self.script_editor_dock_widget)

        self.log_widget = LogWidget(self.api, self.script_editor_widget)
        self.log_dock_widget = QDockWidget(self)
        self.log_dock_widget.hide()
        self.log_dock_widget.setWindowTitle("Log")
        self.log_dock_widget.setWidget(self.log_widget)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.log_dock_widget)

        self.assetb_widget = AssetBrowser()
        self.assetb_dock_widget = QDockWidget(self)
        self.assetb_dock_widget.hide()
        self.assetb_dock_widget.setWindowTitle("Asset browser")
        self.assetb_dock_widget.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self.assetb_dock_widget.setWidget(self.assetb_widget)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.assetb_dock_widget)

        self.recorded_event_widget = RecordEventWidget(api=self.api)
        self.recorded_event_dock_widget = QDockWidget(self)
        self.recorded_event_dock_widget.setWindowTitle("Recorded events")
        self.recorded_event_dock_widget.hide()
        self.recorded_event_dock_widget.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self.recorded_event_dock_widget.setWidget(self.recorded_event_widget)
        self.addDockWidget(Qt.RightDockWidgetArea, self.recorded_event_dock_widget)

        #TODO bug #114 workaround. Disable create sub engine...
        if platform.system().lower() != 'darwin':
            self.ogl_widget = CetechWidget(self, self.api)
            self.ogl_dock = QDockWidget(self)
            self.ogl_dock.hide()
            self.ogl_dock.setWidget(self.ogl_widget)
            self.addDockWidget(Qt.TopDockWidgetArea, self.ogl_dock)

        self.tabifyDockWidget(self.assetb_dock_widget, self.log_dock_widget)

        self.assetb_widget.asset_clicked.connect(self.open_asset)

        self.file_watch = QFileSystemWatcher(self)
        self.file_watch.fileChanged.connect(self.file_changed)
        self.file_watch.directoryChanged.connect(self.dir_changed)

        self.build_file_watch = QFileSystemWatcher(self)
        self.build_file_watch.fileChanged.connect(self.build_file_changed)
        self.build_file_watch.directoryChanged.connect(self.build_dir_changed)

    def open_asset(self, path, ext):
        if self.script_editor_widget.support_ext(ext):
            self.script_editor_widget.open_file(path)
            self.script_editor_dock_widget.show()
            self.script_editor_dock_widget.focusWidget()

    def open_project(self, name, dir):
        self.project.open_project(name, dir)

        # self.project.run_cetech(build_type=CetechProject.BUILD_DEBUG, compile=True, continu=True, daemon=True)

        if platform.system().lower() == 'darwin':
            wid = None
        else:
            wid = self.ogl_widget.winId()

        self.project.run_cetech(build_type=CetechProject.BUILD_DEBUG, compile_=True, continue_=True,
                                wid=wid)


        self.api.start(QThread.LowPriority)

        self.assetb_widget.open_project(self.project.project_dir)
        self.assetb_dock_widget.show()
        self.log_dock_widget.show()

        #TODO bug #114 workaround. Disable create sub engine...
        if platform.system().lower() != 'darwin':
            self.ogl_dock.show()

        self.watch_project_dir()

    def watch_project_dir(self):
        files = self.file_watch.files()
        directories = self.file_watch.directories()

        if len(files):
            self.file_watch.removePaths(files)

        if len(directories):
            self.file_watch.removePaths(directories)

        files = self.build_file_watch.files()
        directories = self.build_file_watch.directories()

        if len(files):
            self.build_file_watch.removePaths(files)

        if len(directories):
            self.build_file_watch.removePaths(directories)

        files = []
        it = QDirIterator(self.project.source_dir, QDirIterator.Subdirectories)
        while it.hasNext():
            files.append(it.next())

        self.file_watch.addPaths(files)

        files = []
        it = QDirIterator(self.project.build_dir, QDirIterator.Subdirectories)
        while it.hasNext():
            files.append(it.next())

        self.build_file_watch.addPaths(files)

    def file_changed(self, path):
        self.api.compile_all()

    def dir_changed(self, path):
        self.watch_project_dir()

    def build_file_changed(self, path):
        self.api.autocomplete_list()

    def build_dir_changed(self, path):
        pass

    def open_script_editor(self):
        self.script_editor_dock_widget.show()

    def open_recorded_events(self):
        self.recorded_event_dock_widget.show()

    def closeEvent(self, evnt):
        self.api.disconnect()

        self.project.killall_process()

        self.statusbar.showMessage("Disconnecting ...")

        while self.api.connected:
            self.api.tick()

        self.statusbar.showMessage("Disconnected")

        evnt.accept()
示例#8
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.chunk_directory = Directory(
            "CHUNK", QIcon(Assets.get_asset_path("document_a4_locked.png")),
            None)
        self.mod_directory = Directory(
            "MOD", QIcon(Assets.get_asset_path("document_a4.png")), None)
        self.workspace = Workspace([self.mod_directory, self.chunk_directory],
                                   parent=self)
        self.workspace.fileOpened.connect(self.handle_workspace_file_opened)
        self.workspace.fileClosed.connect(self.handle_workspace_file_closed)
        self.workspace.fileActivated.connect(
            self.handle_workspace_file_activated)
        self.workspace.fileLoadError.connect(
            self.handle_workspace_file_load_error)
        self.init_actions()
        self.init_menu_bar()
        self.init_toolbar()
        self.setStatusBar(QStatusBar())
        self.setWindowTitle("MHW-Editor-Suite")
        self.init_file_tree(self.chunk_directory,
                            "Chunk directory",
                            self.open_chunk_directory_action,
                            filtered=True)
        self.init_file_tree(self.mod_directory, "Mod directory",
                            self.open_mod_directory_action)
        self.init_help()
        self.setCentralWidget(self.init_editor_tabs())
        self.load_settings()

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

    def load_settings(self):
        self.settings = AppSettings()
        with self.settings.main_window() as group:
            size = group.get("size", QSize(1000, 800))
            position = group.get("position", QPoint(300, 300))
        with self.settings.application() as group:
            chunk_directory = group.get("chunk_directory", None)
            mod_directory = group.get("mod_directory", None)
            lang = group.get("lang", None)
        with self.settings.import_export() as group:
            self.import_export_default_attrs = {
                key: group.get(key, "").split(";")
                for key in group.childKeys()
            }
        # apply settings
        self.resize(size)
        self.move(position)
        if chunk_directory:
            self.chunk_directory.set_path(chunk_directory)
        if mod_directory:
            self.mod_directory.set_path(mod_directory)
        if lang:
            self.handle_set_lang_action(lang)

    def write_settings(self):
        with self.settings.main_window() as group:
            group["size"] = self.size()
            group["position"] = self.pos()
        with self.settings.application() as group:
            group["chunk_directory"] = self.chunk_directory.path
            group["mod_directory"] = self.mod_directory.path
            group["lang"] = FilePluginRegistry.lang
        with self.settings.import_export() as group:
            for key, value in self.import_export_default_attrs.items():
                group[key] = ";".join(value)

    def get_icon(self, name):
        return self.style().standardIcon(name)

    def init_actions(self):
        self.open_chunk_directory_action = create_action(
            self.get_icon(QStyle.SP_DirOpenIcon), "Open chunk_directory ...",
            self.handle_open_chunk_directory, None)
        self.open_mod_directory_action = create_action(
            self.get_icon(QStyle.SP_DirOpenIcon), "Open mod directory ...",
            self.handle_open_mod_directory, QKeySequence.Open)
        self.save_file_action = create_action(
            self.get_icon(QStyle.SP_DriveHDIcon), "Save file",
            self.handle_save_file_action, QKeySequence.Save)
        self.save_file_action.setDisabled(True)
        self.export_action = create_action(self.get_icon(QStyle.SP_FileIcon),
                                           "Export file ...",
                                           self.handle_export_file_action)
        self.export_action.setDisabled(True)
        self.import_action = create_action(self.get_icon(QStyle.SP_FileIcon),
                                           "Import file ...",
                                           self.handle_import_file_action)
        self.import_action.setDisabled(True)
        self.help_action = create_action(None, "Show help",
                                         self.handle_show_help_action)
        self.about_action = create_action(None, "About",
                                          self.handle_about_action)
        self.lang_actions = {
            lang: create_action(None,
                                name,
                                partial(self.handle_set_lang_action, lang),
                                checkable=True)
            for lang, name in LANG
        }
        self.quick_access_actions = [
            create_action(
                None, title,
                partial(self.workspace.open_file_any_dir, file_rel_path))
            for title, file_rel_path in QUICK_ACCESS_ITEMS
        ]

    def init_menu_bar(self):
        menu_bar = self.menuBar()
        # file menu
        file_menu = menu_bar.addMenu("File")
        file_menu.insertAction(None, self.open_chunk_directory_action)
        file_menu.insertAction(None, self.open_mod_directory_action)
        file_menu.insertAction(None, self.export_action)
        file_menu.insertAction(None, self.import_action)
        file_menu.insertAction(None, self.save_file_action)

        quick_access_menu = menu_bar.addMenu("Quick Access")
        for action in self.quick_access_actions:
            quick_access_menu.insertAction(None, action)

        # lang menu
        lang_menu = menu_bar.addMenu("Language")
        for action in self.lang_actions.values():
            lang_menu.insertAction(None, action)

        # help menu
        help_menu = menu_bar.addMenu("Help")
        help_menu.insertAction(None, self.help_action)
        help_menu.insertAction(None, self.about_action)

    def init_toolbar(self):
        toolbar = self.addToolBar("Main")
        toolbar.setIconSize(QSize(16, 16))
        toolbar.setFloatable(False)
        toolbar.setMovable(False)
        toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        toolbar.insertAction(None, self.open_mod_directory_action)
        toolbar.insertAction(None, self.save_file_action)

    def init_file_tree(self, directory, title, action, filtered=False):
        widget = DirectoryDockWidget(directory, filtered=filtered, parent=self)
        widget.path_label.addAction(action, QLineEdit.LeadingPosition)
        widget.tree_view.activated.connect(
            partial(self.handle_directory_tree_view_activated, directory))
        dock = QDockWidget(title, self)
        dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        dock.setFeatures(QDockWidget.DockWidgetMovable)
        dock.setWidget(widget)
        self.addDockWidget(Qt.LeftDockWidgetArea, dock)

    def init_help(self):
        self.help_widget = HelpWidget(self)
        self.help_widget_dock = QDockWidget("Help", self)
        self.help_widget_dock.setAllowedAreas(Qt.LeftDockWidgetArea
                                              | Qt.RightDockWidgetArea)
        self.help_widget_dock.setFeatures(QDockWidget.DockWidgetMovable)
        self.help_widget_dock.setWidget(self.help_widget)
        self.addDockWidget(Qt.RightDockWidgetArea, self.help_widget_dock)
        self.help_widget_dock.hide()

    def handle_show_help_action(self):
        if self.help_widget_dock.isVisible():
            self.help_widget_dock.hide()
        else:
            self.help_widget_dock.show()

    def handle_directory_tree_view_activated(self, directory,
                                             qindex: QModelIndex):
        if qindex.model().isDir(qindex):
            return
        file_path = qindex.model().filePath(qindex)
        self.workspace.open_file(directory, file_path)

    def init_editor_tabs(self):
        self.editor_tabs = QTabWidget()
        self.editor_tabs.setDocumentMode(True)
        self.editor_tabs.setTabsClosable(True)
        self.editor_tabs.tabCloseRequested.connect(
            self.handle_editor_tab_close_requested)
        return self.editor_tabs

    def handle_workspace_file_opened(self, path, rel_path):
        ws_file = self.workspace.files[path]
        editor_view = EditorView.factory(self.editor_tabs, ws_file)
        editor_view.setObjectName(path)
        self.editor_tabs.addTab(editor_view, ws_file.directory.file_icon,
                                f"{ws_file.directory.name}: {rel_path}")
        self.editor_tabs.setCurrentWidget(editor_view)
        self.save_file_action.setDisabled(False)
        self.export_action.setDisabled(False)
        self.import_action.setDisabled(False)

    def handle_workspace_file_activated(self, path, rel_path):
        widget = self.editor_tabs.findChild(QWidget, path)
        self.editor_tabs.setCurrentWidget(widget)

    def handle_workspace_file_closed(self, path, rel_path):
        widget = self.editor_tabs.findChild(QWidget, path)
        widget.deleteLater()
        has_no_files_open = not self.workspace.files
        self.save_file_action.setDisabled(has_no_files_open)
        self.export_action.setDisabled(has_no_files_open)
        self.import_action.setDisabled(has_no_files_open)

    def handle_workspace_file_load_error(self, path, rel_path, error):
        QMessageBox.warning(self, f"Error loading file `{rel_path}`",
                            f"Error while loading\n{path}:\n\n{error}",
                            QMessageBox.Ok, QMessageBox.Ok)

    def handle_editor_tab_close_requested(self, tab_index):
        editor_view = self.editor_tabs.widget(tab_index)
        self.workspace.close_file(editor_view.workspace_file)

    def handle_open_chunk_directory(self):
        path = QFileDialog.getExistingDirectory(parent=self,
                                                caption="Open chunk directory")
        if path:
            self.chunk_directory.set_path(os.path.normpath(path))

    def handle_open_mod_directory(self):
        path = QFileDialog.getExistingDirectory(parent=self,
                                                caption="Open mod directory")
        if path:
            self.mod_directory.set_path(os.path.normpath(path))

    def handle_save_file_action(self):
        main_ws_file = self.get_current_workspace_file()
        for ws_file in main_ws_file.get_files_modified():
            if ws_file.directory is self.chunk_directory:
                if self.mod_directory.is_valid:
                    self.transfer_file_to_mod_workspace(
                        ws_file, ws_file is main_ws_file)
                else:
                    self.save_base_content_file(ws_file)
            else:
                with show_error_dialog(self, "Error writing file"):
                    self.save_workspace_file(ws_file)

    def handle_export_file_action(self):
        ws_file = self.get_current_workspace_file()
        plugin = FilePluginRegistry.get_plugin(ws_file.abs_path)
        fields = plugin.data_factory.EntryFactory.fields()
        data = [it.as_dict() for it in ws_file.data.entries]
        dialog = ExportDialog.init(self, data, fields,
                                   plugin.import_export.get("safe_attrs"))
        dialog.open()

    def handle_import_file_action(self):
        ws_file = self.get_current_workspace_file()
        plugin = FilePluginRegistry.get_plugin(ws_file.abs_path)
        fields = plugin.data_factory.EntryFactory.fields()
        dialog = ImportDialog.init(self,
                                   fields,
                                   plugin.import_export.get("safe_attrs"),
                                   as_list=True)
        if dialog:
            dialog.import_accepted.connect(self.handle_import_accepted)
            dialog.open()

    def handle_import_accepted(self, import_data):
        ws_file = self.get_current_workspace_file()
        num_items = min(len(import_data), len(ws_file.data))
        for idx in range(num_items):
            ws_file.data[idx].update(import_data[idx])
        self.statusBar().showMessage(
            f"Import contains {len(import_data)} items. "
            f"Model contains {len(ws_file.data)} items. "
            f"Imported {num_items}.", STATUSBAR_MESSAGE_TIMEOUT)

    def handle_set_lang_action(self, lang):
        FilePluginRegistry.lang = lang
        for act in self.lang_actions.values():
            act.setChecked(False)
        self.lang_actions[lang].setChecked(True)

    def get_current_workspace_file(self):
        editor = self.editor_tabs.currentWidget()
        return editor.workspace_file

    def save_base_content_file(self, ws_file):
        result = QMessageBox.question(
            self, "Save base content file?",
            "Do you really want to update this chunk file?",
            QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Cancel)
        if result == QMessageBox.Ok:
            with show_error_dialog(self, "Error writing file"):
                self.save_workspace_file(ws_file)

    def transfer_file_to_mod_workspace(self, ws_file, reopen=False):
        mod_abs_path, exists = self.mod_directory.get_child_path(
            ws_file.rel_path)
        if not exists:
            return self.transfer_file(ws_file, self.mod_directory, reopen)

        result = QMessageBox.question(
            self, "File exists, overwrite?",
            f"File '{ws_file.rel_path}' already found in mod directory, overwrite?",
            QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
        if result == QMessageBox.Ok:
            self.transfer_file(ws_file, self.mod_directory, reopen)

    def transfer_file(self, ws_file, target_directory, reopen=False):
        if target_directory is ws_file.directory:
            return
        self.workspace.close_file(ws_file)
        ws_file.set_directory(target_directory)
        self.save_workspace_file(ws_file)
        if reopen:
            self.workspace.open_file(target_directory, ws_file.abs_path)

    def save_workspace_file(self, ws_file):
        ws_file.save()
        self.statusBar().showMessage(f"File '{ws_file.abs_path}' saved.",
                                     STATUSBAR_MESSAGE_TIMEOUT)

    def handle_about_action(self):
        dialog = QDialog(self)
        dialog.setWindowTitle("About MHW Editor Suite")
        layout = QVBoxLayout()
        dialog.setLayout(layout)
        about_text = QLabel(ABOUT_TEXT)
        about_text.setTextFormat(Qt.RichText)
        about_text.setTextInteractionFlags(Qt.TextBrowserInteraction)
        about_text.setOpenExternalLinks(True)
        layout.addWidget(about_text)
        dialog.exec()
示例#9
0
class GUIWindow(QMainWindow):
    def __init__(self, app, pipeline=Pipeline()):
        super().__init__()
        self._app = app
        self._logger = logging.getLogger(self.__class__.__name__)
        self._is_initialized = False
        self.init_basic(pipeline)
        self.init_ui()
        self.init_controls()
        self.setWindowTitle("Cognigraph")
        self.setWindowIcon(QIcon(':/cognigraph_icon.png'))

    def init_basic(self, pipeline):
        self._pipeline = pipeline  # type: Pipeline
        self._updater = AsyncUpdater(self._app, pipeline)
        self._pipeline._signal_sender.long_operation_started.connect(
            self._show_progress_dialog)
        self._pipeline._signal_sender.long_operation_finished.connect(
            self._hide_progress_dialog)
        self._pipeline._signal_sender.request_message.connect(
            self._show_message)
        self._pipeline._signal_sender.node_widget_added.connect(
            self._on_node_widget_added)
        self._controls = Controls(pipeline=self._pipeline)
        self._controls.setSizePolicy(QSizePolicy.Preferred,
                                     QSizePolicy.Expanding)

        self._controls.tree_widget.node_removed.connect(self._on_node_removed)
        if hasattr(self, "central_widget"):
            for w in self.central_widget.subWindowList():
                self.central_widget.removeSubWindow(w)

    def init_controls(self):
        self.controls_dock.setWidget(self._controls)
        self.run_toggle_action.triggered.disconnect()
        self.run_toggle_action.triggered.connect(self._updater.toggle)
        self._updater._sender.run_toggled.connect(self._on_run_button_toggled)
        self._updater._sender.errored.connect(self._show_message)
        self.is_initialized = False

    def init_ui(self):
        self.central_widget = QMdiArea()
        self.setCentralWidget(self.central_widget)

        # -------- controls widget -------- #
        self.controls_dock = QDockWidget("Processing pipeline setup", self)
        self.controls_dock.setObjectName("Controls")
        self.controls_dock.setAllowedAreas(Qt.LeftDockWidgetArea
                                           | Qt.RightDockWidgetArea)
        self.controls_dock.visibilityChanged.connect(
            self._update_pipeline_tree_widget_action_text)

        self.addDockWidget(Qt.LeftDockWidgetArea, self.controls_dock)

        # self._controls.setMinimumWidth(800)
        # --------------------------------- #

        file_menu = self.menuBar().addMenu("&File")  # file menu
        load_pipeline_action = self._createAction("&Load pipeline",
                                                  self._load_pipeline)
        save_pipeline_action = self._createAction("&Save pipeline",
                                                  self._save_pipeline)
        file_menu.addAction(load_pipeline_action)
        file_menu.addAction(save_pipeline_action)

        # -------- view menu & toolbar -------- #
        tile_windows_action = self._createAction(
            "&Tile windows", self.central_widget.tileSubWindows)
        view_menu = self.menuBar().addMenu("&View")
        view_menu.addAction(tile_windows_action)
        view_toolbar = self.addToolBar("View")
        view_toolbar.addAction(tile_windows_action)
        # ------------------------------------- #

        edit_menu = self.menuBar().addMenu("&Edit")
        self._toggle_pipeline_tree_widget_action = self._createAction(
            "&Hide pipeline settings", self._toggle_pipeline_tree_widget)
        edit_menu.addAction(self._toggle_pipeline_tree_widget_action)
        edit_toolbar = self.addToolBar("Edit")
        edit_toolbar.setObjectName("edit_toolbar")
        edit_toolbar.addAction(self._toggle_pipeline_tree_widget_action)

        # -------- run menu & toolbar -------- #
        self.run_toggle_action = self._createAction(
            "&Start", self._on_run_button_toggled)
        run_menu = self.menuBar().addMenu("&Run")
        self.initialize_pipeline = self._createAction("&Initialize pipeline",
                                                      self.initialize)
        run_menu.addAction(self.run_toggle_action)
        run_menu.addAction(self.initialize_pipeline)
        run_toolbar = self.addToolBar("Run")
        run_toolbar.setObjectName("run_toolbar")
        run_toolbar.addAction(self.run_toggle_action)
        run_toolbar.addAction(self.initialize_pipeline)
        # ------------------------------------ #

    def _toggle_pipeline_tree_widget(self):
        if self.controls_dock.isHidden():
            self.controls_dock.show()
        else:
            self.controls_dock.hide()

    def _update_pipeline_tree_widget_action_text(self, is_visible):
        if is_visible:
            self._toggle_pipeline_tree_widget_action.setText(
                "&Hide pipelne settings")
        else:
            self._toggle_pipeline_tree_widget_action.setText(
                "&Show pipelne settings")

    def _load_pipeline(self):
        file_dialog = QFileDialog(caption="Select pipeline file",
                                  directory=PIPELINES_DIR)
        ext_filter = "JSON file (*.json);; All files (*.*)"
        pipeline_path = file_dialog.getOpenFileName(filter=ext_filter)[0]
        if pipeline_path:
            self._logger.info("Loading pipeline configuration from %s" %
                              pipeline_path)
            if not self._updater.is_paused:
                self.run_toggle_action.trigger()
            with open(pipeline_path, "r") as db:
                try:
                    params_dict = json.load(db)
                except json.decoder.JSONDecodeError as e:
                    self._show_message("Bad pipeline configuration file",
                                       detailed_text=str(e))

                pipeline = self.assemble_pipeline(params_dict, "Pipeline")
                self.init_basic(pipeline)
                self.init_controls()
                # self.resize(self.sizeHint())
        else:
            return

    def _save_pipeline(self):
        self._logger.info("Saving pipeline")
        file_dialog = QFileDialog(caption="Select pipeline file",
                                  directory=PIPELINES_DIR)
        ext_filter = "JSON file (*.json);; All files (*.*)"
        pipeline_path = file_dialog.getSaveFileName(filter=ext_filter)[0]
        if pipeline_path:
            self._logger.info("Saving pipeline configuration to %s" %
                              pipeline_path)
            try:
                self._pipeline.save_pipeline(pipeline_path)
            except Exception as exc:
                self._show_message(
                    "Cant`t save pipeline configuration to %s" % pipeline_path,
                    detailed_text=str(exc),
                )
                self._logger.exception(exc)

    def assemble_pipeline(self, d, class_name):
        node_class = getattr(nodes, class_name)
        node = node_class(**d["init_args"])
        for child_class_name in d["children"]:
            child = self.assemble_pipeline(d["children"][child_class_name],
                                           child_class_name)
            node.add_child(child)
        return node

    def initialize(self):
        is_paused = self._updater.is_paused
        if not is_paused:
            self._updater.stop()
        self._logger.info("Initializing all nodes")
        async_initer = AsyncPipelineInitializer(pipeline=self._pipeline,
                                                parent=self)
        async_initer.no_blocking_execution()
        for node in self._pipeline.all_nodes:
            if hasattr(node, "widget"):
                if not node.widget.parent():  # widget not added to QMdiArea
                    self._add_subwindow(node.widget, repr(node))
        self.central_widget.tileSubWindows()
        self.run_toggle_action.setDisabled(False)
        if not is_paused:
            self._updater.start()

    def _finish_initialization(self):
        self.progress_dialog.hide()
        self.progress_dialog.deleteLater()
        for node in self._pipeline.all_nodes:
            if hasattr(node, "widget"):
                self._add_subwindow(node.widget, repr(node))
        self.central_widget.tileSubWindows()

    def _add_subwindow(self, widget, title):
        sw = _HookedSubWindow(self.central_widget)
        sw.setWidget(widget)
        sw.setWindowTitle(title)
        widget.show()

    def _show_progress_dialog(self, text):
        # -------- setup progress dialog -------- #
        self.progress_dialog = QProgressDialog(self)
        self.progress_dialog.setLabelText(text)
        self.progress_dialog.setCancelButtonText(None)
        self.progress_dialog.setRange(0, 0)
        self.progress_dialog.show()

    def _hide_progress_dialog(self):
        self.progress_dialog.hide()
        self.progress_dialog.deleteLater()

    def _on_subwindow_close(self, close_event):
        pass

    def _on_node_widget_added(self, widget, widget_name):
        self._add_subwindow(widget, widget_name)
        self.central_widget.tileSubWindows()

    def _on_node_removed(self, tree_item):
        if hasattr(tree_item.node, "widget"):
            try:
                self.central_widget.removeSubWindow(
                    tree_item.node.widget.parent())
            except AttributeError:
                pass
            except Exception as exc:
                self._show_message(
                    "Can`t remove widget for %s" % tree_item.node,
                    detailed_text=str(exc),
                )
                self._logger.exception(exc)

    def _show_message(self, text, detailed_text=None, level="error"):
        if level == "error":
            icon = QMessageBox.Critical
        elif level == "warning":
            icon = QMessageBox.Warning
        elif level == "info":
            icon = QMessageBox.Information
        msg = QMessageBox(self)
        msg.setIcon(icon)
        msg.setText(text)
        msg.setDetailedText(detailed_text)
        msg.show()

    def _createAction(
        self,
        text,
        slot=None,
        shortcut=None,
        icon=None,
        tip=None,
        checkable=False,
    ):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            action.triggered.connect(slot)
        if checkable:
            action.setCheckable(True)
        return action

    def moveEvent(self, event):
        return super(GUIWindow, self).moveEvent(event)

    def _on_run_button_toggled(self, is_paused=True):
        if is_paused:
            self.run_toggle_action.setText("Start")
        else:
            self.run_toggle_action.setText("Pause")

    @property
    def is_initialized(self):
        return self._is_initialized

    @is_initialized.setter
    def is_initialized(self, value):
        if value:
            self.run_toggle_action.setDisabled(False)
        else:
            self.run_toggle_action.setDisabled(True)
        self._is_initialized = value

    @property
    def _node_widgets(self) -> List[QWidget]:
        node_widgets = list()
        for node in self._pipeline.all_nodes:
            try:
                node_widgets.append(node.widget)
            except AttributeError:
                pass
        return node_widgets
示例#10
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.root_folder = os.path.expanduser("~")
        self.logger = logging.getLogger(name='MainWindow Logger')

        self.set_main_widget()

        #create menus
        self.file_menu = self.menuBar().addMenu('&File')
        self.view_menu = self.menuBar().addMenu('View')
        self.video_menu = self.menuBar().addMenu('Video')
        self.tracking_menu = self.menuBar().addMenu('Tracking')
        self.analysis_menu = self.menuBar().addMenu('Analysis')

        #create toolbar for navigating through videos
        self.video_toolbar = self.addToolBar('Video')
        self.video_trackbar = self.addToolBar('Video Track Bar')

        self.set_file_menu()
        self.set_video_menu()
        self.set_tracking_menu()
        self.set_analysis_menu()

        self.set_slider()
        self.set_status()
        self.set_file_explorer()
        self.set_statistic_toolbar()
        self.set_classification_toolbar()

        self.set_view_menu()

    def set_main_widget(self):
        self.video_player = MainVideoPlayer()
        self.setCentralWidget(self.video_player)

    def add_menu_action(self,
                        menu,
                        name,
                        connection,
                        status_tip,
                        shortcut=None,
                        icon=None,
                        tool_bar=None,
                        return_action=False):
        """Helper function for adding a QAction to a menu.

        Parameters
        ----------
        menu : QMenu
            Which menu to add new QAction to.

        name : string
            Name of new QAction. This is displayed as the QAction
            text in the QMenu.

        connection : function
            Which function should the QAction be connected to.

        status_tip : string
            Status tip to display on MouseOver.

        shortcut : QKeySequence or None (default = None)
            Shortcut to execute action.

        icon : QIcon or None (default = None)
            Icon to attach to QAction.

        tool_bar : QToolBar or None
            QToolBar to attach QAction to (in addition to the specified QMenu).

        return_action : bool (default = False)
            Whether or not to return the action.
        """
        if icon is None:
            action = QAction(name, self)
        else:
            action = QAction(icon, name, self)

        if shortcut is not None:
            action.setShortcut(shortcut)

        action.setStatusTip(status_tip)
        action.triggered.connect(connection)
        menu.addAction(action)

        if tool_bar is not None:
            tool_bar.addAction(action)

        if return_action:
            return action

    def set_file_menu(self):
        self.add_menu_action(menu=self.file_menu,
                             name='Open Directory',
                             connection=self.open_file_directory,
                             status_tip='Open a folder in the file explorer.',
                             shortcut=QKeySequence.Open)
        self.add_menu_action(menu=self.file_menu,
                             name='Open Video',
                             connection=self.open_video,
                             status_tip='Open an individual video.',
                             shortcut=None)
        self.add_menu_action(
            menu=self.file_menu,
            name='Open Tracking Summary',
            connection=self.open_tracking_summary,
            status_tip='Open a tracked video file (.fcts, .xlsx, etc)')

    def set_view_menu(self):
        """Sets up menu to allow users to select which DockWidgets/ToolBars
        are displayed."""
        #file explorer
        display_file_explorer_action = self.file_dock_widget.toggleViewAction()
        self.view_menu.addAction(display_file_explorer_action)

        #statistic widget
        display_statistic_widget_action = self.statistic_toolbar.toggleViewAction(
        )
        self.view_menu.addAction(display_statistic_widget_action)

        #video toolbar
        display_video_toolbar_action = self.video_toolbar.toggleViewAction()
        self.view_menu.addAction(display_video_toolbar_action)

        #slider toolbar
        display_slider_toolbar_action = self.video_trackbar.toggleViewAction()
        self.view_menu.addAction(display_slider_toolbar_action)

    def set_video_menu(self):
        self.previous_action = self.add_menu_action(
            menu=self.video_menu,
            name='Previous Frame',
            connection=self.video_player.previous,
            status_tip='Go to previous frame.',
            icon=QIcon(os.path.join(DIR, 'icons', 'prev_icon.png')),
            tool_bar=self.video_toolbar,
            return_action=True)
        self.previous_action.setEnabled(False)
        self.previous_action.setShortcut(QKeySequence(','))

        self.play_action = self.add_menu_action(
            menu=self.video_menu,
            name='Play',
            connection=self.video_player.on,
            status_tip='Play Video.',
            icon=QIcon(os.path.join(DIR, 'icons', 'play_icon.png')),
            tool_bar=self.video_toolbar,
            return_action=True)
        self.play_action.setEnabled(False)
        self.play_action.setShortcut(QKeySequence(']'))

        self.stop_action = self.add_menu_action(
            menu=self.video_menu,
            name='Stop',
            connection=self.video_player.off,
            status_tip='Stop Video.',
            icon=QIcon(os.path.join(DIR, 'icons', 'stop_icon.png')),
            tool_bar=self.video_toolbar,
            return_action=True)
        self.stop_action.setEnabled(False)
        self.stop_action.setShortcut(QKeySequence('['))

        self.next_action = self.add_menu_action(
            menu=self.video_menu,
            name='Next Frame',
            connection=self.video_player.next,
            status_tip='Go to next frame.',
            icon=QIcon(os.path.join(DIR, 'icons', 'next_icon.png')),
            tool_bar=self.video_toolbar,
            return_action=True)
        self.next_action.setEnabled(False)
        self.next_action.setShortcut(QKeySequence('.'))

        self.stop_start_action = self.add_menu_action(
            menu=self.video_menu,
            name='Pause/Play',
            connection=self.stop_start,
            status_tip='Start playing, pause, or resume playing video.',
            return_action=True)
        self.stop_start_action.setEnabled(False)
        self.stop_start_action.setShortcut(QKeySequence(Qt.Key_Space))

        self.video_zoom_action = self.add_menu_action(
            menu=self.video_menu,
            name='Zoom',
            connection=self.zoom,
            status_tip='Zoom in on a segment of video.',
            return_action=True)
        self.video_zoom_enabled = False
        self.video_zoom_action.setEnabled(False)
        self.video_zoom_action.setShortcut(QKeySequence('Z'))

        self.video_menu.addSeparator()

        # Actions to control the speed of the video.
        self.videoMenuSpeedMenu = self.video_menu.addMenu('Playback Speed')
        speedFunctions = [
            self.adjustSpeed1x, self.adjustSpeed1p5x, self.adjustSpeed2x,
            self.adjustSpeed3x, self.adjustSpeed5x, self.adjustSpeed10x
        ]
        speedFunctionNames = ['1x', '1.5x', '2x', '3x', '5x', '10x']
        speedActionGroup = QActionGroup(self)
        for i in xrange(len(speedFunctionNames)):
            action = self.add_menu_action(
                menu=self.videoMenuSpeedMenu,
                name=speedFunctionNames[i],
                connection=speedFunctions[i],
                status_tip='Adjust the playback speed of the current video.',
                return_action=True)
            action.setCheckable(True)
            speedActionGroup.addAction(action)
            if i == 0:
                action.setChecked(True)

    def set_tracking_menu(self):
        self.add_menu_action(menu=self.tracking_menu,
                             name='Batch Processing',
                             connection=self.track_batch,
                             status_tip='Open Batch Tracking Wizard.')

    def set_analysis_menu(self):
        self.add_menu_action(menu=self.analysis_menu,
                             name='Signal Processing',
                             connection=self.signal_processing,
                             status_tip='Open Signal Processing Dialog.')

    def open_file_directory(self):
        file_dialog = QFileDialog()
        directory_name = str(
            file_dialog.getExistingDirectory(caption='Open Folder',
                                             options=QFileDialog.ShowDirsOnly))

        if not os.path.isdir(directory_name):
            self.logger.warning(
                'Passed directory was not valid (in ' +
                'MainWindow.open_file_directory(), line ~282 of entry.py).')
            return

        self.file_explorer.set_path(directory_name)
        self.root_folder = directory_name

    def open_video(self, video_fname=None):
        """Opens an individual video for display in the central widget."""
        if not isinstance(video_fname, str):
            file_dialog = QFileDialog(self)
            video_fname = str(
                file_dialog.getOpenFileName(caption='Open Video File',
                                            filter='Video Files (*.fmf)',
                                            directory=self.root_folder)[0])

        if not os.path.isfile(video_fname):
            self.logger.warning(
                'Passed `video_fname` was not valid (in ' +
                'MainWindow.open_video(), line 290 of entry.py).')
            return

        self.video_player.set_video(video_fname)
        self.video_player.image_annotation = False
        self.video_player.tracking_summary = None
        self.enable_video_controls()

    def enable_video_controls(self):
        """Enables all video controls and connects signals/slots if necessary."""
        #connect video_player signals
        self.video_player.frame_changed.connect(self.update_frame_label)

        #enable video controls
        self.previous_action.setEnabled(True)
        self.next_action.setEnabled(True)
        self.play_action.setEnabled(True)
        self.stop_action.setEnabled(True)
        self.stop_start_action.setEnabled(True)
        self.video_zoom_action.setEnabled(True)

        #enable slider
        self.slider.setMaximum(self.video_player.video.get_n_frames() - 1)
        self.slider.setValue(0)
        self.slider.setEnabled(True)

        self.frame_label.setText('Frame: 0')
        self.video_label.setText('Current Video: {}'.format(
            self.video_player.video_file_name))

    def open_tracking_summary(self, fcts_fname=None, video_fname=None):
        """Opens a tracking summary file (.fcts, .xlsx, etc) for display."""
        if not isinstance(fcts_fname, str):
            file_dialog = QFileDialog(self)
            fcts_fname = str(
                file_dialog.getOpenFileName(
                    caption='Open Tracking Summary File',
                    filter='Tracking Summary File (*.fcts *.xlsx)',
                    directory=self.root_folder)[0])

        if not os.path.isfile(fcts_fname):
            self.logger.warning(
                'Passed `fcts_fname` was not valid (in ' +
                'MainWindow.open_tracking_summary(), line 332 of entry.py).')
            return

        file_type = fcts_fname.split('.')[-1]
        if file_type == 'fcts':
            with open(fcts_fname, 'rb') as f:
                tracking_summary = pickle.load(f)
        elif file_type == 'xlsx':
            tracking_summary = FCTS().from_xlsx(
                fcts_fname)  # TODO: Add from_xlsx() function
        else:
            return

        if os.path.exists(tracking_summary.video.filename):
            self.video_player.set_video(tracking_summary.video.filename)
        else:
            if not isinstance(video_fname, str):
                file_dialog = QFileDialog(self)
                video_fname = str(
                    file_dialog.getOpenFileName(
                        caption='Select Associated Video File',
                        filter='Video File (*.fmf)',
                        directory=self.root_folder)[0])
            self.video_player.set_video(video_fname)

        self.video_player.tracking_summary = tracking_summary
        self.video_player.image_annotation = True
        self.video_player.update_label()
        self.enable_video_controls()

        # setup statistic toolbar
        self.statistic_toolbar.setEnabled(True)
        # calculate statistics about fly held in current experiment.
        lwa, rwa = wing_stats.individual_wing_angles(tracking_summary.male)
        fwa = wing_stats.full_wing_angle(tracking_summary.male)
        wd = wing_stats.wing_distances(tracking_summary.male)
        nn = spatial_stats.nearest_neighbor_centroid(tracking_summary.male,
                                                     tracking_summary.female)
        n2e, t2e = spatial_stats.nose_and_tail_to_ellipse(
            tracking_summary.male, tracking_summary.female)
        vel = centroid_stats.centroid_velocity(tracking_summary.male)
        self.statistics_widget.statistics = {
            'LeftWingAngle': lwa,
            'RightWingAngle': rwa,
            'FullWingAngle': fwa,
            'WingDistance': wd,
            'Centroid-to-Centroid': nn,
            'Nose-to-Ellipse': n2e,
            'Rear-to-Ellipse': t2e,
            'CentroidVelocity': vel
        }
        self.statistics_widget.update_combobox()
        self.statistics_widget.update_stat_label(0)
        self.statistic_toolbar.show()

        self.classification_toolbar.setEnabled(True)
        self.classification_widget.set_tracking_summary(tracking_summary)
        self.classification_widget.statistics = \
            tracking_summary.male.get_all_behaviors_as_dict()
        self.classification_widget.update_combobox()
        self.classification_widget.update_stat_label(0)
        self.classification_toolbar.show()

    def set_slider(self):
        """Places slider widget in video track bar menu."""
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setMinimum(0)
        self.video_trackbar.addWidget(self.slider)
        self.slider.valueChanged[int].connect(
            self.video_player.slider_update_label)
        self.video_player.frame_changed.connect(self.update_slider)
        self.slider.setEnabled(False)

    def set_status(self):
        """Annotates video statistics at bottom of main window."""
        status = self.statusBar()
        status.setSizeGripEnabled(True)

        self.frame_label = QLabel()
        self.frame_label.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.frame_label.setText('Frame: NA (00:00:00)')

        self.video_label = QLabel()
        self.video_label.setText('Current Video: NA')

        status.addPermanentWidget(self.frame_label)
        status.addWidget(self.video_label)

    def set_file_explorer(self):
        """Initializes the file explorer as a DockWidget."""
        self.file_explorer = FileExplorer()
        self.file_dock_widget = QDockWidget('File Explorer', self)
        self.file_dock_widget.setWidget(self.file_explorer)
        self.addDockWidget(Qt.RightDockWidgetArea, self.file_dock_widget)
        self.file_explorer.open_video.connect(self.load_video_from_file_exp)

    def set_statistic_toolbar(self):
        self.statistic_toolbar = QDockWidget('Tracking Statistics')
        self.statistics_widget = StatisticWindowWidget()
        self.statistic_toolbar.setWidget(self.statistics_widget)
        self.statistic_toolbar.setEnabled(False)
        self.statistic_toolbar.hide()
        self.video_player.frame_changed.connect(
            self.statistics_widget.update_stat_label)
        self.addDockWidget(Qt.TopDockWidgetArea, self.statistic_toolbar)

    def set_classification_toolbar(self):
        self.classification_toolbar = QDockWidget('Behavioral Classifications')
        self.classification_widget = ClassificationWindowWidget()
        self.classification_toolbar.setWidget(self.classification_widget)
        self.classification_toolbar.setEnabled(False)
        self.classification_toolbar.hide()
        self.video_player.frame_changed.connect(
            self.classification_widget.update_stat_label)
        self.addDockWidget(Qt.TopDockWidgetArea, self.classification_toolbar)
        self.tabifyDockWidget(self.statistic_toolbar,
                              self.classification_toolbar)

    def track_batch(self):
        dialog = BatchTrackingDialog(self.root_folder)
        if dialog.exec_():
            return

    def signal_processing(self):
        dialog = StatProcessing(root_folder=self.root_folder, parent=self)
        dialog.show()

    @pyqtSlot(int, str, int)
    def update_frame_label(self, ix, hms, frame_rate):
        self.frame_label.setText(
            'Frame: {} ({}) | FPS: {} | Playback Speed: {}x'.format(
                ix, hms, frame_rate, self.video_player.playback_speed))

    @pyqtSlot(str)
    def load_video_from_file_exp(self, fname):
        self.open_video(str(fname))

    @pyqtSlot(int)
    def update_slider(self, ix):
        self.slider.setValue(ix)

    @pyqtSlot()
    def stop_start(self):
        if self.video_player.is_playing:
            self.video_player.off()
        else:
            self.video_player.on()

    @pyqtSlot()
    def zoom(self):
        """Allows user to select a region of the video to zoom in on."""
        if self.video_zoom_enabled:
            self.video_zoom_enabled = False
            self.video_player.zoom_enabled = False
            non_zooming_cursor = QCursor(Qt.ArrowCursor)
            self.video_player.setCursor(non_zooming_cursor)
            self.video_player.close_zoom_window()
            return

        self.video_zoom_enabled = True
        zooming_cursor = QCursor(Qt.CrossCursor)
        self.video_player.setCursor(zooming_cursor)
        self.video_player.zoom_enabled = True

    # Playback speed adjustments
    @pyqtSlot()
    def adjustSpeed1x(self):
        self.video_player.playback_speed = 1

    @pyqtSlot()
    def adjustSpeed1p5x(self):
        self.video_player.playback_speed = 1.5

    @pyqtSlot()
    def adjustSpeed2x(self):
        self.video_player.playback_speed = 2

    @pyqtSlot()
    def adjustSpeed3x(self):
        self.video_player.playback_speed = 3

    @pyqtSlot()
    def adjustSpeed5x(self):
        self.video_player.playback_speed = 5

    @pyqtSlot()
    def adjustSpeed10x(self):
        self.video_player.playback_speed = 10
示例#11
0
class MainWindow(QMainWindow):
    dep_file_name_list = [
        'analytics', 'bookkeeping', 'development', 'finances', 'hr',
        'marketing', 'purchasing', 'sales', 'testing'
    ]

    dep_name_list = [
        'Аналитический отдел', 'Бухгалтерия', 'Отдел закупок', 'Отдел кадров',
        'Отдел маркетинга', 'Отдел разработки', 'Отдел продаж',
        'Отдел тестирования', 'Финансовый отдел'
    ]

    def __init__(self):
        QMainWindow.__init__(self)
        MainWindow.departments_committed = pyqtSignal(list)
        data = self.__readDepartmentsData()
        self.firm = Firm(Human('Иван', 'Попов'), data)

        self.setWindowTitle('Симулятор офисного расписания')

        # parameters
        self.params_dock = QDockWidget()
        self.params_dock.setAllowedAreas(Qt.LeftDockWidgetArea
                                         | Qt.RightDockWidgetArea)
        self.params_widget = ParametersWidget(data)
        self.params_dock.setWidget(self.params_widget)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.params_dock)

        # filter
        self.filter_dock = QDockWidget()
        self.filter_dock.setAllowedAreas(Qt.LeftDockWidgetArea
                                         | Qt.RightDockWidgetArea)

        # console
        console = QDockWidget()
        console.setAllowedAreas(Qt.BottomDockWidgetArea)

        # tabs
        tabs = QTabWidget()
        confWidget = QListWidget()
        confWidget.model().rowsInserted.connect(confWidget.scrollToBottom)
        tabs.addTab(confWidget, "История")
        console.setWidget(tabs)
        self.addDockWidget(Qt.BottomDockWidgetArea, console)

        # Calendar
        init_matrix = [[[] for i in range(0, 7)] for j in range(0, 9)]
        self.calendar_widget = CalendarWidget(Calendar(init_matrix), self)
        self.setCentralWidget(self.calendar_widget)

        self.tabs = tabs

        self.__createActions()
        self.__onCancelAction()

        self.__createMenus()
        self.__createToolBars()

    def __setDefaultState(self):
        self.params_dock.widget().getModel().uncheckAll()
        self.params_dock.show()
        self.startAction.setEnabled(True)
        self.newAction.setEnabled(False)
        self.pauseAction.setEnabled(False)
        self.cancelAction.setEnabled(False)
        self.nextAction.setEnabled(False)
        self.finishAction.setEnabled(False)
        self.centralWidget().setEnabled(False)
        self.filter_dock.hide()

    def __onCancelAction(self):
        self.tabs.widget(0).addItem('Сбросить параметры моделирования')
        self.__onResetAction()
        self.__setDefaultState()

    def __onResetAction(self):
        self.tabs.widget(0).addItem('Очистить календарь')
        self.calendar_widget.clear_widget()
        self.current_cell = {'row': 0, 'col': 0}
        self.repaint()

    def __onPauseAction(self):
        self.tabs.widget(0).addItem('Пауза моделирования')

    def __onStartAction(self):
        checked_departments = self.params_widget.getModel(
        ).getCheckedDepartmentList()
        self.checked_departments = checked_departments
        if len(checked_departments) == 0:
            self.tabs.widget(0).addItem(
                'Ошибка [параметры]: выберите хотя бы один отдел')
            return
        num_of_days = self.params_widget.sb_period.value()
        self.Matrix = [[[] for i in range(0, num_of_days)]
                       for j in range(0, 9)]

        if self.params_widget.chb_defaultSchedule.isChecked():
            self.__readDefaultSchedule(num_of_days)

        self.filter_dock.setWidget(FilterWidget(checked_departments))
        self.calendar_widget = CalendarWidget(Calendar(self.Matrix), self)
        self.calendar_widget.setFormData(checked_departments)
        self.setCentralWidget(self.calendar_widget)
        self.addDockWidget(Qt.RightDockWidgetArea, self.filter_dock)
        self.params_dock.hide()
        self.newAction.setEnabled(True)
        self.cancelAction.setEnabled(True)
        self.nextAction.setEnabled(True)
        self.finishAction.setEnabled(True)
        self.tabs.widget(0).addItem('Начало моделирования')
        self.startAction.setEnabled(False)
        self.pauseAction.setEnabled(False)
        self.filter_dock.show()

    from lib.logic_manager import LogicManager

    def __onNextAction(self):
        step = int(self.params_widget.cb_step.currentText().split()[0])
        calendar = self.calendar_widget.getCalendar()
        (rest_events,
         next_cell) = LogicManager.simulate_next_step(calendar, step,
                                                      self.current_cell)

        if next_cell is None:
            self.tabs.widget(0).addItem('Моделирование завершено')
        else:
            self.calendar_widget.highlightCell(self.current_cell)
            self.current_cell = next_cell
            self.tabs.widget(0).addItem('Следующий шаг: ' + str(rest_events) +
                                        ' осталось событий')

    def __onFinishAction(self):
        self.tabs.widget(0).addItem('Завершить моделирование...')
        width = len(self.calendar_widget.getCalendar().matrix[0])
        height = len(self.calendar_widget.getCalendar().matrix)

        # sleeper = Sleeper(self.__onNextAction)
        for col_num in range(0, width, 1):
            for row_num in range(0, height, 1):
                self.__onNextAction()
                # sleeper.start()
                # sleeper.wait(1000)

    def __createActions(self):
        newAction = QAction('&Очистить календарь', self)
        newAction.setIcon(self.style().standardIcon(QStyle.SP_BrowserReload))
        newAction.setShortcut(QKeySequence.Forward)
        newAction.setStatusTip('Очистить календарь')
        newAction.triggered.connect(self.__onResetAction)
        self.newAction = newAction

        cancelAction = QAction('&Сбросить параметры моделирования', self)
        cancelAction.setIcon(self.style().standardIcon(QStyle.SP_BrowserStop))
        cancelAction.setShortcut(Qt.Key_Stop)
        cancelAction.setStatusTip('Сбросить параметры моделирования')
        self.cancelAction = cancelAction
        self.cancelAction.triggered.connect(self.__onCancelAction)

        startAction = QAction('&Начать', self)
        startAction.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        startAction.setShortcut(Qt.Key_Stop)
        startAction.setStatusTip('Начало моделирования')
        startAction.triggered.connect(self.__onStartAction)
        self.startAction = startAction

        nextAction = QAction('&Следующий шаг', self)
        nextAction.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekForward))
        nextAction.setShortcut(Qt.Key_Space)
        nextAction.setStatusTip('Следующий шаг')
        nextAction.triggered.connect(self.__onNextAction)
        self.nextAction = nextAction

        finishAction = QAction('&Завершить моделирование', self)
        finishAction.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipForward))
        finishAction.setShortcut(QKeySequence.Forward)
        finishAction.setStatusTip('Завершить моделирование')
        finishAction.triggered.connect(self.__onFinishAction)
        self.finishAction = finishAction

        pauseAction = QAction('&Пауза', self)
        pauseAction.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
        pauseAction.setShortcut(Qt.Key_Pause)
        pauseAction.setStatusTip('Пауза моделирования')
        pauseAction.triggered.connect(self.__onPauseAction)
        self.pauseAction = pauseAction

        exitAction = QAction('&Выход', self)
        exitAction.setShortcut(Qt.Key_Exit)
        exitAction.setStatusTip('Выход')
        exitAction.triggered.connect(self.close)
        self.exitAction = exitAction

    def __createMenus(self):
        sessionMenu = self.menuBar().addMenu('Сессия')
        sessionMenu.addAction(self.newAction)
        sessionMenu.addAction(self.cancelAction)
        sessionMenu.addSeparator()
        sessionMenu.addAction(self.exitAction)

        controlMenu = self.menuBar().addMenu('Управление')
        controlMenu.addAction(self.startAction)
        controlMenu.addAction(self.pauseAction)
        controlMenu.addAction(self.nextAction)
        controlMenu.addAction(self.finishAction)

    def __createToolBars(self):
        sessioToolBar = self.addToolBar('Сессия')
        sessioToolBar.addAction(self.newAction)
        sessioToolBar.addAction(self.cancelAction)

        controlToolBar = self.addToolBar('Управление')
        controlToolBar.addAction(self.startAction)
        controlToolBar.addAction(self.nextAction)
        controlToolBar.addAction(self.finishAction)
        controlToolBar.addAction(self.pauseAction)

    def __readDefaultSchedule(self, num_of_days):
        file_name = 'default'
        file = QFile(':/schedule/' + file_name + '.txt')

        if not file.open(QIODevice.ReadOnly | QIODevice.Text):
            raise FileNotFoundError(file_name)

        stream = QTextStream(file)
        stream.setCodec('UTF-8')

        Matrix = [[[] for i in range(0, num_of_days)] for j in range(0, 9)]
        days_of_week = [
            '', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница',
            'Суббота', 'Воскресенье'
        ]
        while not stream.atEnd():
            week_day = stream.readLine()[:-1]
            line = stream.readLine()
            while line:
                params_of_event = line.split(',')
                time = int(params_of_event[0].replace(':', ''))
                duration = int(params_of_event[1])
                title = params_of_event[2]
                location = params_of_event[3]
                department = params_of_event[4]
                start_day_number = days_of_week.index(week_day)
                days_list = [
                    k for k in range(start_day_number, num_of_days, 7)
                ]

                type = ScheduleEvent.Type.HEAD if department == 'Руководство' else ScheduleEvent.Type.DEP
                participants_list = []
                if type == ScheduleEvent.Type.HEAD:
                    participants_list.append(self.firm.getBoss())
                    for dep in self.checked_departments:
                        participants_list.append(dep.getBoss())
                elif type == ScheduleEvent.Type.DEP:
                    for dep in self.checked_departments:
                        if dep.getName() == department:
                            participants_list.extend(dep.getEmployeeList())
                else:
                    raise Exception(
                        'Error while processing default schedule data: TYPE')

                for day in days_list:
                    if len(participants_list) != 0:
                        Matrix[int(time / 100) - 10][day - 1].append(
                            ScheduleEvent(time=time,
                                          duration=duration,
                                          title=title,
                                          location=location,
                                          type=type,
                                          part_list=participants_list,
                                          day=day))
                line = stream.readLine()

        self.Matrix = Matrix

    def __readDepartmentsData(self):
        department_list = []  # of Department
        for file_name in MainWindow.dep_file_name_list:
            count = 0
            file = QFile(':/stuff/' + file_name + '.txt')
            if not file.open(QIODevice.ReadOnly | QIODevice.Text):
                raise FileNotFoundError(file_name)

            stream = QTextStream(file)
            stream.setCodec('UTF-8')
            dep_name = stream.readLine()
            if dep_name[-1] != ':':
                raise Exception('resource ' + file_name +
                                ' with no department mark')

            dep_name = dep_name[:-1]
            new_dep_obj = Department(dep_name)

            while not stream.atEnd():
                count += 1
                (n, s) = stream.readLine().split()
                if count == 1:
                    new_dep_obj.setBoss(Employee(n, s))
                else:
                    new_dep_obj.addEmployee(Employee(n, s))

            if count == 0:
                raise Exception('resource ' + file_name + ' has no items')

            department_list.append(new_dep_obj)
        return department_list
示例#12
0
class SimulatorWindow(QMainWindow):
    def __init__(self, parent=None):
        super(SimulatorWindow, self).__init__(parent)

        self.initWindow()

    def initWindow(self):
        self.setupToolBar()
        self.setupDockable()
        self.setupTerminal()
        self.setWindowTitle('模拟')

    def setupToolBar(self):
        self.toolBar = self.addToolBar('Control')
        self.toolBar.setIconSize(QSize(48, 48))

        self.resetAction = QAction(QIcon('icons/reset.png'),
                                   '初始化(F9)',
                                   self,
                                   shortcut=QKeySequence('F9'),
                                   statusTip='初始化(F9)',
                                   triggered=self.resetSimulator)
        self.toolBar.addAction(self.resetAction)

        self.stepAction = QAction(QIcon('icons/step.png'),
                                  '单步(F10)',
                                  self,
                                  shortcut=QKeySequence('F10'),
                                  statusTip='单步(F10)',
                                  triggered=self.stepSimulator)
        self.toolBar.addAction(self.stepAction)

        self.runAction = QAction(QIcon('icons/run.png'),
                                 '运行(F11)',
                                 self,
                                 shortcut=QKeySequence('F11'),
                                 statusTip='运行(F11)',
                                 triggered=self.runSimulator)
        self.toolBar.addAction(self.runAction)

    def setupDockable(self):
        self.msgBrowser = MessageBrowser()
        self.bottomDock = QDockWidget('信息', self)
        self.bottomDock.setFeatures(QDockWidget.DockWidgetClosable)
        self.bottomDock.setWidget(self.msgBrowser)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.bottomDock)
        self.bottomDock.hide()

        self.regBrowser = RegBrowser()
        self.leftDock = QDockWidget('寄存器', self)
        self.leftDock.setFeatures(QDockWidget.DockWidgetClosable)
        self.leftDock.setWidget(self.regBrowser)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.leftDock)

        self.binBrowser = BinBrowser()
        self.rightDock = QDockWidget('内存', self)
        self.rightDock.setFeatures(QDockWidget.DockWidgetClosable)
        self.rightDock.setWidget(self.binBrowser)
        self.addDockWidget(Qt.RightDockWidgetArea, self.rightDock)

    def setupTerminal(self):
        self.terminal = TerminalBrowser()
        self.lineInput = TerminalInput()
        self.lineInput.returnPressed.connect(self.updateInput)

        layout = QVBoxLayout()
        layout.addWidget(self.terminal)
        layout.addWidget(self.lineInput)
        central = QWidget()
        central.setLayout(layout)
        self.setCentralWidget(central)

    def updateBrowser(self):
        self.regBrowser.showReg(simulator.reg +
                                [simulator.pc, simulator.hi, simulator.lo])
        self.binBrowser.showBin(simulator.mem, simulator.pc)

        self.terminal.insertHtml(parseHtml(simulator.get_output()))
        self.terminal.moveCursor(QTextCursor.End)

    def updateInput(self):
        simulator.input_data.extend(self.lineInput.text().split())

        self.terminal.insertHtml('<font color="#93C763">' +
                                 parseHtml(self.lineInput.text()) + '</font>')
        self.terminal.moveCursor(QTextCursor.End)
        self.lineInput.clear()

        if self.state == 'STEP':
            self.stepSimulator()
        elif self.state == 'RUN':
            self.runSimulator()

    def setWidgetEnabled(self):
        self.stepAction.setEnabled(not simulator.program_end
                                   and self.state == 'IDLE')
        self.runAction.setEnabled(not simulator.program_end
                                  and self.state == 'IDLE')

        if self.state != 'IDLE':
            self.lineInput.setEnabled(True)
            self.lineInput.setFocus()
        else:
            self.lineInput.setEnabled(False)

    def loadSimulator(self, mem, init_pc):
        if init_pc < 0:
            simulator.load(mem, config.TEXT_ADDR_LOWER)
            self.resetSimulator()
            self.bottomDock.show()
            self.msgBrowser.append(
                '<font color="#FFCD22">[WARNING] Can not find "main" label. Program counter will be set to the lower bound of text segment instead.</font>'
            )
        else:
            simulator.load(mem, init_pc)
            self.resetSimulator()

    def resetSimulator(self):
        simulator.reset()
        self.state = 'IDLE'

        self.bottomDock.hide()
        self.terminal.clear()
        self.lineInput.clear()
        self.msgBrowser.clear()

        self.updateBrowser()
        self.setWidgetEnabled()

    def stepSimulator(self):
        self.state = 'STEP'

        self.msgBrowser.clear()
        self.bottomDock.show()
        self.msgBrowser.append('Simulating...')

        try:
            simulator.step()
        except SimulationInfoException as e:
            self.msgBrowser.append('[INFO] %s' % (str(e)))
        except Exception as e:
            self.msgBrowser.append('<font color="red">[EXCEPTION] %s</font>' %
                                   (str(e)))
            self.msgBrowser.append('Simulation terminated.')
            self.state = 'IDLE'
        else:
            self.msgBrowser.append('Simulation terminated.')
            self.state = 'IDLE'

        self.updateBrowser()
        self.setWidgetEnabled()

    def runSimulator(self):
        self.state = 'RUN'

        self.msgBrowser.clear()
        self.bottomDock.show()
        self.msgBrowser.append('Simulating...')

        try:
            simulator.run()
        except SimulationInfoException as e:
            self.msgBrowser.append('[INFO] %s' % (str(e)))
        except Exception as e:
            self.msgBrowser.append('<font color="red">[EXCEPTION] %s</font>' %
                                   (str(e)))
            self.msgBrowser.append('Simulation terminated.')
            self.state = 'IDLE'
        else:
            self.msgBrowser.append('Simulation terminated.')
            self.state = 'IDLE'

        self.updateBrowser()
        self.setWidgetEnabled()
示例#13
0
class InvoiceX(QMainWindow):
    def __init__(self):
        super().__init__()

        self.mainWindowLeft = 300
        self.mainWindowTop = 300
        self.mainWindowWidth = 680
        self.mainWindowHeight = 480

        self.fileLoaded = False
        self.dialog = None
        self.initUI()

    def initUI(self):

        # StatusBar

        self.statusBar()
        self.setStatusTip('Select a PDF to get started')
        self.set_menu_bar()
        self.set_dockview_fields()
        self.set_center_widget()
        self.set_toolbar()

        self.setGeometry(self.mainWindowLeft, self.mainWindowTop,
                         self.mainWindowWidth, self.mainWindowHeight)
        self.setWindowTitle('Invoice-X')
        self.setWindowIcon(
            QIcon(os.path.join(os.path.dirname(__file__), 'icons/logo.ico')))
        self.show()

        if not spawn.find_executable('convert'):
            QMessageBox.critical(self, 'Import Error',
                                 "Imagemagick is not installed",
                                 QMessageBox.Ok)
            self.close()

        if sys.platform[:3] == 'win':
            if not spawn.find_executable('magick'):
                QMessageBox.critical(
                    self, 'Import Error',
                    "Imagemagick and GhostScript are not installed",
                    QMessageBox.Ok)
                self.close()

    def set_toolbar(self):
        toolbar = self.addToolBar('File')
        toolbar.addAction(self.openFile)
        toolbar.addAction(self.saveFile)
        toolbar.addAction(self.validateMetadata)
        toolbar.addAction(self.editFields)

    def set_center_widget(self):
        self.square = QLabel(self)
        self.square.setAlignment(Qt.AlignCenter)
        self.setCentralWidget(self.square)

    def set_dockview_fields(self):
        self.fields = QDockWidget("Fields", self)
        self.fields.installEventFilter(self)
        self.fieldsQWidget = QWidget()
        self.fieldsScrollArea = QScrollArea()
        self.fieldsScrollArea.setWidgetResizable(True)
        self.fieldsScrollArea.setWidget(self.fieldsQWidget)

        self.layout = QGridLayout()
        self.fieldsQWidget.setLayout(self.layout)

        self.fields.setWidget(self.fieldsScrollArea)
        self.fields.setFloating(False)
        self.fields.setMinimumWidth(360)
        self.fields.setStyleSheet("QWidget { background-color: #AAB2BD}")
        self.addDockWidget(Qt.RightDockWidgetArea, self.fields)

    def set_menu_bar(self):
        self.exitAct = QAction(
            QIcon(os.path.join(os.path.dirname(__file__), 'icons/exit.png')),
            'Exit', self)
        self.exitAct.setShortcut('Ctrl+Q')
        self.exitAct.setStatusTip('Exit application')
        self.exitAct.triggered.connect(self.close)

        self.openFile = QAction(
            QIcon(os.path.join(os.path.dirname(__file__), 'icons/pdf.png')),
            'Open', self)
        self.openFile.setShortcut('Ctrl+O')
        self.openFile.setStatusTip('Open new File')
        self.openFile.triggered.connect(self.show_file_dialog)

        self.saveFile = QAction(
            QIcon(os.path.join(os.path.dirname(__file__), 'icons/save.png')),
            'Save', self)
        self.saveFile.setShortcut('Ctrl+S')
        self.saveFile.setStatusTip('Save File')
        self.saveFile.triggered.connect(self.save_file_dialog)

        self.saveAsFile = QAction('Save As', self)
        self.saveAsFile.setStatusTip('Save File as a new File')
        self.saveAsFile.triggered.connect(self.show_save_as_dialog)

        self.viewDock = QAction('View Fields', self, checkable=True)
        self.viewDock.setStatusTip('View Fields')
        self.viewDock.setChecked(True)
        self.viewDock.triggered.connect(self.view_dock_field_toggle)

        extractFields = QAction('Extract Fields', self)
        extractFields.setStatusTip('Extract Fields from PDF and add to XML')
        extractFields.triggered.connect(self.extract_fields_from_pdf)

        jsonFormat = QAction('JSON', self)
        jsonFormat.setStatusTip('Export file to JSON')
        jsonFormat.triggered.connect(lambda: self.export_fields('json'))

        xmlFormat = QAction('XML', self)
        xmlFormat.setStatusTip('Export file to XML')
        xmlFormat.triggered.connect(lambda: self.export_fields('xml'))

        ymlFormat = QAction('YML', self)
        ymlFormat.setStatusTip('Export file to YML')
        ymlFormat.triggered.connect(lambda: self.export_fields('yml'))

        self.validateMetadata = QAction(
            QIcon(os.path.join(os.path.dirname(__file__),
                               'icons/validate.png')), 'Validate', self)
        self.validateMetadata.setStatusTip('Validate XML')
        self.validateMetadata.triggered.connect(self.validate_xml)

        addMetadata = QAction('Add Metadata', self)
        addMetadata.setStatusTip('Add metadata to PDF')

        self.editFields = QAction(
            QIcon(os.path.join(os.path.dirname(__file__), 'icons/edit.png')),
            'Edit Metadata', self)
        self.editFields.setStatusTip('Edit Metadata in XML')
        self.editFields.triggered.connect(self.edit_fields_dialog)

        documentation = QAction('Documentation', self)
        documentation.setStatusTip('Open Documentation for Invoice-X')
        documentation.triggered.connect(self.documentation_menubar)

        aboutApp = QAction('About', self)
        aboutApp.setStatusTip('Know about Invoice-X')
        aboutApp.triggered.connect(self.about_app_menubar)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(self.openFile)
        fileMenu.addAction(self.saveFile)
        fileMenu.addAction(self.saveAsFile)
        fileMenu.addAction(self.viewDock)
        fileMenu.addAction(self.exitAct)

        commandMenu = menubar.addMenu('&Command')

        exportMetadata = commandMenu.addMenu('&Export Metadata')
        exportMetadata.addAction(jsonFormat)
        exportMetadata.addAction(xmlFormat)
        exportMetadata.addAction(ymlFormat)

        commandMenu.addAction(self.validateMetadata)
        commandMenu.addAction(self.editFields)
        commandMenu.addAction(addMetadata)
        commandMenu.addAction(extractFields)

        helpMenu = menubar.addMenu('&Help')
        helpMenu.addAction(documentation)
        helpMenu.addAction(aboutApp)

    def view_dock_field_toggle(self, state):
        if state:
            self.fields.show()
        else:
            self.fields.hide()

    def validate_xml(self):
        try:
            if self.factx.is_valid():
                QMessageBox.information(self, 'Valid XML', "The XML is Valid",
                                        QMessageBox.Ok)
            else:
                QMessageBox.critical(self, 'Invalid XML', "The XML is invalid",
                                     QMessageBox.Ok)
        except AttributeError:
            QMessageBox.critical(self, 'File Not Found', "Load a PDF first",
                                 QMessageBox.Ok)

    def set_pdf_preview(self):
        # print(str(fileName[0]))
        if not os.path.exists('.load'):
            os.mkdir('.load')
        if sys.platform[:3] == 'win':
            convert = [
                'magick', self.fileName[0], '-flatten', '.load/preview.jpg'
            ]
        else:
            convert = [
                'convert', '-verbose', '-density', '150', '-trim',
                self.fileName[0], '-quality', '100', '-flatten', '-sharpen',
                '0x1.0', '.load/preview.jpg'
            ]
        subprocess.call(convert)
        self.pdfPreviewImage = '.load/preview.jpg'
        self.fileLoaded = True
        self.square.setPixmap(
            QPixmap(self.pdfPreviewImage).scaled(self.square.size().width(),
                                                 self.square.size().height(),
                                                 Qt.KeepAspectRatio,
                                                 Qt.SmoothTransformation))

    def edit_fields_dialog(self):
        try:
            self.dialog = EditFieldsClass(self, self.factx, self.fieldsDict,
                                          self.metadata_field)
            self.dialog.installEventFilter(self)
            # self.dialog.show()
        except AttributeError:
            QMessageBox.critical(self, 'File Not Found', "Load a PDF first",
                                 QMessageBox.Ok)

    def update_dock_fields(self):
        self.factx.write_json('.load/output.json')
        with open('.load/output.json') as jsonFile:
            self.fieldsDict = json.load(jsonFile)
        os.remove('.load/output.json')
        # print(self.fieldsDict)

        i = 0

        self.metadata_field = {
            'amount_tax': 'Amount Tax',
            'amount_total': 'Amount Total',
            'amount_untaxed': 'Amount Untaxed',
            'buyer': 'Buyer',
            'currency': 'Currency',
            'date': 'Date',
            'date_due': 'Date Due',
            'invoice_number': 'Invoice Number',
            'name': 'Name',
            'notes': 'Notes',
            'seller': 'Seller',
            'type': 'Type',
            'version': 'Version'
        }

        for key in sorted(self.fieldsDict):
            i += 1
            try:
                self.factx[key]
            except IndexError:
                self.fieldsDict[key] = "Field Not Specified"
            except TypeError:
                pass
            fieldKey = QLabel(self.metadata_field[key] + ": ")
            if self.fieldsDict[key] is None:
                fieldValue = QLabel("NA")
            else:
                if key[:4] == "date" and \
                        self.fieldsDict[key] != "Field Not Specified":
                    self.fieldsDict[key] = self.fieldsDict[key][:4] \
                        + "/" + self.fieldsDict[key][4:6] \
                        + "/" + self.fieldsDict[key][6:8]
                if self.fieldsDict[key] == "Field Not Specified":
                    fieldValue = QLabel(self.fieldsDict[key])
                    fieldValue.setStyleSheet("QLabel { color: #666666}")
                else:
                    fieldValue = QLabel(self.fieldsDict[key])
            # fieldValue.setFrameShape(QFrame.Panel)
            # fieldValue.setFrameShadow(QFrame.Plain)
            # fieldValue.setLineWidth(3)
            self.layout.addWidget(fieldKey, i, 0)
            self.layout.addWidget(fieldValue, i, 1)

    def show_file_dialog(self):

        self.fileName = QFileDialog.getOpenFileName(self, 'Open file',
                                                    os.path.expanduser("~"),
                                                    "pdf (*.pdf)")
        self.load_pdf_file()

    def load_pdf_file(self):
        if self.fileName[0]:
            if self.check_xml_for_pdf() is None:
                self.standard = None
                self.level = None
                self.choose_standard_level()
                if self.standard is not None:
                    self.factx = FacturX(self.fileName[0], self.standard,
                                         self.level)
            else:
                self.factx = FacturX(self.fileName[0])
            if hasattr(self, 'factx'):
                self.set_pdf_preview()
                self.update_dock_fields()
                self.setStatusTip("PDF is Ready")

    def choose_standard_level(self):
        self.chooseStandardDialog = QDialog()
        layout = QGridLayout()

        noXMLLabel = QLabel("No XML found", self)
        layout.addWidget(noXMLLabel, 0, 0)

        chooseStandardLabel = QLabel("Standard", self)
        chooseStandardCombo = QComboBox(self)
        chooseStandardCombo.addItem("Factur-X")
        chooseStandardCombo.addItem("Zugferd")
        chooseStandardCombo.addItem("UBL")
        chooseStandardCombo.model().item(2).setEnabled(False)
        chooseStandardCombo.activated[str].connect(self.on_select_level)

        chooseLevelLabel = QLabel("Level", self)
        self.chooseLevelCombo = QComboBox(self)
        self.chooseLevelCombo.addItem("Minimum")
        self.chooseLevelCombo.addItem("Basic WL")
        self.chooseLevelCombo.addItem("Basic")
        self.chooseLevelCombo.addItem("EN16931")
        self.chooseLevelCombo.activated[str].connect(self.set_level)

        applyStandard = QPushButton("Apply")
        applyStandard.clicked.connect(self.set_standard_level)
        discardStandard = QPushButton("Cancel")
        discardStandard.clicked.connect(self.discard_standard_level)

        layout.addWidget(chooseStandardLabel, 1, 0)
        layout.addWidget(chooseStandardCombo, 1, 1)
        layout.addWidget(chooseLevelLabel, 2, 0)
        layout.addWidget(self.chooseLevelCombo, 2, 1)
        layout.addWidget(discardStandard, 3, 0)
        layout.addWidget(applyStandard, 3, 1)

        self.chooseStandardDialog.setLayout(layout)
        self.chooseStandardDialog.setWindowTitle("Choose Standard")
        self.chooseStandardDialog.setWindowModality(Qt.ApplicationModal)
        self.chooseStandardDialog.exec_()

    def set_standard_level(self):
        try:
            self.standard = self.standard_temp
            self.level = self.level_temp
        except AttributeError:
            self.standard = 'factur-x'
            self.level = 'minimum'
        self.chooseStandardDialog.close()

    def discard_standard_level(self):
        self.chooseStandardDialog.close()

    def on_select_level(self, text):
        if text == "Factur-X":
            self.chooseLevelCombo.clear()
            self.chooseLevelCombo.addItem("Minimum")
            self.chooseLevelCombo.addItem("Basic WL")
            self.chooseLevelCombo.addItem("Basic")
            self.chooseLevelCombo.addItem("EN16931")
        elif text == "Zugferd":
            self.chooseLevelCombo.clear()
            self.chooseLevelCombo.addItem("Basic")
            self.chooseLevelCombo.addItem("Comfort")
        elif text == "UBL":
            self.chooseLevelCombo.clear()
            self.chooseLevelCombo.addItem("UBL 2.0")
            self.chooseLevelCombo.addItem("UBL 2.1")

        standard_dict = {
            'Factur-X': ['factur-x', 'minimum'],
            'Zugferd': ['zugferd', 'basic'],
        }
        self.standard_temp = standard_dict[text][0]
        self.level_temp = standard_dict[text][1]

    def set_level(self, text):
        level_dict = {
            'Minimum': 'minimum',
            'Basic WL': 'basicwl',
            'Basic': 'basic',
            'EN16931': 'en16931',
            'Comfort': 'comfort'
        }
        self.level_temp = level_dict[text]

    def check_xml_for_pdf(self):
        pdf = PdfFileReader(self.fileName[0])
        pdf_root = pdf.trailer['/Root']
        if '/Names' not in pdf_root or '/EmbeddedFiles' not in \
                pdf_root['/Names']:
            return None

        for file in pdf_root['/Names']['/EmbeddedFiles']['/Names']:
            if isinstance(file, IndirectObject):
                obj = file.getObject()
                if obj['/F'] in xml_flavor.valid_xmp_filenames():
                    xml_root = etree.fromstring(obj['/EF']['/F'].getData())
                    xml_content = xml_root
        return xml_content

    def save_file_dialog(self):
        if self.fileLoaded:
            if self.confirm_save_dialog():
                try:
                    self.factx.write_pdf(self.fileName[0])
                except TypeError:
                    QMessageBox.critical(self, 'Type Error',
                                         "Some field value(s) are invalid",
                                         QMessageBox.Ok)
        else:
            QMessageBox.critical(self, 'File Not Found', "Load a PDF first",
                                 QMessageBox.Ok)

    def confirm_save_dialog(self):
        reply = QMessageBox.question(
            self, 'Message', "Do you want to save? This cannot be undone",
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            return True
        else:
            return False

    def show_save_as_dialog(self):
        if self.fileLoaded:
            try:
                self.saveFileName = QFileDialog.getSaveFileName(
                    self, 'Save file', os.path.expanduser("~"), "pdf (*.pdf)")
                if self.saveFileName[0]:
                    if self.saveFileName[0].endswith('.pdf'):
                        fileName = self.saveFileName[0]
                    else:
                        fileName = self.saveFileName[0] + '.pdf'
                    self.factx.write_pdf(fileName)
            except TypeError:
                QMessageBox.critical(self, 'Type Error',
                                     "Some field value(s) are not valid",
                                     QMessageBox.Ok)
        else:
            QMessageBox.critical(self, 'File Not Found', "Load a PDF first",
                                 QMessageBox.Ok)

    def extract_fields_from_pdf(self):
        if self.fileLoaded:
            self.populate = PopulateFieldClass(self, self.factx,
                                               self.fieldsDict,
                                               self.metadata_field)
        else:
            QMessageBox.critical(self, 'File Not Found', "Load a PDF first",
                                 QMessageBox.Ok)

    def documentation_menubar(self):
        pass

    def about_app_menubar(self):
        pass

    def export_fields(self, outputformat):
        if self.fileLoaded:
            self.exportFileName = QFileDialog.getSaveFileName(
                self, 'Export file',
                os.path.expanduser("~") + '/output.%s' % outputformat,
                "%s (*.%s)" % (outputformat, outputformat))
            if self.exportFileName[0]:
                if outputformat is "json":
                    self.pdf_write_json(self.exportFileName[0])
                elif outputformat is "xml":
                    self.pdf_write_xml(self.exportFileName[0])
                elif outputformat is "yml":
                    self.pdf_write_yml(self.exportFileName[0])
        else:
            QMessageBox.critical(self, 'File Not Found', "Load a PDF first",
                                 QMessageBox.Ok)

    def pdf_write_json(self, fileName):
        self.factx.write_json(fileName)

    def pdf_write_xml(self, fileName):
        self.factx.write_xml(fileName)

    def pdf_write_yml(self, fileName):
        self.factx.write_yml(fileName)

    def resizeEvent(self, event):
        if self.fileLoaded:
            self.square.setPixmap(
                QPixmap(self.pdfPreviewImage).scaled(
                    self.square.size().width(),
                    self.square.size().height(), Qt.KeepAspectRatio,
                    Qt.SmoothTransformation))
            self.square.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Ignored)
            QMainWindow.resizeEvent(self, event)

    def eventFilter(self, source, event):
        if event.type() == QEvent.Close and source is self.fields:
            self.viewDock.setChecked(False)
        return QMainWindow.eventFilter(self, source, event)

    def closeEvent(self, event):
        if os.path.isdir('.load'):
            shutil.rmtree('.load/')
示例#14
0
class MainWindow(QMainWindow):
    var1 = ""
    var2 = ""
    
    def __init__(self):
        super(MainWindow, self).__init__()

        self.setUpMenus()
       
        CSRWidgets.changeCentralWidget(self, CSRWidgets.createDesignButtons(self, 'default')) #Sets central widget on init.
        self.setWindowTitle("CSR Proving Ground")
        
        self.resize(1500, 900)
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def setUpMenus(self):
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.createDockWindows()
        
    def about(self):
        QMessageBox.about(self, "C3PO", "His high exaltedness, the Great Jabba the Hutt, has decreed that you are to be terminated immediately.")

    def createMenus(self):
        CSRWidgets.createActions(self)
        
        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.quitAct)

        self.editMenu = self.menuBar().addMenu("&Edit")

        self.viewMenu = self.menuBar().addMenu("&View")

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)

    def createToolBars(self):
        self.homeToolBar = self.addToolBar("Home")
        self.homeToolBar.addAction(self.homeAct)
        self.homeToolBar.addAction(self.quitAct)

        self.searchToolBar = self.addToolBar("Search")
        self.searchToolBar.addAction(self.searchAct)
        
        self.searchBar = QLineEdit()
        self.searchBar.setMaximumWidth(150)
        self.searchBar.returnPressed.connect(self.btnSearch_Click)
        self.searchToolBar.addWidget(self.searchBar)
        
        self.searchToolBar.addSeparator()
        self.searchToolBar.addAction(self.undoAct)
        
        self.searchToolBar.addSeparator()
        
        btnNameChange = QPushButton('Change Name', self)
        btnNameChange.clicked.connect(self.btnNameChange_Click)
        
        self.lblVar1 = QLabel()
        self.lblVar1.setFont(QFont('Veranda', 14, QFont.Bold))
        #self.lblVar1.setMargin(10)
        self.lblVar1.setStyleSheet('padding-left:10px')
        
        self.lblTxtVar1 = QLabel()
        self.lblTxtVar1.setFont(QFont('Veranda', 14, QFont.Bold))
        #self.lblTxtVar1.setMargin(0)
        self.lblTxtVar1.setStyleSheet('padding-left:1px')
        
        self.lblVar2 = QLabel()
        self.lblVar2.setFont(QFont('Veranda', 14, QFont.Bold))
        self.lblVar2.setMargin(10)  
        
        self.lblTxtVar2 = QLabel()
        self.lblTxtVar2.setFont(QFont('Veranda', 14, QFont.Bold))
        self.lblTxtVar2.setMargin(0)              
        
        self.lblSkuName = QLabel()
        self.lblSkuName.setFont(QFont('Veranda', 14, QFont.Bold))
        self.lblSkuName.setMargin(10)
        
        self.searchToolBar.addWidget(btnNameChange)
        self.searchToolBar.addWidget(self.lblVar1)
        self.searchToolBar.addWidget(self.lblTxtVar1)
        self.searchToolBar.addWidget(self.lblVar2)
        self.searchToolBar.addWidget(self.lblTxtVar2)
        self.searchToolBar.addWidget(self.lblSkuName)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def createDockWindows(self):
        dock = QDockWidget("Available Garments Types", self)
        #dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.availableItems = QListWidget(dock)
        self.availableItems.setMinimumWidth(350)
        self.availableItems.setMaximumWidth(350)
        #self.availableItems.addItems(("stuff"))
        self.availableItems.itemClicked.connect(self.itemClicked_Click)
        dock.setWidget(self.availableItems)
        self.addDockWidget(Qt.RightDockWidgetArea, dock)
        self.viewMenu.addAction(dock.toggleViewAction())
        dock.hide()

        self.dock = QDockWidget("Available Garment Sizes", self)
        self.orderItem = QTreeWidget(dock)
        #self.orderItem.setMinimumWidth(350)
        #self.orderItem.setMaximumWidth(350)
        #self.orderItem.insertText(("more stuff"))
        self.dock.setWidget(self.orderItem)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
        self.viewMenu.addAction(self.dock.toggleViewAction())
        self.dock.hide()
        
        #Create a tree widget for use when the t-shirt is clicked.
        self.treeDock = QDockWidget("Order Items", self)
        self.garmentTree = QTreeWidget(self.treeDock)
        self.garmentTree.setObjectName('garmentTree')
        self.garmentTree.itemClicked.connect(CSRWidgets.sumQuantity)
        self.garmentTree.itemClicked.connect(lambda: CSRWidgets.updateNameDesign(self))
            
        self.garmentTree.setMaximumWidth(480)
        self.garmentTree.setMinimumWidth(480)
   
        self.treeDock.hide()
        
    def btnSale_Click(self):
        btnName = self.sender()
        sku_code = str(btnName.objectName())
#         #print(sku_code)
#         sv = mysql_db.getSecondVar(self, sku_code)
#         if self.var1 == "":
#             CSRWidgets.getCustomerName(self, sku_code)
#         elif self.var1 != "" and not self.var2:
#             sv = mysql_db.getSecondVar(self, sku_code)
#             print(sv)
#             if sv:
#                 CSRWidgets.getCustomerName(self, sku_code)
#             else:
#                 self.var2 = None
#                 self.lblVar2.hide()
#                 self.lblTxtVar2.hide()
        
        CSRWidgets.loadDesignItem(self, sku_code)
        
    def btnNameChange_Click(self):
        CSRWidgets.changeCustName(self)
        
    def btnHome_Click(self):
        CSRWidgets.changeCentralWidget(self, CSRWidgets.createDesignButtons(self,'default'))
        self.availableItems.clear()
        itSku = QTreeWidgetItemIterator(self.garmentTree) 
#################################################################################           
        while itSku.value():
            if itSku.value().parent() != None:   
                itSku.value().setExpanded(False)
            itSku += 1
#################################################################################
        
    def btnSearch_Click(self):
        self.availableItems.clear()
        #self.orderItem.clear()
        searchTerm = self.searchBar.text()
        CSRWidgets.changeCentralWidget(self, CSRWidgets.createDesignButtons(self,searchTerm))

    def btnUndo_Click(self):
        CSRWidgets.undo(self)

    def itemClicked_Click(self):
        button = self.sender()
        txtItem = button.uniqueId
        CSRWidgets.loadGarmentInfo(self, self.currentInfo[txtItem][2], self.currentInfo[txtItem][1], self.currentInfo[txtItem][0], self.currentInfo[txtItem][6])
示例#15
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.initAssembler()
        self.initWindow()

    # --------------------------------------------------------------------------
    # Initialize assembler
    # --------------------------------------------------------------------------
    def initAssembler(self):
        # Load config and pseudo instructions
        pseudo.load_pseudo(config.CONFIG_FILE)
        config.load_config(config.CONFIG_FILE)

    # --------------------------------------------------------------------------
    # Initialize main window
    # --------------------------------------------------------------------------
    def initWindow(self):
        self.currentFile = ''
        self.dirty = False

        self.setupFileMenu()
        self.setupSettingMenu()
        self.setupAssembleMenu()
        self.setupHelpMenu()
        self.setupEditor()
        self.setupDockable()

        self.setCentralWidget(self.editor)
        self.setWindowTitle('Untitled - YAME')
        self.setWindowIcon(QIcon('icons/yame.png'))

        self.simulatorWindow = SimulatorWindow(self)

    # --------------------------------------------------------------------------
    # Set when text in the editor is modified
    # --------------------------------------------------------------------------
    def setDirty(self):
        self.dirty = True
        self.updateStatus()

    # --------------------------------------------------------------------------
    # Clear dirty state
    # --------------------------------------------------------------------------
    def clearDirty(self):
        self.dirty = False
        self.updateStatus()

    # --------------------------------------------------------------------------
    # Check if text in the editor is modified
    # --------------------------------------------------------------------------
    def isDirty(self):
        return self.dirty and (self.currentFile or self.editor.toPlainText())

    # --------------------------------------------------------------------------
    # YAME's main window
    # --------------------------------------------------------------------------
    def updateStatus(self):
        title = '* ' if self.isDirty() else ''
        if self.currentFile:
            title += self.currentFile
        else:
            title += 'Untitled'
        title += ' - YAME'
        self.setWindowTitle(title)

    # --------------------------------------------------------------------------
    # Confirm message box
    # --------------------------------------------------------------------------
    def okToContinue(self):
        if self.isDirty():
            reply = QMessageBox.question(
                self, 'YAME - 尚未保存的修改',
                '<p align="center" style="font-size: 16px;">存在尚未保存的修改,是否保存?</p>',
                QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
            if reply == QMessageBox.Cancel:
                return False
            elif reply == QMessageBox.Yes:
                return self.saveFile()
        return True

    # --------------------------------------------------------------------------
    # Quit the app
    # --------------------------------------------------------------------------
    def closeEvent(self, event):
        if self.okToContinue():
            # Save config and pseudo instructions
            pseudo.save_pseudo(config.CONFIG_FILE)
            config.save_config(config.CONFIG_FILE)

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

    # --------------------------------------------------------------------------
    # Assemble text to machine code
    # --------------------------------------------------------------------------
    def assemble(self):
        self.msgBrowser.clear()
        self.bottomDock.show()

        self.msgBrowser.append('Assembling...')
        try:
            mem, init_pc = assembler.assemble(self.editor.toPlainText())
        except Exception as e:
            # Move editor to the corresponding line
            regex_res = re.search('Line ([0-9]+?):', str(e))
            if regex_res != None:
                line_num = int(regex_res.group(1))
                self.editor.moveCursor(QTextCursor.End)
                cursor = QTextCursor(
                    self.editor.document().findBlockByLineNumber(line_num - 1))
                self.editor.setTextCursor(cursor)

            self.msgBrowser.append('<font color="red">[ERROR] %s</font>' %
                                   (str(e)))
            self.msgBrowser.append('Assembling procedure terminated.')
            return False
        else:
            self.msgBrowser.append('Assembling procedure finished.')
            self.binBrowser.init_pc = init_pc
            self.binBrowser.showBin(mem)
            self.rightDock.show()
            return True

    # --------------------------------------------------------------------------
    # Disassemble machine code to text
    # --------------------------------------------------------------------------
    def disassemble(self):
        if not self.okToContinue():
            return False

        self.msgBrowser.clear()
        self.bottomDock.show()
        self.rightDock.show()

        self.msgBrowser.append('Disassembling...')
        try:
            text = disassembler.disassemble(self.binBrowser.mem)
        except Exception as e:
            self.msgBrowser.append('<font color="red">[ERROR] %s</font>' %
                                   (str(e)))
            self.msgBrowser.append('Disassembling procedure terminated.')
            return False
        else:
            self.msgBrowser.append('Disassembling procedure finished.')
            self.currentFile = ''
            self.editor.setPlainText(text)
            return True

    # --------------------------------------------------------------------------
    # Simulate MIPS instructions
    # --------------------------------------------------------------------------
    def simulate(self):
        if not self.assemble():
            return False

        self.simulatorWindow.loadSimulator(self.binBrowser.mem,
                                           self.binBrowser.init_pc)
        self.simulatorWindow.show()
        return True

    # --------------------------------------------------------------------------
    # Pesudo instructions management
    # --------------------------------------------------------------------------
    def pseudoIns(self):
        pseudoDialog = PseudoDialog(self)
        pseudoDialog.exec_()

        # Update highlighter
        self.highlighter = MipsHighlighter(self.editor.document())

    # --------------------------------------------------------------------------
    # Setting memory size, text segment address, etc.
    # --------------------------------------------------------------------------
    def setting(self):
        settingDialog = SettingDialog(self)
        settingDialog.exec_()

    # --------------------------------------------------------------------------
    # About message box
    # --------------------------------------------------------------------------
    def about(self):
        QMessageBox.about(
            self, '关于 YAME',
            '<p style="font-size: 16px;">YAME: A MIPS Editor</p>'\
            '<p style="font-size: 16px;">Made by TsReaper</p>'\
            '<p style="font-size: 16px;">YAME 是一个简单的 MIPS 编辑器 / 汇编器 / 反汇编器 / 模拟器。</p>'
            '<p style="font-size: 16px;">工程 github 页面:<a href="https://github.com/TsReaper/YAME-A-MIPS-Editor">https://github.com/TsReaper/YAME-A-MIPS-Editor</a></p>'
        )

    # --------------------------------------------------------------------------
    # Clear editor
    # --------------------------------------------------------------------------
    def newFile(self):
        if not self.okToContinue():
            return False

        self.editor.clear()
        self.currentFile = ''
        self.clearDirty()
        return True

    # --------------------------------------------------------------------------
    # Open a file in the disk
    # --------------------------------------------------------------------------
    def openFile(self):
        if not self.okToContinue():
            return False

        path, _ = QFileDialog.getOpenFileName(self, '打开', '', '汇编文件 (*.asm)')

        if path:
            try:
                # Try to use gbk decoder
                file = open(path, 'r')
                self.editor.setPlainText(file.read())
            except:
                # Try to use utf-8 decoder
                file.close()
                file = open(path, 'r', encoding='utf-8')
                self.editor.setPlainText(file.read())
            file.close()

            self.currentFile = path
            self.clearDirty()
            return True

        return False

    # --------------------------------------------------------------------------
    # Save current text
    # --------------------------------------------------------------------------
    def saveFile(self):
        if not self.currentFile:
            return self.saveAnotherFile()

        file = open(self.currentFile, 'w')
        file.write(self.editor.toPlainText())
        file.close()

        self.clearDirty()
        return True

    # --------------------------------------------------------------------------
    # Save copy of current text
    # --------------------------------------------------------------------------
    def saveAnotherFile(self):
        path, _ = QFileDialog.getSaveFileName(
            self, '另存为', self.currentFile if self.currentFile else '',
            '汇编文件 (*.asm)')

        if path:
            file = open(path, 'w')
            file.write(self.editor.toPlainText())
            file.close()

            self.currentFile = path
            self.clearDirty()
            return True

        return False

    # --------------------------------------------------------------------------
    # Import coe or bin file
    # --------------------------------------------------------------------------
    def importFile(self):
        self.newFile()

        path, _ = QFileDialog.getOpenFileName(self, '导入', '',
                                              'COE文件 (*.coe);;二进制文件 (*.bin)')

        try:
            if path.split('.')[-1] == 'coe':
                mem = coe_file.read(path)
            elif path.split('.')[-1] == 'bin':
                mem = bin_file.read(path)
            else:
                return False
        except Exception as e:
            self.msgBrowser.clear()
            self.bottomDock.show()
            self.msgBrowser.append('<font color="red">[ERROR] %s</font>' %
                                   (str(e)))
            return False

        self.rightDock.show()
        self.binBrowser.showBin(mem)

        return self.disassemble()

    # --------------------------------------------------------------------------
    # Export coe or bin file
    # --------------------------------------------------------------------------
    def exportFile(self):
        if not self.assemble():
            return False

        path, _ = QFileDialog.getSaveFileName(self, '导出', '',
                                              'COE文件 (*.coe);;二进制文件 (*.bin)')

        if path.split('.')[-1] == 'coe':
            coe_file.write(path, self.binBrowser.mem)
            return True
        if path.split('.')[-1] == 'bin':
            bin_file.write(path, self.binBrowser.mem)
            return True

        return False

    # --------------------------------------------------------------------------
    # Setup file menu
    # --------------------------------------------------------------------------
    def setupFileMenu(self):
        fileMenu = QMenu('文件(&F)', self)
        self.menuBar().addMenu(fileMenu)

        fileMenu.addAction('新建(&N)', self.newFile, 'Ctrl+N')
        fileMenu.addAction('打开(&O)...', self.openFile, 'Ctrl+O')
        fileMenu.addAction('保存(&S)', self.saveFile, 'Ctrl+S')
        fileMenu.addAction('另存为(&A)...', self.saveAnotherFile, 'Ctrl+Alt+S')
        fileMenu.addAction('导入(&I)...', self.importFile, 'Ctrl+I')
        fileMenu.addAction('导出(&E)...', self.exportFile, 'Ctrl+E')
        fileMenu.addAction('退出(&X)', self.close, 'Alt+F4')

    # --------------------------------------------------------------------------
    # Setup setting menu
    # --------------------------------------------------------------------------
    def setupSettingMenu(self):
        settingMenu = QMenu('设置(&S)', self)
        self.menuBar().addMenu(settingMenu)

        settingMenu.addAction('汇编器设置', self.setting, 'F6')
        settingMenu.addAction('伪指令', self.pseudoIns, 'F7')

    # --------------------------------------------------------------------------
    # Setup assemble menu
    # --------------------------------------------------------------------------
    def setupAssembleMenu(self):
        assembleMenu = QMenu('汇编(&A)', self)
        self.menuBar().addMenu(assembleMenu)

        assembleMenu.addAction('汇编(&A)', self.assemble, 'F9')
        assembleMenu.addAction('反汇编(&D)', self.disassemble, 'F10')
        assembleMenu.addAction('模拟(&S)', self.simulate, 'F11')

    # --------------------------------------------------------------------------
    # Setup help menu
    # --------------------------------------------------------------------------
    def setupHelpMenu(self):
        helpMenu = QMenu("帮助(&H)", self)
        self.menuBar().addMenu(helpMenu)

        helpMenu.addAction('关于(&A)', self.about)

    # --------------------------------------------------------------------------
    # Setup mips editor
    # --------------------------------------------------------------------------
    def setupEditor(self):
        self.editor = MipsEditor()
        self.editor.textChanged.connect(self.setDirty)
        self.highlighter = MipsHighlighter(self.editor.document())

    # --------------------------------------------------------------------------
    # Setup dockable widgets
    # --------------------------------------------------------------------------
    def setupDockable(self):
        self.msgBrowser = MessageBrowser()
        self.bottomDock = QDockWidget('信息', self)
        self.bottomDock.setFeatures(QDockWidget.DockWidgetClosable)
        self.bottomDock.setWidget(self.msgBrowser)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.bottomDock)
        self.bottomDock.hide()

        self.binBrowser = BinBrowser()
        self.rightDock = QDockWidget('机器码', self)
        self.rightDock.setFeatures(QDockWidget.DockWidgetClosable)
        self.rightDock.setWidget(self.binBrowser)
        self.addDockWidget(Qt.RightDockWidgetArea, self.rightDock)
        self.rightDock.hide()
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):

        # ============================================================================
        # Header

        MainWindow.setObjectName("")
        MainWindow.setMinimumSize(603, 534)
        MainWindow.setMaximumSize(603, 534)

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        # =================Sessao de Empresa Ativa====================
        self.LabelCnpjCompany = QtWidgets.QLabel(self.centralwidget)
        self.LabelCnpjCompany.setGeometry(QtCore.QRect(240, 0, 90, 21))
        self.LabelCnpjCompany.setText("CNPJ: ")

        self.ActiveCNPJ = QtWidgets.QLabel(self.centralwidget)
        self.ActiveCNPJ.setGeometry(QtCore.QRect(280, 0, 111, 21))
        self.ActiveCNPJ.setText("")
        self.ActiveCNPJ.setObjectName("ActiveCNPJ")

        self.TxtCnpjCompany = QtWidgets.QLabel(self.centralwidget)
        self.TxtCnpjCompany.setGeometry(QtCore.QRect(420, 0, 90, 21))
        self.TxtCnpjCompany.setText("Empresa: ")

        self.ActiveCompany = QtWidgets.QLabel(self.centralwidget)
        self.ActiveCompany.setGeometry(QtCore.QRect(486, 0, 111, 21))
        self.ActiveCompany.setText("")
        self.ActiveCompany.setObjectName("ActiveCompany")
        # ====================================================================================

        # ====================================================================================
        #                   Criar Menu
        # ====================================================================================

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 603, 22))
        self.menubar.setObjectName("menubar")

        self.menuEmpresa = QtWidgets.QMenu(self.menubar)
        self.menuEmpresa.setObjectName("menuEmpresa")

        self.menuImportar = QtWidgets.QMenu(self.menubar)
        self.menuImportar.setObjectName("menuImportar")

        self.menuExportar = QtWidgets.QMenu(self.menubar)
        self.menuExportar.setObjectName("menuExportar")

        self.menuAnalise = QtWidgets.QMenu(self.menubar)
        self.menuAnalise.setObjectName('menuAnalise')

        self.menuCorrecoes = QtWidgets.QMenu(self.menubar)
        self.menuCorrecoes.setObjectName("menuCorrecoes")

        self.menuUteis = QtWidgets.QMenu(self.menubar)
        self.menuUteis.setObjectName('menuUteis')

        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        # ====================================================================================

        # ====================================================================================
        # Criação das telas
        # ====================================================================================
        self.AlertScreen = QDockWidget(self.centralwidget)
        self.AlertScreen.hide()
        # ==================Ativar Empresa====================================================
        self.AtivarEmpresaScreen = QDockWidget(self.centralwidget)
        self.AtivarEmpresaScreen.hide()

        # ==================Cadastrar Empresa=================================================
        self.CadastrarEmpresaScreen = QDockWidget(self.centralwidget)
        self.CadastrarEmpresaScreen.hide()

        # ==================Editar Empresa====================================================
        self.EditarEmpresaScreen = QDockWidget(self.centralwidget)
        self.EditarEmpresaScreen.hide()
        # ====================================================================================

        # ==================Importar XML====================================================
        self.ImportarXMLScreen = QDockWidget(self.centralwidget)
        self.ImportarXMLScreen.hide()
        # ====================================================================================

        # ==================Importar Registro C170============================================
        self.ImportarC170Screen = QDockWidget(self.centralwidget)
        self.ImportarC170Screen.hide()
        # ====================================================================================

        # ==================Corrigir cadastro - CEST==========================================
        self.CorrgirCestScreen = QDockWidget(self.centralwidget)
        self.CorrgirCestScreen.hide()
        # ====================================================================================

        # ==================Corrigir cadastro - 0220==========================================
        self.Corrgir0220Screen = QDockWidget(self.centralwidget)
        self.Corrgir0220Screen.hide()
        # ====================================================================================

        # ==================XML em SPED=======================================================
        self.XMLinSPEDScreen = QDockWidget(self.centralwidget)
        self.XMLinSPEDScreen.hide()
        # ====================================================================================

        # ==================Calcular Quant ICMS Ressarcimento=================================
        self.Calc_Quant_ICMS_RessarScreen = QDockWidget(self.centralwidget)
        self.Calc_Quant_ICMS_RessarScreen.hide()
        # ====================================================================================

        # ==================Exportar Saldo Inicial - Tela=====================================
        self.ExportarSaldoInicialScreen = QDockWidget(self.centralwidget)
        self.ExportarSaldoInicialScreen.hide()
        # ====================================================================================

        # ==================Exportar Saldo Inicial - Tela=====================================
        self.FindXMlWithoutStScreen = QDockWidget(self.centralwidget)
        self.FindXMlWithoutStScreen.hide()
        # ====================================================================================

        # ==================Importar Cadatro produtis - Tela==================================
        self.CadstroProdutosScreen = QDockWidget(self.centralwidget)
        self.CadstroProdutosScreen.hide()
        # ====================================================================================

        # ==================Importar Registro H010- Tela======================================
        self.ImportarRegistroH010Screen = QDockWidget(self.centralwidget)
        self.ImportarRegistroH010Screen.hide()
        # ====================================================================================

        # ==================Importar Codigo de Relacionamento Tela============================
        self.ImportarCodigoRelacionamentoScreen = QDockWidget(
            self.centralwidget)
        self.ImportarCodigoRelacionamentoScreen.hide()
        # ====================================================================================

        # ====================================================================================
        self.actionAtivar_empresa = QtWidgets.QAction(MainWindow)
        self.actionAtivar_empresa.setObjectName("actionAtivar_empresa")
        self.actionAtivar_empresa.triggered.connect(
            lambda: self.handleAtiverEmpresa())

        self.actionCadastrar = QtWidgets.QAction(MainWindow)
        self.actionCadastrar.setObjectName("actionCadastrar")
        self.actionCadastrar.triggered.connect(
            lambda: self.handleCadastrarEmpresa())

        #====================Action Importar XML ====================================
        self.actionXML_Entrada = QtWidgets.QAction(MainWindow)
        self.actionXML_Entrada.setObjectName("actionXML_Entrada")
        self.actionXML_Entrada.triggered.connect(
            lambda: self.handleImportarXML())
        #===========================================================================

        #===================Action Editar===========================================
        self.actionEditar = QtWidgets.QAction(MainWindow)
        self.actionEditar.setObjectName("actionEditar")
        self.actionEditar.triggered.connect(lambda: self.handleEditarEmpresa())
        #===========================================================================

        self.actionCodigo_de_relacionamento_2 = QtWidgets.QAction(MainWindow)
        self.actionCodigo_de_relacionamento_2.setObjectName(
            "actionCodigo_de_relacionamento_2")

        self.actionGerar_SPED_com_0220 = QtWidgets.QAction(MainWindow)
        self.actionGerar_SPED_com_0220.setObjectName(
            "actionGerar_SPED_com_0220")

        #====================SPED_Corrigir_CEST=======================================
        self.actionAdicionar_SPED_Corrigir_CEST = QtWidgets.QAction(MainWindow)
        self.actionAdicionar_SPED_Corrigir_CEST.setObjectName(
            "actionAdicionar_SPED_Corrigir_CEST")
        self.actionAdicionar_SPED_Corrigir_CEST.triggered.connect(
            lambda: self.handleCorrgirCest())
        #=============================================================================

        #====================Action Registro C170 ====================================
        self.actionRegistro_C170_SPED = QtWidgets.QAction(MainWindow)
        self.actionRegistro_C170_SPED.setObjectName("actionRegistro_C170_SPED")
        self.actionRegistro_C170_SPED.triggered.connect(
            lambda: self.handleImportarC170())
        #=============================================================================

        #====================Action adicionar 0220====================================
        self.actionAdicionar_registro_0220_no_SPED = QtWidgets.QAction(
            MainWindow)
        self.actionAdicionar_registro_0220_no_SPED.setObjectName(
            "actionAdicionar_registro_0220_no_SPED")
        self.actionAdicionar_registro_0220_no_SPED.triggered.connect(
            lambda: self.handleCorrgir0220())
        #=============================================================================

        self.actionFator_de_convers_o = QtWidgets.QAction(MainWindow)
        self.actionFator_de_convers_o.setObjectName("actionFator_de_convers_o")

        # ======================Calcular SALDO INICIAL================================
        self.actionSaldo_inicial = QtWidgets.QAction(MainWindow)
        self.actionSaldo_inicial.setObjectName("actionSaldo_inicial")
        self.actionSaldo_inicial.triggered.connect(
            lambda: self.handleCalSaldoInicial())
        # =============================================================================
        self.actionVerificarXMLInSPED = QtWidgets.QAction(MainWindow)
        self.actionVerificarXMLInSPED.setObjectName(
            "actionactionVerificarXMLInSPED")
        self.actionVerificarXMLInSPED.triggered.connect(
            lambda: self.handleXMLInSPED())

        # =========================Action calcular quant icms ressarcimento============
        self.actionCalcQuantICMSRessar = QtWidgets.QAction(MainWindow)
        self.actionCalcQuantICMSRessar.setObjectName(
            "actionCalcQuantICMSRessar")
        self.actionCalcQuantICMSRessar.triggered.connect(
            lambda: self.handleCalcularICMSRessarcimento())
        # =============================================================================

        # =========================Action Encontar XML sem ST============
        self.actionFindXMLWitoughtST = QtWidgets.QAction(MainWindow)
        self.actionFindXMLWitoughtST.setObjectName("actionFindXMLWitoughtST")
        self.actionFindXMLWitoughtST.triggered.connect(
            lambda: self.handleFindXMLWhithoughtST())
        # =============================================================================

        # =========================Action Impoartar Cadastro produtos==================
        self.actionImportarCadastroProduto = QtWidgets.QAction(MainWindow)
        self.actionImportarCadastroProduto.setObjectName(
            "actionImportarCadastroProduto")
        self.actionImportarCadastroProduto.triggered.connect(
            lambda: self.handleCadastroProdutos())
        # =============================================================================

        # =========================Action importar Registro H010=======================
        self.actionImportarRegistroH010 = QtWidgets.QAction(MainWindow)
        self.actionImportarRegistroH010.setObjectName(
            "actionImportarRegistroH010")
        self.actionImportarRegistroH010.triggered.connect(
            lambda: self.handleImportarRegistroH010())
        # =============================================================================

        # =========================Action importar Codigo de Relacionamento============
        self.actionImportarCodigoRelacionamento = QtWidgets.QAction(MainWindow)
        self.actionImportarCodigoRelacionamento.setObjectName(
            "actionImportarCodigoRelacionamento")
        self.actionImportarCodigoRelacionamento.triggered.connect(
            lambda: self.handleImportarCodigoRelacionamento())
        # =============================================================================

        # ======================= Adicionar Ações no menu =============================

        self.menuEmpresa.addAction(self.actionAtivar_empresa)
        self.menuEmpresa.addAction(self.actionCadastrar)
        self.menuEmpresa.addAction(self.actionEditar)

        self.menuImportar.addAction(self.actionXML_Entrada)
        self.menuImportar.addAction(self.actionRegistro_C170_SPED)
        self.menuImportar.addAction(self.actionFator_de_convers_o)
        self.menuImportar.addAction(self.actionImportarCadastroProduto)
        self.menuImportar.addAction(self.actionImportarRegistroH010)
        self.menuImportar.addAction(self.actionImportarCodigoRelacionamento)

        self.menuExportar.addAction(self.actionCodigo_de_relacionamento_2)
        self.menuExportar.addAction(self.actionSaldo_inicial)

        self.menuAnalise.addAction(self.actionVerificarXMLInSPED)

        self.menuCorrecoes.addAction(self.actionAdicionar_SPED_Corrigir_CEST)
        self.menuCorrecoes.addAction(
            self.actionAdicionar_registro_0220_no_SPED)

        self.menuUteis.addAction(self.actionCalcQuantICMSRessar)
        self.menuUteis.addAction(self.actionFindXMLWitoughtST)

        self.menubar.addAction(self.menuEmpresa.menuAction())
        self.menubar.addAction(self.menuImportar.menuAction())
        self.menubar.addAction(self.menuExportar.menuAction())
        self.menubar.addAction(self.menuAnalise.menuAction())
        self.menubar.addAction(self.menuCorrecoes.menuAction())
        self.menubar.addAction(self.menuUteis.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.ActiveCompany.setWhatsThis(
            _translate(
                "MainWindow",
                "<html><head/><body><p>Empresa ativa</p></body></html>"))
        self.menuEmpresa.setTitle(_translate("MainWindow", "Empresa"))
        self.menuImportar.setTitle(_translate("MainWindow", "Importar"))
        self.menuExportar.setTitle(_translate("MainWindow", "Exportar"))
        self.menuAnalise.setTitle(_translate("MainWindow", "Analises"))
        self.menuCorrecoes.setTitle(_translate("MainWindow", "Correções"))
        self.menuUteis.setTitle(_translate("MainWindow", "Uteis"))

        self.actionAtivar_empresa.setText(_translate("MainWindow", "Ativar"))
        self.actionCadastrar.setText(_translate("MainWindow", "Cadastrar"))
        self.actionXML_Entrada.setText(_translate("MainWindow", "XML Entrada"))

        self.actionEditar.setText(_translate("MainWindow", "Editar"))
        self.actionCodigo_de_relacionamento_2.setText(
            _translate("MainWindow", "Codigo de relacionamento"))

        self.actionGerar_SPED_com_0220.setText(
            _translate("MainWindow", "Adicionar registro 0220 no SPED"))

        self.actionAdicionar_SPED_Corrigir_CEST.setText(
            _translate("MainWindow", "SPED - Corrigir CEST"))

        self.actionRegistro_C170_SPED.setText(
            _translate("MainWindow", "Registro C170 - SPED"))

        self.actionAdicionar_registro_0220_no_SPED.setText(
            _translate("MainWindow", "SPED - Adicionar 0220"))

        self.actionFator_de_convers_o.setText(
            _translate("MainWindow", "Fator de conversão"))

        self.actionSaldo_inicial.setText(
            _translate("MainWindow", "Saldo inicial"))

        self.actionVerificarXMLInSPED.setText(
            _translate("MainWindow", "Verificar XML em SPED"))

        self.actionCalcQuantICMSRessar.setText(
            _translate("MainWindow", "Calcular ICMS Ressarcimento"))

        self.actionFindXMLWitoughtST.setText(
            _translate("MainWindow", "Encontrar XML Transf S/ ST"))

        self.actionImportarCadastroProduto.setText(
            _translate("MainWindow", "Cadastro de Produtos"))

        self.actionImportarRegistroH010.setText(
            _translate("MainWindow", "Registro H010"))

        self.actionImportarCodigoRelacionamento.setText(
            _translate("MainWindow", "Codigo Relacionamento"))

    def handleAtiverEmpresa(self):
        AtivarFeature(self.AtivarEmpresaScreen, self.ActiveCompany,
                      self.ActiveCNPJ)

    def handleCadastrarEmpresa(self):
        CadastrarFeature(self.CadastrarEmpresaScreen)

    def handleImportarXML(self):
        XMLFeature(self.ImportarXMLScreen, self.ActiveCNPJ, self.AlertScreen)

    def handleImportarC170(self):
        RegistroC170Feature(self.ImportarC170Screen, self.ActiveCNPJ)

    def handleCorrgirCest(self):
        CorrigirCestFeature(self.CorrgirCestScreen, self.ActiveCNPJ)

    def handleCorrgir0220(self):
        Corrigir0220Feature(self.Corrgir0220Screen, self.ActiveCNPJ)

    def handleEditarEmpresa(self):
        EditarFeature(self.EditarEmpresaScreen, self.ActiveCNPJ)

    def handleXMLInSPED(self):
        XMLInSPEDFeature(self.XMLinSPEDScreen, self.ActiveCNPJ)

    def handleCalcularICMSRessarcimento(self):
        CalcICMSRessarFeature(self.XMLinSPEDScreen, self.ActiveCNPJ)

    def handleCalSaldoInicial(self):
        SaldoInicialFeature(self.ExportarSaldoInicialScreen, self.ActiveCNPJ)

    def handleFindXMLWhithoughtST(self):
        FindXMlWithoutStFeature(self.FindXMlWithoutStScreen, self.ActiveCNPJ)

    def handleCadastroProdutos(self):
        ImportarCadastroProdutosFeature(self.FindXMlWithoutStScreen,
                                        self.ActiveCNPJ)

    def handleImportarRegistroH010(self):
        RegistroH010Feature(self.FindXMlWithoutStScreen, self.ActiveCNPJ)

    def handleImportarCodigoRelacionamento(self):
        ImportarCodigoRelacionamentoFeature(self.FindXMlWithoutStScreen,
                                            self.ActiveCNPJ)
示例#17
0
class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()

        self.setWindowTitle('MIPS')  # 窗口标题

        # 设置各项菜单
        self.setupFileMenu()
        self.setupAssembleMenu()
        self.setupDebugMenu()
        self.setupHelpMenu()

        self.setupEditor()  # 设置编辑器
        self.setCentralWidget(self.editor)

        self.setupDock()  # 设置Dock栏

    def setupEditor(self):
        self.editor = Editor()  # 创建编辑器对象

    def setupFileMenu(self):
        fileMenu = QMenu('文件(&F)', self)
        self.menuBar().addMenu(fileMenu)

        self.currentFile = ''  # 设置当前文件路径为空值

        fileMenu.addAction('新建(&N)', self.newFile, 'Ctrl+N')  # 新建立一个文件
        fileMenu.addAction('打开(&O)...', self.openFile, 'Ctrl+O')  # 打开已有的文件
        fileMenu.addAction('保存(&S)', self.saveFile, 'Ctrl+S')  # 将当前文件保存
        fileMenu.addAction('另存为(&A)...', self.saveAnotherFile,
                           'Ctrl+Alt+S')  # 将当前文件保存到指定路径
        fileMenu.addAction('退出(&X)', self.close, 'Ctrl+F4')  # 退出MIPS汇编器

    def setupAssembleMenu(self):
        assembleMenu = QMenu('汇编(&A)', self)
        self.menuBar().addMenu(assembleMenu)

        self.assembler = Assembler()  # 创建汇编器对象

        assembleMenu.addAction('汇编(&A)', self.assemble, 'F10')  # 对当前代码实行汇编操作
        assembleMenu.addAction('反汇编(&D)', self.disassemble,
                               'F11')  # 对当前代码实行反汇编操作

    def setupDebugMenu(self):
        assembleMenu = QMenu('调试(&D)', self)
        self.menuBar().addMenu(assembleMenu)

        self.isStart = False  # 设置是否开始调试布尔值为否

        assembleMenu.addAction('启动调试(&S)', self.startDebug, 'F5')  # 启动调试
        assembleMenu.addAction('继续调试(&C)', self.contiuneDebug,
                               'F5')  # 将调试进行到最后一步
        assembleMenu.addAction('单步执行(&I)', self.nextDebug, 'F11')  # 单步进行调试
        assembleMenu.addAction('停止调试(&S)', self.stopDebug,
                               'Shift+F5')  # 停止调试过程
        assembleMenu.addAction('重启调试(&R)', self.resetDebug,
                               'Ctrl+Shift+F5')  # 重新启动调试过程

    def setupHelpMenu(self):
        helpMenu = QMenu("帮助(&H)", self)
        self.menuBar().addMenu(helpMenu)

        helpMenu.addAction('关于(&A)', self.about)  # 本程序的小介绍

    def setupDock(self):
        # 建立输出运行结果的窗口
        self.rightBrowser = Browser()  # 建立在窗口右端
        self.rightDock = QDockWidget('运行结果/内存', self)
        self.rightDock.setFeatures(QDockWidget.DockWidgetClosable)
        self.rightDock.setWidget(self.rightBrowser)
        self.addDockWidget(Qt.RightDockWidgetArea, self.rightDock)
        self.rightDock.hide()  # 窗口自动隐藏

        # 建立输出调试过程的窗口
        self.bottomBrowser = Browser()  # 建立在窗口底端
        self.bottomDock = QDockWidget('调试窗口', self)
        self.bottomDock.setFeatures(QDockWidget.DockWidgetClosable)
        self.bottomDock.setWidget(self.bottomBrowser)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.bottomDock)
        self.bottomDock.hide()

    def newFile(self):
        self.editor.clear()  # 清空当前屏幕
        self.rightDock.hide()  # 隐藏Dock栏
        self.bottomDock.hide()
        self.currentFile = ''
        return True

    def openFile(self):
        # 打开汇编文件或二进制文件
        path, _ = QFileDialog.getOpenFileName(
            self, '打开', '', '汇编文件 (*.asm);;二进制文件(*.coe *.bin)')

        if path:
            file = open(path, 'r')
            self.editor.setPlainText(file.read())
            file.close()

            self.rightDock.hide()
            self.bottomDock.hide()

            self.currentFile = path
            return True

        return False

    def saveFile(self):
        # 如果没有文件名则跳转到另存为
        if not self.currentFile:
            return self.saveAnotherFile()

        # 将编辑器内容写入到当前路径文件
        file = open(self.currentFile, 'w')
        file.write(self.editor.toPlainText())
        file.close()

        return True

    def saveAnotherFile(self):
        # 选择存入文件路径
        path, _ = QFileDialog.getSaveFileName(
            self, '另存为', self.currentFile if self.currentFile else '',
            '汇编文件 (*.asm);;二进制文件(*.coe *.bin)')

        # 路径存在则将编辑器内容写入
        if path:
            file = open(path, 'w')
            file.write(self.editor.toPlainText())
            file.close()

            self.currentFile = path
            return True

        return False

    def assemble(self):
        self.saveFile()  # 执行前保存文件

        try:
            self.rightBrowser.setText(self.assembler.assembly(
                self.currentFile))  # 执行汇编并在右侧输出结果
        except:
            self.rightBrowser.setText(
                'error!!! \ncheck your code!!!')  # 代码有误不能正确汇编
        return self.rightDock.show()

    def disassemble(self):
        self.saveFile()

        try:
            self.rightBrowser.setText(
                self.assembler.disassembly(self.currentFile))  # 执行反汇编并在右侧输出结果
        except:
            self.rightBrowser.setText(
                'error!!! \ncheck your code!!!')  # 代码有误不能正确反汇编
        return self.rightDock.show()

    def startDebug(self):
        self.saveFile()

        self.assembler.step = 0  # 初始化执行步数
        self.debugStr = ''  # 初始化结果字符
        self.isStart = True  # 设定已经开始

        # 初始化寄存器内容
        for k in self.assembler.registers:
            self.assembler.registers[k] = '00000000'
        self.assembler.memory = {}  # 初始化内存

        try:
            self.assembler.debug(self.currentFile)
            self.debugStr = str(self.assembler.memory).strip("{}").replace(
                "'", '').replace(':', ' ').replace(',', ' ')  # 执行单步模拟操作
        except:
            self.debugStr += '\nthe debug is over\nnow check your code'  # 模拟完成或代码有误则停止
            return False

        # 将寄存器内容展示在底部,结果展示在右部
        self.bottomBrowser.setText(' ' + str(self.assembler.registers).strip(
            "{},").replace(':', '\t').replace(',', '\t').replace("'", ''))
        self.rightBrowser.setText(self.debugStr)
        self.rightDock.show()
        self.bottomDock.show()
        return True

    def contiuneDebug(self):
        # 如果没有开始则开始调试
        if not self.isStart:
            self.startDebug()

        # 模拟进行到最后一步
        while self.nextDebug():
            continue

        self.bottomBrowser.setText(
            str(self.assembler.registers).strip("{},").replace(
                ':', '\t').replace(',', '\t').replace("'", ''))
        self.rightBrowser.setText(self.debugStr)
        self.rightDock.show()
        self.bottomDock.show()
        return True

    def nextDebug(self):
        if not self.isStart:
            return self.startDebug()

        try:
            self.assembler.debug(self.currentFile)
            self.debugStr = str(self.assembler.memory).strip("{}").replace(
                "'", '').replace(':', ' ').replace(',', ' ')
        except:
            self.debugStr += '\nthe debug is over\nnow check your code'
            self.rightBrowser.setText(self.debugStr)
            self.rightDock.show()
            return False

        self.bottomBrowser.setText(
            str(self.assembler.registers).strip("{},").replace(
                ':', '\t').replace(',', '\t').replace("'", ''))
        self.rightBrowser.setText(self.debugStr)
        self.rightDock.show()
        self.bottomDock.show()
        return True

    def stopDebug(self):
        self.isStart = False  # 结束调试并将开始置否
        self.bottomDock.hide()
        self.rightDock.hide()
        return True

    def resetDebug(self):
        self.stopDebug()
        return self.startDebug()

    def about(self):
        # 简短介绍本程序
        QMessageBox.about(
            self, '关于本MIPS汇编器', '<p style="font-size: 16px;">Made By Aaron</p>'
            '<p style="font-size: 16px;">可实现MIPS汇编器(支持伪码),反汇编器,调试器</p>'
            '<p style="font-size: 16px;">介绍请见README.md</p>'
            '<p style="font-size: 16px;">具体细节请参考实验报告')
示例#18
0
class _QtDock(_AbstractDock):
    def _dock_initialize(self):
        self.dock = QDockWidget()
        self.scroll = QScrollArea(self.dock)
        self.dock.setWidget(self.scroll)
        widget = QWidget(self.scroll)
        self.scroll.setWidget(widget)
        self.scroll.setWidgetResizable(True)
        self.dock.setAllowedAreas(Qt.LeftDockWidgetArea)
        self.dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.plotter.app_window.addDockWidget(Qt.LeftDockWidgetArea, self.dock)
        self.dock_layout = QVBoxLayout()
        widget.setLayout(self.dock_layout)

    def _dock_finalize(self):
        self.dock.setMinimumSize(self.dock.sizeHint().width(), 0)
        self._dock_add_stretch(self.dock_layout)

    def _dock_show(self):
        self.dock.show()

    def _dock_hide(self):
        self.dock.hide()

    def _dock_add_stretch(self, layout):
        layout.addStretch()

    def _dock_add_layout(self, vertical=True):
        layout = QVBoxLayout() if vertical else QHBoxLayout()
        return layout

    def _dock_add_label(self, value, align=False, layout=None):
        layout = self.dock_layout if layout is None else layout
        widget = QLabel()
        if align:
            widget.setAlignment(Qt.AlignCenter)
        widget.setText(value)
        layout.addWidget(widget)
        return widget

    def _dock_add_button(self, name, callback, layout=None):
        layout = self.dock_layout if layout is None else layout
        # If we want one with text instead of an icon, we should use
        # QPushButton(name)
        widget = QToolButton()
        widget.clicked.connect(callback)
        widget.setText(name)
        layout.addWidget(widget)
        return widget

    def _dock_named_layout(self, name, layout, compact):
        layout = self.dock_layout if layout is None else layout
        if name is not None:
            hlayout = self._dock_add_layout(not compact)
            self._dock_add_label(value=name, align=not compact, layout=hlayout)
            layout.addLayout(hlayout)
            layout = hlayout
        return layout

    def _dock_add_slider(self,
                         name,
                         value,
                         rng,
                         callback,
                         compact=True,
                         double=False,
                         layout=None,
                         stretch=0):
        layout = self._dock_named_layout(name, layout, compact)
        slider_class = QFloatSlider if double else QSlider
        cast = float if double else int
        widget = slider_class(Qt.Horizontal)
        widget.setMinimum(cast(rng[0]))
        widget.setMaximum(cast(rng[1]))
        widget.setValue(cast(value))
        widget.valueChanged.connect(callback)
        layout.addWidget(widget)
        return widget

    def _dock_add_spin_box(self,
                           name,
                           value,
                           rng,
                           callback,
                           compact=True,
                           double=True,
                           layout=None):
        layout = self._dock_named_layout(name, layout, compact)
        value = value if double else int(value)
        widget = QDoubleSpinBox() if double else QSpinBox()
        widget.setAlignment(Qt.AlignCenter)
        widget.setMinimum(rng[0])
        widget.setMaximum(rng[1])
        inc = (rng[1] - rng[0]) / 20.
        inc = max(int(round(inc)), 1) if not double else inc
        widget.setKeyboardTracking(False)
        widget.setSingleStep(inc)
        widget.setValue(value)
        widget.valueChanged.connect(callback)
        layout.addWidget(widget)
        return widget

    def _dock_add_combo_box(self,
                            name,
                            value,
                            rng,
                            callback,
                            compact=True,
                            layout=None):
        layout = self._dock_named_layout(name, layout, compact)
        widget = QComboBox()
        widget.addItems(rng)
        widget.setCurrentText(value)
        widget.currentTextChanged.connect(callback)
        widget.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        layout.addWidget(widget)
        return widget

    def _dock_add_group_box(self, name, layout=None):
        layout = self.dock_layout if layout is None else layout
        hlayout = QVBoxLayout()
        widget = QGroupBox(name)
        widget.setLayout(hlayout)
        layout.addWidget(widget)
        return hlayout
示例#19
0
class pyviViewerWindow(QtGui.QMainWindow):
    def __init__(self, flowchart):
        QtGui.QMainWindow.__init__(self)
        self.resize(1000, 800)
        self.setWindowTitle('Viewer')

        self.fc = flowchart
        self.fc.sigChartChanged.connect(self.nodeEvent)
        self.fc.sigChartLoaded.connect(self.loadChartEvent)
        self.fc.widget().resize(1000, 800)

        self.pyviwin = SimpleWindow()
        ## http://blog.qt.io/blog/2013/02/19/introducing-qwidgetcreatewindowcontainer/
        pyvi_widget = QWidget.createWindowContainer(self.pyviwin)
        pyvi_widget.setMinimumSize(200, 200)
        pyvi_widget.resize(800, 800)
        self.setCentralWidget(pyvi_widget)

        self.layerDockWidget = QDockWidget('Layers')
        self.layerDockWidget.setFeatures(QDockWidget.DockWidgetFloatable
                                         | QDockWidget.DockWidgetMovable)
        self.layerDockWidget.setWidget(self.pyviwin.layerWidget)
        self.pyviwin.layerWidget.resize(200, 500)
        self.addDockWidget(Qt.RightDockWidgetArea, self.layerDockWidget)

        self.plotDockWidget = QDockWidget('Plot')
        self.plotDockWidget.setFeatures(QDockWidget.DockWidgetFloatable
                                        | QDockWidget.DockWidgetMovable
                                        | QDockWidget.DockWidgetClosable)
        self.plotWidget = PlotWidget()
        self.plotDockWidget.setWidget(self.plotWidget)
        self.plotWidget.resize(100, 100)
        # self.plotDockWidget.show()
        # self.addDockWidget(Qt.RightDockWidgetArea, self.plotDockWidget)

        self.plotList = {'plot 1': self.plotWidget}

        self.plot3DDockWidget = QDockWidget('Plot3D')
        self.plot3DDockWidget.setFeatures(QDockWidget.DockWidgetFloatable
                                          | QDockWidget.DockWidgetMovable
                                          | QDockWidget.DockWidgetClosable)
        self.pyviwin_plot = SimpleWindow()
        pyviwin_plot_widget = QWidget.createWindowContainer(self.pyviwin_plot)
        pyviwin_plot_widget.setMinimumSize(100, 100)
        pyviwin_plot_widget.resize(200, 200)
        self.plot3DDockWidget.setWidget(pyviwin_plot_widget)
        self.plot3DDockWidget.show()
        # self.plot3D.resize(100,100)

        self.plotLayerDockWidget = QDockWidget('Plot Layers')
        self.plotLayerDockWidget.setFeatures(QDockWidget.DockWidgetFloatable
                                             | QDockWidget.DockWidgetMovable)
        self.plotLayerDockWidget.setWidget(self.pyviwin_plot.layerWidget)
        self.pyviwin_plot.layerWidget.resize(200, 500)
        self.addDockWidget(Qt.RightDockWidgetArea, self.plotLayerDockWidget)

        # self.dockWidgetDict = {}

        self.createActions()
        self.createMenus()

        self.show()
        self.fc.widget().show()

    def save(self):
        try:
            self.fc.saveFile()
        except:
            raise

    def open(self):
        self.fc.loadFile()

    def createActions(self):
        self.saveAct = QAction("&Save...",
                               self,
                               shortcut=QtGui.QKeySequence.Save,
                               statusTip="Save the current form letter",
                               triggered=self.save)

        self.openAct = QAction("&Open...",
                               self,
                               shortcut=QtGui.QKeySequence.Open,
                               statusTip="Save the current form letter",
                               triggered=self.open)

        self.reloadAct = QAction("&Reload nodelibs...",
                                 self,
                                 shortcut=QtGui.QKeySequence.Refresh,
                                 statusTip="Reload nodelibraries",
                                 triggered=self.fc.widget().reloadLibrary)

        self.quitAct = QAction("&Quit",
                               self,
                               shortcut=QtGui.QKeySequence.Quit,
                               statusTip="Quit the application",
                               triggered=self.close)

        self.toggleViewerAct = QAction("&Toggle Viewer",
                                       self,
                                       statusTip="Toggle viewer window",
                                       triggered=self.toggleViewer)

        self.toggleFlowchartAct = QAction("&Toggle Flowchart",
                                          self,
                                          statusTip="Toggle flowchart window",
                                          triggered=self.toggleFlowchart)

        self.togglePlotterAct = QAction("&Toggle Plotter",
                                        self,
                                        statusTip="Toggle plot window",
                                        triggered=self.togglePlotter)

    def toggleViewer(self):
        if self.isHidden():
            self.show()
        else:
            self.hide()

    def togglePlotter(self):
        if self.plotDockWidget.isHidden():
            self.plotDockWidget.show()
        else:
            self.plotDockWidget.hide()

    def toggleFlowchart(self):
        if self.fc.widget().isHidden():
            self.fc.widget().show()
        else:
            self.fc.widget().hide()

    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.reloadAct)
        # self.fileMenu.addSeparator()
        # self.fileMenu.addAction(self.quitAct)

        # self.editMenu = self.menuBar().addMenu("&Edit")
        # self.editMenu.addAction(self.undoAct)

        self.viewMenu = self.menuBar().addMenu("&View")
        self.viewMenu.addAction(self.toggleViewerAct)
        self.viewMenu.addAction(self.toggleFlowchartAct)
        self.viewMenu.addAction(self.togglePlotterAct)

    def loadChartEvent(self):
        # self.clearDock()
        for node in self.fc.nodes().values():
            self.addNode(node)

    def nodeEvent(self, flowchart, action, node):
        if action == 'add':
            self.addNode(node)
        elif action == 'remove':
            self.removeNode(node)
        elif action == 'rename':
            pass
            # try:
            #     self.dockWidgetDict[node].setWindowTitle(node.name())
            # except KeyError:
            #     pass

    def addNode(self, node):
        # ctrlWidget = node.ctrlWidget()
        # if ctrlWidget:
        #     dock = QDockWidget(node.name(), self)
        #     dock.setWidget(node.ctrlWidget())
        #     dock.hide()
        #     # nodeDock.hideTitleBar()
        #     # self.da.addDock(nodeDock, 'right', )
        #     self.addDockWidget(Qt.RightDockWidgetArea, dock)
        #     self.viewMenu.addAction(dock.toggleViewAction())
        #     self.dockWidgetDict[node] = dock
        if type(node) is pvWindowNode:
            node.setPyViWindow(self.pyviwin, self.pyviwin_plot)
        elif type(node) is PlotWidgetNode:
            node.setPlotList(self.plotList)
            node.setPlot(self.plotWidget)

    def removeNode(self, node):
        print("removing...", node)
示例#20
0
class OpenposeGUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("OpencvGUI")
        self.setWindowIcon(QIcon("icon/logo.png"))

        # QAction
        self.action_autosave = QAction(QIcon("icon/autosave.png"), "自动保存",
                                       self)
        self.action_save = QAction(QIcon("icon/save.png"), "保存", self)
        self.action_image = QAction(QIcon("icon/image.png"), "打开图片", self)
        self.action_video = QAction(QIcon("icon/video.png"), "打开视频", self)
        self.action_camera = QAction(QIcon("icon/camera.png"), "打开摄像头", self)
        self.action_folder = QAction(QIcon("icon/folder.png"), "打开文件夹", self)
        self.action_setting = QAction(QIcon("icon/setting.png"), "设置", self)
        self.action_filetree = QAction(QIcon("icon/filetree.png"), "目录树", self)
        self.action_camera.setCheckable(True)
        self.action_video.setCheckable(True)
        self.action_setting.setCheckable(True)
        self.action_filetree.setCheckable(True)
        self.action_autosave.setCheckable(True)

        # 菜单栏
        self.menu_bar = QMenuBar()
        self.menu_open = self.menu_bar.addMenu("Open")
        self.menu_open.addAction(self.action_image)
        self.menu_open.addAction(self.action_video)
        self.menu_open.addAction(self.action_camera)

        self.menu_view = self.menu_bar.addMenu("View")
        self.menu_view.addAction(self.action_setting)
        self.menu_view.addAction(self.action_filetree)

        self.menu_function = self.menu_bar.addMenu("Function")
        self.action_background = self.menu_function.addAction(
            "Black/RGB Blackground")
        self.action_geture = self.menu_function.addAction(
            "Gesture Recognition")

        self.setMenuBar(self.menu_bar)

        # 工具栏
        self.tool_bar = QToolBar()
        self.tool_bar.addAction(self.action_save)
        self.tool_bar.addAction(self.action_autosave)
        self.tool_bar.addSeparator()
        self.tool_bar.addAction(self.action_folder)
        self.tool_bar.addAction(self.action_camera)
        self.tool_bar.addAction(self.action_image)
        self.tool_bar.addAction(self.action_video)
        self.tool_bar.addSeparator()
        self.tool_bar.addAction(self.action_setting)
        self.tool_bar.addAction(self.action_filetree)
        self.addToolBar(self.tool_bar)

        # 状态栏
        self.status_bar = QStatusBar()
        self.status_fps = QLabel("FPS:00.0")
        self.status_bar.addPermanentWidget(self.status_fps)
        self.setStatusBar(self.status_bar)

        # 组件
        self.timer = QTimer()
        self.camera = Camera(self)
        self.setting_widget = SettingWidget(self)
        self.label_frame = LabelFrame(self)
        self.file_system_tree = FileSystemTreeView(self)
        self.openpose_model = OpenposeModel(self)
        self.media_control = MediaControl(self)
        self.save_widget = SaveWidget()
        self.gesture_model = GestureModel()

        # 设置dock
        self.dock_filetree = QDockWidget(self)
        self.dock_filetree.setWidget(self.file_system_tree)
        self.dock_file_label = QLabel("Current Directory")
        self.dock_file_label.setMinimumHeight(25)
        self.dock_file_label.setAlignment(Qt.AlignCenter | Qt.AlignHCenter)
        self.dock_filetree.setTitleBarWidget(self.dock_file_label)
        self.dock_filetree.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self.dock_filetree.hide()

        self.dock_setting = QDockWidget(self)
        self.dock_setting.setWidget(self.setting_widget)
        self.dock_setting_label = QLabel("Openpose Settings")
        self.dock_setting_label.setMinimumHeight(25)
        self.dock_setting_label.setAlignment(Qt.AlignCenter | Qt.AlignHCenter)
        self.dock_setting.setTitleBarWidget(self.dock_setting_label)
        self.dock_setting.setFeatures(QDockWidget.AllDockWidgetFeatures)
        self.dock_setting.hide()

        self.dock_media = QDockWidget(self)
        self.dock_media.setWidget(self.media_control)
        self.dock_media.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.dock_media.hide()

        self.setCentralWidget(self.label_frame)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_setting)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_filetree)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.dock_media)

        # 信号与槽

        self.setting_widget.horizontalSlider_Body.sliderReleased.connect(
            self.change_body_threshold)
        self.setting_widget.horizontalSlider_Face.sliderReleased.connect(
            self.change_face_threshold)
        self.setting_widget.horizontalSlider_Hand.sliderReleased.connect(
            self.change_hand_threshold)
        self.setting_widget.checkBox_body.stateChanged.connect(
            self.check_body)  # 状态改变触发check_box_changed函数
        self.setting_widget.checkBox_hand.stateChanged.connect(
            self.check_hand)  # 状态改变触发check_box_changed函数
        self.setting_widget.checkBox_face.stateChanged.connect(
            self.check_face)  # 状态改变触发check_box_changed函数
        self.setting_widget.radioButton_black.toggled.connect(
            self.change_background)

        self.setting_widget.comboBox_resolution.currentIndexChanged.connect(
            self.change_resolution)

        self.media_control.play_button.toggled.connect(self.play_media)

        self.action_image.triggered.connect(self.open_image)
        self.action_video.triggered.connect(self.open_video)
        self.action_folder.triggered.connect(self.open_folder)
        self.action_camera.triggered.connect(self.open_camera)
        self.action_filetree.triggered.connect(self.show_filetree)
        self.action_setting.triggered.connect(self.show_setting)
        self.action_autosave.triggered.connect(self.auto_save)

        self.action_save.triggered.connect(self.save_current)
        self.action_setting.triggered.connect(self.setting_widget.show)

        self.file_system_tree.doubleClicked.connect(self.open_image)
        self.camera.timer.timeout.connect(self.update)
        self.timer.timeout.connect(self.save_current)

    def update(self):
        start_time = time.time()
        frame = self.camera.frame()
        self.media_control.update(self.camera.frame_pos,
                                  self.camera.frame_count)
        if frame is None:
            return None
        result, keypoints = self.openpose_model(frame)
        result, keypoints = self.gesture_recognition(result, keypoints)

        message = self.generate_message(keypoints)
        self.label_frame.update_frame(result)
        fps = 1 / (time.time() - start_time)
        self.status_fps.setText("FPS:{:.1f}".format(fps))
        self.status_bar.showMessage(message, 2000)
        return result, keypoints

    def gesture_recognition(self, result, keypoints):
        """实现手势识别"""
        if self.setting_widget.gesture_on():
            hands = keypoints[1]
            person_num = hands[0].shape[0]
            for i in range(person_num):
                for hand in hands:
                    rect = self.gesture_model.hand_bbox(hand[i])
                    gesture = self.gesture_model(hand[i])
                    if rect:
                        print(rect)
                        x, y, w, h = rect
                        cv2.rectangle(result, (x, y), (x + w, y + h),
                                      (255, 255, 255))
                        cv2.putText(result, gesture, (x, y),
                                    cv2.FONT_HERSHEY_SIMPLEX, 1,
                                    (255, 255, 255))
        return result, keypoints

    def generate_message(self, keypoints):
        """获取识别结果信息"""
        if keypoints[0].size != 1:
            person_num = keypoints[0].shape[0]
            message = "person: {}".format(person_num)
            for i in range(person_num):
                message += " | person{}(".format(i + 1)
                if self.setting_widget.body_on():
                    pose_keypoints = keypoints[0][i, :, 2]
                    pose_detected = pose_keypoints[
                        pose_keypoints > self.setting_widget.body_threshold()]
                    message += "pose: {:>2d}/{}".format(pose_detected.size, 25)

                if self.setting_widget.hand_on():
                    right_hand_keypoinys = keypoints[1][0][i, :, 2]
                    left_hand_keypoinys = keypoints[1][1][i, :, 2]

                    right_hand_detected = right_hand_keypoinys[
                        right_hand_keypoinys >
                        self.setting_widget.hand_threshold()]
                    left_hand_detected = left_hand_keypoinys[
                        left_hand_keypoinys >
                        self.setting_widget.hand_threshold()]
                    message += " | right hand: {:>2d}/{}".format(
                        right_hand_detected.size, 21)
                    message += " | left hand: {:>2d}/{}".format(
                        left_hand_detected.size, 21)
                message += ")"
        else:
            message = "person: {}".format(0)
        return message

    def save_current(self):
        if not self.label_frame.pixmap():
            QMessageBox.warning(self, "Note", "No data in frame",
                                QMessageBox.Yes)
            return

        pixmap = self.label_frame.cvimg2pixmap(
            self.openpose_model.get_rendered_image())
        body_keypoints, hand_keypoints, face_keypoints = self.openpose_model.get_keypoints(
        )
        body_keypoints = copy.deepcopy(
            body_keypoints) if self.setting_widget.body_on() else None
        hand_keypoints = copy.deepcopy(
            hand_keypoints) if self.setting_widget.hand_on() else None
        face_keypoints = copy.deepcopy(
            face_keypoints) if self.setting_widget.face_on() else None
        keypoints = (body_keypoints, hand_keypoints, face_keypoints)

        if self.timer.isActive():
            self.save_widget.save(pixmap.copy(), *keypoints)
        else:
            message = self.generate_message(keypoints)
            self.save_widget.setFrame(pixmap.copy(), *keypoints, message)
            self.save_widget.show()

    def auto_save(self):
        if not self.camera.is_open():
            self.action_autosave.setChecked(False)
        if self.action_autosave.isChecked():
            self.timer.start(self.setting_widget.save_interval() * 1000)
        else:
            self.timer.stop()

    def update_setting(self):
        pass

    def update_openpose(self, key, value):
        pass

    # 槽函数

    # 参数
    def check_body(self, status):
        # 姿态估计
        flag = True if status == Qt.Checked else False
        render_pose = 1 if status == Qt.Checked else 0
        self.setting_widget.horizontalSlider_Body.setEnabled(flag)
        self.setting_widget.radioButton_black.setEnabled(flag)
        self.setting_widget.radioButton_rgb.setEnabled(flag)
        self.openpose_model.update_wrapper("render_pose", render_pose)

    def check_hand(self, status):
        # 手部估计
        flag = True if status == Qt.Checked else False
        self.setting_widget.horizontalSlider_Hand.setEnabled(flag)
        self.setting_widget.checkBox_gesture.setEnabled(flag)
        self.openpose_model.update_wrapper("hand", flag)

    def check_face(self, status):
        # 脸部估计
        flag = True if status == Qt.Checked else False
        self.setting_widget.horizontalSlider_Face.setEnabled(flag)
        self.setting_widget.checkBox_emotion.setEnabled(flag)
        self.openpose_model.update_wrapper("face", flag)

    def change_body_threshold(self):
        # 姿态估计阈值
        value = self.setting_widget.body_threshold()
        self.setting_widget.label_threshold_body.setText(str(value * 100))
        self.openpose_model.update_wrapper("render_threshold", value)

    def change_hand_threshold(self):
        # 手部估计阈值
        value = self.setting_widget.hand_threshold()
        self.setting_widget.label_threshold_hand.setText(str(value * 100))
        self.openpose_model.update_wrapper("hand_render_threshold", value)

    def change_face_threshold(self):
        # 脸部估计阈值
        value = self.setting_widget.face_threshold()
        self.setting_widget.label_threshold_face.setText(str(value * 100))
        self.openpose_model.update_wrapper("face_render_threshold", value)

    def change_resolution(self):
        resolution = self.setting_widget.net_resolution()
        self.openpose_model.update_wrapper("net_resolution", resolution)

    def change_background(self):
        # 背景
        self.openpose_model.update_wrapper(
            "disable_blending", self.setting_widget.black_background())

    # 功能
    def show_setting(self):
        if self.dock_setting.isHidden():
            self.dock_setting.show()
        else:
            self.dock_setting.hide()

    def show_filetree(self):
        if self.dock_filetree.isHidden():
            self.dock_filetree.show()
        else:
            self.dock_filetree.hide()

    def open_image(self, file_index=None):
        if file_index:
            file = self.file_system_tree.fileSystemModel.filePath(file_index)
        else:
            file, _ = QFileDialog.getOpenFileName(
                self, '请选择图片', './',
                'Image files(*.jpg *.png *.JPG *.PNG)')  # 可设置默认路径
        if not file or not file.endswith((".jpg", ".png", ".JPG", ".PNG")):
            return False
        image = cv2.imread(file)
        result, keypoints = self.openpose_model(image)
        message = self.generate_message(keypoints)
        # self.label_frame.resize(*image.shape[:2])
        self.label_frame.update_frame(result)
        self.status_bar.showMessage(message)

    def open_video(self):
        if self.action_video.isChecked():
            file, _ = QFileDialog.getOpenFileName(
                self, '请选择视频', './', 'Video files(*.mp4 *.avi)')  # 可设置默认路径
            if not file:
                self.action_video.setChecked(False)
                return
            self.camera.start(file)
            self.label_frame.resize(*self.camera.resolution)
            self.action_video.setIcon(QIcon('icon/stop.png'))
            self.update()  # 初始化画面
            self.camera.is_pause = True
            self.media_control.pause()
            self.dock_media.show()
        else:
            self.label_frame.clear()
            self.camera.stop()
            self.status_fps.setText("FPS:00.0")
            self.action_video.setIcon(QIcon("icon/video.png"))
            self.media_control.play()
            self.dock_media.hide()

    def open_folder(self):
        new_foler = QFileDialog.getExistingDirectory(self, '请选择目录',
                                                     './')  # 可设置默认路径
        if not new_foler:
            return
        self.file_system_tree.alter_dir(new_foler)
        self.dock_filetree.show()
        self.status_bar.showMessage("current folder: {}".format(new_foler),
                                    3000)

    def open_camera(self):
        if self.action_camera.isChecked():
            self.camera.start()
            self.action_camera.setIcon(QIcon('icon/stop.png'))
        else:
            self.label_frame.clear()
            self.camera.stop()
            self.status_fps.setText("FPS:00.0")
            self.action_camera.setIcon(QIcon("icon/camera.png"))

    def play_media(self):
        if not self.media_control.is_play():
            self.media_control.pause()
            self.camera.is_pause = True
        else:
            self.media_control.play()
            self.camera.is_pause = False
示例#21
0
    def __init__(self, ClassObject):
        super(QMainWindow, self).__init__()

        w = ClassObject()
        w.app_main_window = self
        self._widget = w

        if len(w.mainmenu) > 0:
            w._mainmenu = self.__initMainMenu(w.mainmenu)

        w.init_form()

        if conf.PYFORMS_USE_QT5:
            self.layout().setContentsMargins(conf.PYFORMS_MAINWINDOW_MARGIN,
                                             conf.PYFORMS_MAINWINDOW_MARGIN,
                                             conf.PYFORMS_MAINWINDOW_MARGIN,
                                             conf.PYFORMS_MAINWINDOW_MARGIN)
        else:
            self.layout().setMargin(conf.PYFORMS_MAINWINDOW_MARGIN)

        self.setCentralWidget(w)
        self.setWindowTitle(w.title)

        docks = {}
        for name, item in w.controls.items():
            if isinstance(item, ControlDockWidget):
                if item.side not in docks:
                    docks[item.side] = []
                docks[item.side].append((name, item))

        for key, widgets in docks.items():
            side = QtCore.Qt.RightDockWidgetArea
            if key == 'left':
                side = QtCore.Qt.LeftDockWidgetArea
            elif key == 'right':
                side = QtCore.Qt.RightDockWidgetArea
            elif key == 'top':
                side = QtCore.Qt.TopDockWidgetArea
            elif key == 'bottom':
                side = QtCore.Qt.BottomDockWidgetArea
            else:
                side = QtCore.Qt.LeftDockWidgetArea

            if isinstance(widgets, list):
                widgets = sorted(widgets, key=lambda x: x[1].order)

                for name, widget in widgets:
                    dock = QDockWidget(self)
                    dock.setFeatures(QDockWidget.DockWidgetFloatable
                                     | QDockWidget.DockWidgetClosable
                                     | QDockWidget.DockWidgetMovable)
                    dock.setObjectName(name)

                    if conf.PYFORMS_USE_QT5:
                        dock.setContentsMargins(0, 0, 0, 0)
                        widget.form.layout().setContentsMargins(
                            widget.margin, widget.margin, widget.margin,
                            widget.margin)
                    else:
                        dock.setMargin(0)
                        widget.form.layout().setMargin(widget.margin)

                    # print dock.objectName(),1
                    dock.setWidget(widget.form)
                    dock.setWindowTitle(widget.label)
                    widget.dock = dock
                    if not widget._show: dock.hide()

                    self.addDockWidget(side, dock)
            else:
                dock = QDockWidget(self)
                dock.setFeatures(QDockWidget.DockWidgetFloatable
                                 | QDockWidget.DockWidgetClosable
                                 | QDockWidget.DockWidgetMovable)
                # dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)

                if conf.PYFORMS_USE_QT5:
                    widget.form.layout().setContentsMargins(
                        widget.margin, widget.margin, widget.margin,
                        widget.margin)
                else:
                    widget.form.layout().setMargin(widget.margin)

                # print dock.objectName(), 2
                dock.setObjectName(name)
                dock.setWidget(widget.form)
                self.addDockWidget(side, dock)
                dock.setWindowTitle(widget.label)
                widget.dock = dock
                if not widget._show: dock.hide()

        if conf.PYFORMS_STYLESHEET:
            stylesheet_files = [conf.PYFORMS_STYLESHEET]

            p = platform.system()
            if p == 'Windows' and conf.PYFORMS_STYLESHEET_WINDOWS:
                stylesheet_files.append(conf.PYFORMS_STYLESHEET_WINDOWS)
            elif p == 'Darwin' and conf.PYFORMS_STYLESHEET_DARWIN:
                stylesheet_files.append(conf.PYFORMS_STYLESHEET_DARWIN)
            elif p == 'Linux' and conf.PYFORMS_STYLESHEET_LINUX:
                stylesheet_files.append(conf.PYFORMS_STYLESHEET_LINUX)

            logger.debug('Import stylesheets: {0}'.format(stylesheet_files))
            self.loadStyleSheetFile(stylesheet_files)
示例#22
0
class _QtDock(_AbstractDock):
    def _dock_initialize(self):
        self.dock = QDockWidget()
        self.scroll = QScrollArea(self.dock)
        self.dock.setWidget(self.scroll)
        widget = QWidget(self.scroll)
        self.scroll.setWidget(widget)
        self.scroll.setWidgetResizable(True)
        self.dock.setAllowedAreas(Qt.LeftDockWidgetArea)
        self.dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.plotter.app_window.addDockWidget(Qt.LeftDockWidgetArea, self.dock)
        self.dock_layout = QVBoxLayout()
        widget.setLayout(self.dock_layout)

    def _dock_finalize(self):
        self.dock.setMinimumSize(self.dock.sizeHint().width(), 0)
        self._dock_add_stretch(self.dock_layout)

    def _dock_show(self):
        self.dock.show()

    def _dock_hide(self):
        self.dock.hide()

    def _dock_add_stretch(self, layout):
        layout.addStretch()

    def _dock_add_layout(self, vertical=True):
        layout = QVBoxLayout() if vertical else QHBoxLayout()
        return layout

    def _dock_add_label(self, value, align=False, layout=None):
        layout = self.dock_layout if layout is None else layout
        widget = QLabel()
        if align:
            widget.setAlignment(Qt.AlignCenter)
        widget.setText(value)
        layout.addWidget(widget)
        return widget

    def _dock_add_button(self, name, callback, layout=None):
        layout = self.dock_layout if layout is None else layout
        widget = QPushButton(name)
        widget.released.connect(callback)
        layout.addWidget(widget)
        return widget

    def _dock_add_text(self, value, callback, validator=None, layout=None):
        layout = self.dock_layout if layout is None else layout
        widget = QLineEdit(value)
        widget.setAlignment(Qt.AlignCenter)
        if validator is not None:
            widget.setValidator(QDoubleValidator(validator[0], validator[1],
                                                 2))

            def _callback():
                callback(float(widget.text()))
        else:

            def _callback():
                callback(widget.text())

        widget.returnPressed.connect(_callback)
        layout.addWidget(widget)
        return widget

    def _dock_add_slider(self,
                         name,
                         value,
                         rng,
                         callback,
                         compact=True,
                         double=False,
                         layout=None):
        layout = self.dock_layout if layout is None else layout
        hlayout = self._dock_add_layout(not compact)
        if name is not None:
            self._dock_add_label(value=name, align=not compact, layout=hlayout)
        slider_class = QFloatSlider if double else QSlider
        widget = slider_class(Qt.Horizontal)
        widget.setMinimum(rng[0] if double else int(rng[0]))
        widget.setMaximum(rng[1] if double else int(rng[1]))
        widget.setValue(value if double else int(value))
        widget.valueChanged.connect(callback)
        hlayout.addWidget(widget)
        layout.addLayout(hlayout)
        return widget

    def _dock_add_spin_box(self,
                           name,
                           value,
                           rng,
                           callback,
                           compact=True,
                           double=True,
                           layout=None):
        layout = self.dock_layout if layout is None else layout
        hlayout = self._dock_add_layout(not compact)
        if name is not None:
            self._dock_add_label(value=name, align=not compact, layout=hlayout)
        value = value if double else int(value)
        widget = QDoubleSpinBox() if double else QSpinBox()
        widget.setAlignment(Qt.AlignCenter)
        widget.setMinimum(rng[0])
        widget.setMaximum(rng[1])
        widget.setValue(value)
        widget.valueChanged.connect(callback)
        hlayout.addWidget(widget)
        layout.addLayout(hlayout)
        return widget

    def _dock_add_combo_box(self,
                            name,
                            value,
                            rng,
                            callback,
                            compact=True,
                            layout=None):
        layout = self.dock_layout if layout is None else layout
        hlayout = self._dock_add_layout(not compact)
        if name is not None:
            self._dock_add_label(value=name, align=not compact, layout=hlayout)
        widget = QComboBox()
        widget.addItems(rng)
        widget.setCurrentText(value)
        widget.currentTextChanged.connect(callback)
        hlayout.addWidget(widget)
        layout.addLayout(hlayout)
        return widget

    def _dock_add_group_box(self, name, layout=None):
        layout = self.dock_layout if layout is None else layout
        hlayout = QVBoxLayout()
        widget = QGroupBox(name)
        widget.setLayout(hlayout)
        layout.addWidget(widget)
        return hlayout