Esempio n. 1
0
class CentralWidget(QWidget):
    def __init__(self, communicator):
        super().__init__()
        self.initUI(communicator)
        self.setStyleSheet("QWidget {border: 0;}")

    def initUI(self, communicator):
        self.questionBlock = Questions(communicator)
        self.lectionBlock = Lection(communicator)
        layout = QHBoxLayout()
        layout.setSpacing(0)
        self.splitter = QSplitter(Qt.Horizontal)
        self.splitter.addWidget(self.lectionBlock)
        self.splitter.addWidget(self.questionBlock)
        self.splitter.setHandleWidth(0)
        self.splitter.setStretchFactor(0, 5)
        self.splitter.setStretchFactor(1, 2)
        self.splitter.setStyleSheet(
            "QWidget {background-color: #78aef9;border:0;}")
        layout.addWidget(self.splitter)
        self.setContentsMargins(-10, -10, -10, -10)
        self.setLayout(layout)
        QApplication.setStyle(QStyleFactory.create('Cleanlooks'))

    def closeEvent(self, event):
        os.exit(0)
Esempio n. 2
0
    def makeHSplitterLayout(self, left_menu, bar_open_tabs, document,
                            right_menu, search_and_replace):
        """
        This will create the layout containing the middle section of the application
        :param left_menu: reference to the left menu of the application
        :param bar_open_tabs: reference to the bar containing the open tabs
        :param document: reference to the document
        :param right_menu: reference to the right menu of the application.
        :param search_and_replace: reference to the search and replace for the document
        :return: returns the created layout
        """
        logging.debug("Creating Layout - Horizontal")

        horizontal_workspace = QSplitter(
            QtCore.Qt.Horizontal
        )  # Splitter between LeftMenu, Doc, and Right Menu
        horizontal_workspace.setHandleWidth(
            self.layout_props.getDefSplitterWidth())

        horizontal_workspace.addWidget(left_menu)

        document_view = QWidget()
        doc_layout = QVBoxLayout(document_view)
        doc_layout.setContentsMargins(0, 0, 0, 0)
        doc_layout.setSpacing(0)
        doc_layout.addWidget(bar_open_tabs)
        doc_layout.addWidget(search_and_replace)
        doc_layout.addWidget(document)
        horizontal_workspace.addWidget(document_view)

        horizontal_workspace.addWidget(right_menu)

        return horizontal_workspace
Esempio n. 3
0
class MainWidget(QWidget):
    def __init__(self):
        super(MainWidget, self).__init__()
        self._k_widget = KWidget()
        self._vol_widget = VolWidget()
        self._spliter = QSplitter(Qt.Vertical, self)
        self.init_ui()
        self.init_connection()

    def init_ui(self):
        self._spliter.addWidget(self._k_widget)
        self._spliter.addWidget(self._vol_widget)
        self._spliter.setStretchFactor(0, 8)
        self._spliter.setStretchFactor(1, 2)
        self._spliter.setHandleWidth(1)
        _layout = QHBoxLayout()
        _layout.addWidget(self._spliter)
        _layout.setContentsMargins(10, 10, 10, 10)
        _layout.setSpacing(0)
        self.setLayout(_layout)

    def init_connection(self):
        self._k_widget.view_box().setXLink(self._vol_widget.view_box())
        self._k_widget.sig_y_padding_changed.connect(
            self._vol_widget.on_y_padding_changed)
        self._vol_widget.sig_y_padding_changed.connect(
            self._k_widget.on_y_padding_changed)
        self._k_widget.sig_v_pos.connect(self._vol_widget.on_v_pos)
        self._vol_widget.sig_v_pos.connect(self._k_widget.on_v_pos)
Esempio n. 4
0
    def sig_to_stems_clicked(self, row):
        signature = self.sig_to_stems_major_table.item(row, 0).text()
        print(signature)
        signature = tuple(signature.split(SEP_SIG))

        stems = sorted(self.lexicon.signatures_to_stems()[signature])
        number_of_stems_per_column = 5

        # create a master list of sublists, where each sublist contains k stems
        # k = number_of_stems_per_column
        stem_rows = list()
        stem_row = list()

        for i, stem in enumerate(stems, 1):
            stem_row.append(stem)
            if not i % number_of_stems_per_column:
                stem_rows.append(stem_row)
                stem_row = list()
        if stem_row:
            stem_rows.append(stem_row)

        # set up the minor table as table widget
        sig_to_stems_minor_table = QTableWidget()
        sig_to_stems_minor_table.horizontalHeader().hide()
        sig_to_stems_minor_table.verticalHeader().hide()
        sig_to_stems_minor_table.clear()
        sig_to_stems_minor_table.setRowCount(len(stem_rows))
        sig_to_stems_minor_table.setColumnCount(number_of_stems_per_column)

        # fill in the minor table
        for row, stem_row in enumerate(stem_rows):
            for col, stem in enumerate(stem_row):
                item = QTableWidgetItem(stem)
                sig_to_stems_minor_table.setItem(row, col, item)

        sig_to_stems_minor_table.resizeColumnsToContents()

        minor_table_title = QLabel('{} (number of stems: {})'
                                   .format(SEP_SIG.join(signature), len(stems))
                                   )

        minor_table_widget_with_title = QWidget()
        layout = QVBoxLayout()
        layout.addWidget(minor_table_title)
        layout.addWidget(sig_to_stems_minor_table)
        minor_table_widget_with_title.setLayout(layout)

        new_display = QSplitter(Qt.Horizontal)
        new_display.setHandleWidth(10)
        new_display.setChildrenCollapsible(False)

        new_display.addWidget(self.sig_to_stems_major_table)
        new_display.addWidget(minor_table_widget_with_title)
        new_display_width = self.majorDisplay.width() / 2
        new_display.setSizes(
            [new_display_width * 0.4, new_display_width * 0.6])

        self.load_main_window(major_display=new_display)
        self.status.clearMessage()
        self.status.showMessage('{} selected'.format(signature))
Esempio n. 5
0
    def build_central_content(self):
        main_panel = QSplitter(self)
        main_panel.setHandleWidth(1)
        main_panel.setOrientation(Qt.Vertical)
        main_panel.setContentsMargins(0, 0, 0, 0)

        from ui.panel_registers import RegistersPanel
        self.registers_panel = RegistersPanel(self.app, 0, 0)
        main_panel.addWidget(self.registers_panel)

        box = QVBoxLayout()
        box.setContentsMargins(0, 0, 0, 0)
        from ui.panel_memory import MemoryPanel
        self.memory_panel = MemoryPanel(self.app)
        box.addWidget(self.memory_panel)

        from ui.panel_java_explorer import JavaExplorerPanel
        self.java_explorer_panel = JavaExplorerPanel(self.app)
        self.java_explorer_panel.hide()
        box.addWidget(self.java_explorer_panel)

        q = QWidget()
        q.setLayout(box)
        main_panel.addWidget(q)

        from ui.panel_log import LogPanel
        self.log_panel = LogPanel(self.app)
        main_panel.addWidget(self.log_panel)

        main_panel.setStretchFactor(0, 1)
        main_panel.setStretchFactor(1, 3)
        main_panel.setStretchFactor(2, 1)
        return main_panel
Esempio n. 6
0
    def initUI(self):
        """Override."""
        self._monitor_tb.setTabPosition(QTabWidget.TabPosition.South)
        self._monitor_tb.addTab(self._avail_src_view, "Available sources")
        self._monitor_tb.addTab(self._process_mon_view, "Process monitor")

        splitter = QSplitter(Qt.Vertical)
        splitter.setHandleWidth(self.SPLITTER_HANDLE_WIDTH)
        splitter.setChildrenCollapsible(False)
        splitter.addWidget(self._con_view)
        splitter.addWidget(self._src_view)
        splitter.addWidget(self._monitor_tb)
        splitter.setStretchFactor(0, 3)
        splitter.setStretchFactor(1, 1)
        h = splitter.sizeHint().height()
        splitter.setSizes([0.1 * h, 0.6 * h, 0.3 * h])

        layout = QVBoxLayout()
        layout.addWidget(splitter)
        self.setLayout(layout)

        self._con_view.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)

        self._src_view.expandToDepth(1)
        self._src_view.resizeColumnToContents(0)
        self._src_view.resizeColumnToContents(1)
Esempio n. 7
0
    def initUI(self):
        """Override."""
        ctrl_widget = QWidget()
        ctrl_layout = QHBoxLayout()
        AT = Qt.AlignTop
        ctrl_layout.addWidget(self._roi_ctrl_widget)
        ctrl_layout.addWidget(self._roi_fom_ctrl_widget, alignment=AT)
        ctrl_layout.addWidget(self._roi_hist_ctrl_widget, alignment=AT)
        ctrl_layout.addWidget(self._roi_norm_ctrl_widget, alignment=AT)
        ctrl_layout.addWidget(self._roi_proj_ctrl_widget, alignment=AT)
        ctrl_layout.setContentsMargins(1, 1, 1, 1)
        ctrl_widget.setLayout(ctrl_layout)
        ctrl_widget.setFixedHeight(
            self._roi_proj_ctrl_widget.minimumSizeHint().height())

        subview_splitter = QSplitter(Qt.Vertical)
        subview_splitter.setHandleWidth(9)
        subview_splitter.setChildrenCollapsible(False)
        subview_splitter.addWidget(self._roi_proj_plot)
        subview_splitter.addWidget(self._roi_hist)

        view_splitter = QSplitter(Qt.Horizontal)
        view_splitter.setHandleWidth(9)
        view_splitter.setChildrenCollapsible(False)
        view_splitter.addWidget(self._corrected)
        view_splitter.addWidget(subview_splitter)
        view_splitter.setSizes([1e6, 1e6])

        layout = QVBoxLayout()
        layout.addWidget(view_splitter)
        layout.addWidget(ctrl_widget)
        layout.setContentsMargins(1, 1, 1, 1)
        self.setLayout(layout)
Esempio n. 8
0
class Ui:
    def __init__(self, app):
        self._app = app
        self._layout = QVBoxLayout(app)
        self._bottom_layout = QHBoxLayout()
        self._top_separator = Separator(parent=app)
        self._splitter = QSplitter(app)
        if use_mac_theme():
            self._splitter.setHandleWidth(0)

        # NOTE: 以位置命名的部件应该只用来组织界面布局,不要
        # 给其添加任何功能性的函数
        self.top_panel = TopPanel(app, app)
        self._left_panel_container = QScrollArea(self._app)
        self._left_panel_container.setWidgetResizable(True)
        self.left_panel = LeftPanel(self._app, self._splitter)
        self._left_panel_container.setWidget(self.left_panel)
        self.right_panel = RightPanel(self._app, self._splitter)

        # alias
        self.pc_panel = self.top_panel.pc_panel
        self.table_container = self.right_panel.table_container
        self.magicbox = MagicBox(self._app)

        # 对部件进行一些 UI 层面的初始化
        self._splitter.addWidget(self._left_panel_container)
        self._splitter.addWidget(self.right_panel)

        self.right_panel.setMinimumWidth(780)
        self._left_panel_container.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.right_panel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        if use_mac_theme():
            self._layout.addWidget(self.magicbox)
            self._layout.addWidget(self._splitter)
            self._layout.addWidget(self._top_separator)
            self._layout.addWidget(self.top_panel)
        else:
            self._layout.addWidget(self.top_panel)
            self._layout.addWidget(self._top_separator)
            self._layout.addWidget(self._splitter)
            self._layout.addWidget(self.magicbox)

        # self._layout.addLayout(self._bottom_layout)
        # self._bottom_layout.addWidget(self.magicbox)
        self._layout.setSpacing(0)
        self._layout.setContentsMargins(0, 0, 0, 0)
        self.top_panel.layout().setSpacing(0)
        self.top_panel.layout().setContentsMargins(0, 0, 0, 0)

        self.pc_panel.playlist_btn.clicked.connect(self.show_player_playlist)

        self._app.hotkey_manager.registe(
            [QKeySequence('Ctrl+F'), QKeySequence(':'), QKeySequence('Alt+x')],
            self.magicbox.setFocus
        )

    def show_player_playlist(self):
        songs = self._app.playlist.list()
        self.table_container.show_player_playlist(songs)
    def buildUI(self):

        self.fig = Figure()
        self.zoom = 1
        self.mapCanvas = FigureCanvas(self.fig)
        self.mapCanvas.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                     QtWidgets.QSizePolicy.Expanding)

        main_splitter = QSplitter(Qt.Vertical)

        self.map_settings_widget = IPMapSettingsWidget()

        main_splitter.addWidget(self.map_settings_widget)
        main_splitter.addWidget(self.mapCanvas)

        main_splitter.setStretchFactor(0, 0)
        main_splitter.setStretchFactor(1, 1)

        # I want to make sure the splitter handle is easily seen...
        main_splitter.setStyleSheet(
            "QSplitter::handle{ background-color: #444444}")
        main_splitter.setHandleWidth(2)

        main_layout = QVBoxLayout()
        main_layout.addWidget(main_splitter)

        self.setLayout(main_layout)

        self.compute_initial_figure()

        self.connect_signals_and_slots()
Esempio n. 10
0
    def __init__(self, *args, **kwargs):
        super(ProductUI, self).__init__(*args, **kwargs)
        main_layout = QHBoxLayout()
        main_layout.setContentsMargins(QMargins(0, 0, 0, 0))
        main_splitter = QSplitter(self)
        self.menu_folded = ScrollFoldedBox(self)
        main_splitter.addWidget(self.menu_folded)

        self.frame_tab = QMainWindow(self)

        main_splitter.addWidget(self.frame_tab)
        main_splitter.setHandleWidth(1)
        main_layout.addWidget(main_splitter)

        self.menu_folded.setMinimumWidth(180)
        self.menu_folded.setMaximumWidth(240)

        self.setLayout(main_layout)
        self.menu_folded.setFoldedStyleSheet(
            "QScrollArea{border: none;background-color:rgb(255,255,255)}"
            "#foldedBox{border-right: 1px solid rgb(180, 180, 180);}"
            "#foldedHead{background-color:rgb(1,129,135);border-bottom:1px solid rgb(200,200,200);"
            "border-right: 1px solid rgb(180, 180, 180);max-height: 30px;}"
            "#headLabel{padding:8px 5px;font-weight: bold;font-size: 15px;color:rgb(245,245,245);}"
            "#foldedBody{border-right: 1px solid rgb(180, 180, 180);}"
            "#foldedBox QScrollBar:vertical{width: 5px;background: transparent;}"
            "#foldedBox QScrollBar::handle:vertical {background: rgba(0, 0, 0, 30);width:5px;"
            "border-radius: 5px;border:none;}"
            "#foldedBox QScrollBar::handle:vertical:hover,"
            "QScrollBar::handle:horizontal:hover{background: rgba(0, 0, 0, 80);}"
        )
Esempio n. 11
0
    def __init__(self, parent=None, project_path=None):
        super().__init__()
        self.parent = parent
        mono = MonoPanel(parent)
        node_list = NodeTree()
        self.scene = mono.view.scene()

        left_panel = QWidget()
        config_button = QPushButton('Global\nConfiguration')
        config_button.setMinimumHeight(40)
        config_button.clicked.connect(self.global_config)

        vlayout = QVBoxLayout()
        vlayout.addWidget(config_button)
        vlayout.addWidget(node_list)
        vlayout.setContentsMargins(0, 0, 0, 0)
        left_panel.setLayout(vlayout)

        splitter = QSplitter()
        splitter.addWidget(left_panel)
        splitter.addWidget(mono)
        splitter.setHandleWidth(10)
        splitter.setCollapsible(0, False)
        splitter.setCollapsible(1, False)
        splitter.setStretchFactor(1, 1)

        mainLayout = QHBoxLayout()
        mainLayout.addWidget(splitter)
        self.setLayout(mainLayout)

        if project_path is not None:
            self.scene.load(project_path)
            self.scene.run_all()
Esempio n. 12
0
    def init_splitter(self):
        self.frame = QFrame()
        self.frame.setFrameShape(QFrame.StyledPanel)
        hbox = QHBoxLayout()  # here should be no 'self' argument
        self.browser_widget = bv.BrowserWidget(self)
        self.top_splitter = QSplitter(Qt.Horizontal)
        frame = QFrame()
        layout = QVBoxLayout()
        for addon in self.addon_list:
            layout.addWidget(addon)
            addon.hide()
        frame.setLayout(layout)        
        self.top_splitter.addWidget(frame)
        self.current_addon = self.addon_list[0]
        self.current_addon.show_itself()
        self.top_splitter.addWidget(self.browser_widget)
        self.top_splitter.setSizes([100, 200])

        handle_width = 6

        # https://stackoverflow.com/questions/2545577/qsplitter-becoming-undistinguishable-between-qwidget-and-qtabwidget
        self.top_splitter.setOpaqueResize(False)
        self.top_splitter.setChildrenCollapsible(False)
        self.top_splitter.setHandleWidth(handle_width)

        splitter2 = QSplitter(Qt.Vertical)
        splitter2.addWidget(self.top_splitter)
        splitter2.addWidget(self.jupyter_widget)
        splitter2.setOpaqueResize(False)
        splitter2.setChildrenCollapsible(False)
        splitter2.setHandleWidth(handle_width)

        hbox.addWidget(splitter2)

        self.frame.setLayout(hbox)
Esempio n. 13
0
class LmrManager(QWidget):
    def __init__(self):
        super(LmrManager, self).__init__()

        self.h_layout = QHBoxLayout()

        self.left_frame = LeftFrame()

        self.middle_frame = MiddleFrame()
        self.right_frame = RightFrame()

        self.mr_splitter = QSplitter()

        # 缩小三个框直接的缝隙
        self.mr_splitter.setHandleWidth(1)

        self.mr_splitter.insertWidget(0, self.middle_frame)
        self.mr_splitter.insertWidget(1, self.right_frame)

        self.mr_splitter.setStretchFactor(
            0, 1)  # 全屏后保持1:4的比例,但是之前设置的最小宽度此时可能就比较小了
        self.mr_splitter.setStretchFactor(1, 4)

        # 设置为不可拖动至隐藏
        self.mr_splitter.setCollapsible(0, False)
        self.mr_splitter.setCollapsible(1, False)

        self.h_layout.addWidget(self.left_frame)
        self.h_layout.addWidget(self.mr_splitter)

        self.setLayout(self.h_layout)
Esempio n. 14
0
class Ui:
    def __init__(self, app):
        self._app = app
        self._layout = QVBoxLayout(app)
        self._bottom_layout = QHBoxLayout()
        self._top_separator = Separator(parent=app)
        self._splitter = QSplitter(app)
        if use_mac_theme():
            self._splitter.setHandleWidth(0)

        # NOTE: 以位置命名的部件应该只用来组织界面布局,不要
        # 给其添加任何功能性的函数
        self.top_panel = TopPanel(app, app)
        self._left_panel_container = QScrollArea(self._app)
        self._left_panel_container.setWidgetResizable(True)
        self.left_panel = LeftPanel(self._app, self._splitter)
        self._left_panel_container.setWidget(self.left_panel)
        self.right_panel = RightPanel(self._app, self._splitter)

        # alias
        self.pc_panel = self.top_panel.pc_panel
        self.table_container = self.right_panel.table_container
        self.magicbox = MagicBox(self._app)

        # 对部件进行一些 UI 层面的初始化
        self._splitter.addWidget(self._left_panel_container)
        self._splitter.addWidget(self.right_panel)

        self.right_panel.setMinimumWidth(780)
        self._left_panel_container.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.right_panel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        if use_mac_theme():
            self._layout.addWidget(self.magicbox)
            self._layout.addWidget(self._splitter)
            self._layout.addWidget(self._top_separator)
            self._layout.addWidget(self.top_panel)
        else:
            self._layout.addWidget(self.top_panel)
            self._layout.addWidget(self._top_separator)
            self._layout.addWidget(self._splitter)
            self._layout.addWidget(self.magicbox)

        # self._layout.addLayout(self._bottom_layout)
        # self._bottom_layout.addWidget(self.magicbox)
        self._layout.setSpacing(0)
        self._layout.setContentsMargins(0, 0, 0, 0)
        self.top_panel.layout().setSpacing(0)
        self.top_panel.layout().setContentsMargins(0, 0, 0, 0)

        self.pc_panel.playlist_btn.clicked.connect(self.show_player_playlist)

        self._app.hotkey_manager.registe(
            [QKeySequence('Ctrl+F'), QKeySequence(':'), QKeySequence('Alt+x')],
            self.magicbox.setFocus
        )

    def show_player_playlist(self):
        songs = self._app.playlist.list()
        self.table_container.show_player_playlist(songs)
Esempio n. 15
0
    def initUI(self):
        """Override."""
        ctrl_layout = QHBoxLayout()
        AT = Qt.AlignTop
        ctrl_layout.addWidget(self._roi_ctrl_widget)
        ctrl_layout.addWidget(self._roi_fom_ctrl_widget, alignment=AT)
        ctrl_layout.addWidget(self._roi_hist_ctrl_widget, alignment=AT)
        ctrl_layout.addWidget(self._roi_norm_ctrl_widget, alignment=AT)
        ctrl_layout.addWidget(self._roi_proj_ctrl_widget, alignment=AT)

        subview_splitter = QSplitter(Qt.Vertical)
        subview_splitter.setHandleWidth(9)
        subview_splitter.setChildrenCollapsible(False)
        subview_splitter.addWidget(self._roi_proj_plot)
        subview_splitter.addWidget(self._roi_hist)

        view_splitter = QSplitter(Qt.Horizontal)
        view_splitter.setHandleWidth(9)
        view_splitter.setChildrenCollapsible(False)
        view_splitter.addWidget(self._corrected)
        view_splitter.addWidget(subview_splitter)

        layout = QVBoxLayout()
        layout.addWidget(view_splitter)
        layout.addLayout(ctrl_layout)
        self.setLayout(layout)
Esempio n. 16
0
    def __init__(self):
        super(Main, self).__init__()

        hbox = QHBoxLayout(self)

        frame1 = RadioFrame(self)
        frame1.setFrameShape(QFrame.Panel)

        frame2 = CheckFrame(self)
        frame2.setFrameShape(QFrame.Panel)

        splitter1 = QSplitter(Qt.Horizontal)
        splitter1.addWidget(frame1)
        splitter1.addWidget(frame2)
        splitter1.setHandleWidth(10)

        frame3 = ComboFrame(self)
        frame3.setFrameShape(QFrame.Panel)

        splitter2 = QSplitter(Qt.Vertical)
        splitter2.addWidget(splitter1)
        splitter2.addWidget(frame3)

        hbox.addWidget(splitter2)
        self.setLayout(hbox)

        self.setWindowTitle("splitter")
        self.show()
Esempio n. 17
0
    def sig_to_stems_clicked(self, row):
        signature = self.sig_to_stems_major_table.item(row, 0).text()
        print(signature)
        signature = tuple(signature.split(SEP_SIG))

        stems = sorted(self.lexicon.signatures_to_stems()[signature])
        number_of_stems_per_column = 5

        # create a master list of sublists, where each sublist contains k stems
        # k = number_of_stems_per_column
        stem_rows = list()
        stem_row = list()

        for i, stem in enumerate(stems, 1):
            stem_row.append(stem)
            if not i % number_of_stems_per_column:
                stem_rows.append(stem_row)
                stem_row = list()
        if stem_row:
            stem_rows.append(stem_row)

        # set up the minor table as table widget
        sig_to_stems_minor_table = QTableWidget()
        sig_to_stems_minor_table.horizontalHeader().hide()
        sig_to_stems_minor_table.verticalHeader().hide()
        sig_to_stems_minor_table.clear()
        sig_to_stems_minor_table.setRowCount(len(stem_rows))
        sig_to_stems_minor_table.setColumnCount(number_of_stems_per_column)

        # fill in the minor table
        for row, stem_row in enumerate(stem_rows):
            for col, stem in enumerate(stem_row):
                item = QTableWidgetItem(stem)
                sig_to_stems_minor_table.setItem(row, col, item)

        sig_to_stems_minor_table.resizeColumnsToContents()

        minor_table_title = QLabel('{} (number of stems: {})'
                                   .format(SEP_SIG.join(signature), len(stems)))

        minor_table_widget_with_title = QWidget()
        layout = QVBoxLayout()
        layout.addWidget(minor_table_title)
        layout.addWidget(sig_to_stems_minor_table)
        minor_table_widget_with_title.setLayout(layout)

        new_display = QSplitter(Qt.Horizontal)
        new_display.setHandleWidth(10)
        new_display.setChildrenCollapsible(False)

        new_display.addWidget(self.sig_to_stems_major_table)
        new_display.addWidget(minor_table_widget_with_title)
        new_display_width = self.majorDisplay.width() / 2
        new_display.setSizes(
            [new_display_width * 0.4, new_display_width * 0.6])

        self.load_main_window(major_display=new_display)
        self.status.clearMessage()
        self.status.showMessage('{} selected'.format(signature))
Esempio n. 18
0
class Ui:
    def __init__(self, app):
        self._app = app
        self._layout = QVBoxLayout(app)
        self._top_separator = Separator(parent=app)
        self._splitter = QSplitter(app)

        # NOTE: 以位置命名的部件应该只用来组织界面布局,不要
        # 给其添加任何功能性的函数
        self.top_panel = TopPanel(app, app)
        self.sidebar = self._left_panel_con = LeftPanel(self._app, )
        self.left_panel = self._left_panel_con.p
        self.right_panel = RightPanel(self._app, self._splitter)
        self.bottom_panel = self.right_panel.bottom_panel
        self.mpv_widget = MpvOpenGLWidget(self._app)
        self.frameless_container = None

        # alias
        self.magicbox = self.bottom_panel.magicbox
        self.pc_panel = self.top_panel.pc_panel
        self.table_container = self.right_panel.table_container
        # backward compatible, old name is songs_table_container
        self.songs_table_container = self.table_container
        self.songs_table = self.table_container.songs_table
        self.back_btn = self.bottom_panel.back_btn
        self.forward_btn = self.bottom_panel.forward_btn
        self.toggle_video_btn = self.pc_panel.toggle_video_btn

        self.pc_panel.playlist_btn.clicked.connect(
            lambda: self._app.browser.goto(page='/player_playlist'))

        self._setup_ui()

        # ui controllers
        self.video_show_ctl = VideoShowCtl(self._app, self)

    def _setup_ui(self):
        self._app.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

        self._splitter.setHandleWidth(0)
        self._splitter.addWidget(self._left_panel_con)
        self._splitter.addWidget(self.right_panel)

        self.right_panel.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)

        # self._layout.addWidget(self.bottom_panel)
        self._layout.addWidget(self._splitter)
        self._layout.addWidget(self.mpv_widget)
        self._layout.addWidget(self._top_separator)
        self._layout.addWidget(self.top_panel)

        self._layout.setSpacing(0)
        self._layout.setContentsMargins(0, 0, 0, 0)
        self.top_panel.layout().setSpacing(0)
        self.top_panel.layout().setContentsMargins(0, 0, 0, 0)

        self._app.resize(880, 600)
Esempio n. 19
0
    def create_layout(self):
        figure = Figure((8.0, 6.0), dpi=100)
        self.canvas = FigureCanvas(figure)
        main_view = QWidget()
        self.canvas.setParent(main_view)
        self.axes = figure.add_subplot(111)
        mpl_toolbar = NavigationToolbar(self.canvas, main_view)

        self.qcb_show_points.setChecked(DISPLAY_POINTS)
        self.qcb_show_points.stateChanged.connect(self.on_show)

        self.qcb_show_legend.setChecked(DISPLAY_LEGEND)
        self.qcb_show_legend.stateChanged.connect(self.on_show)

        self.qpb_show.clicked.connect(self.on_show)

        qvb_graph = QVBoxLayout()
        qvb_graph.addWidget(self.canvas)
        qvb_graph.addWidget(mpl_toolbar)
        qw_graph = QWidget()
        qw_graph.setLayout(qvb_graph)

        qf_separator = QFrame()
        qf_separator.setFrameShape(QFrame.HLine)

        qhb_time_unit = QHBoxLayout()
        for unit in TIME_UNITS.keys():
            qrb_unit = QRadioButton(unit)
            if self.parent.time_unit == unit:
                qrb_unit.setChecked(True)
            else:
                qrb_unit.setChecked(False)
            self.qbg_time_unit.addButton(qrb_unit)
            qhb_time_unit.addWidget(qrb_unit)
        self.qbg_time_unit.buttonClicked.connect(self.time_unit_changed)

        self.qvb_options.addStretch(1)
        self.qvb_options.addWidget(qf_separator)
        self.qvb_options.addStretch(1)
        self.qvb_options.addLayout(qhb_time_unit)
        self.qvb_options.addWidget(self.qcb_show_points)
        self.qvb_options.addWidget(self.qcb_show_legend)
        self.qvb_options.addWidget(self.qpb_show)
        qw_options = QWidget()
        qw_options.setLayout(self.qvb_options)

        splitter = QSplitter()
        splitter.addWidget(qw_options)
        splitter.addWidget(qw_graph)
        splitter.setHandleWidth(10)
        splitter.setCollapsible(0, False)
        splitter.setCollapsible(1, False)
        splitter.setStretchFactor(1, 1)

        main_layout = QHBoxLayout()
        main_layout.addWidget(splitter)
        self.setLayout(main_layout)
Esempio n. 20
0
    def __init__(self):
        super().__init__()
        self.language = settings.LANG
        self.csv_separator = settings.CSV_SEPARATOR
        self.fmt_float = settings.FMT_FLOAT
        self.logging_level = settings.LOGGING_LEVEL
        self.panel = MainPanel(self)

        config_button = QPushButton('Global\nConfiguration')
        config_button.setMinimumHeight(40)
        config_button.clicked.connect(self.global_config)

        pageList = QListWidget()
        for name in ['Start', 'Extract variables', 'Max/Min/Mean/Arrival/Duration', 'Interpolate on points',
                     'Interpolate along lines', 'Project along lines', 'Project mesh',
                     'Compute volume', 'Compute flux', 'Compare two results',
                     'Transform coordinate systems', 'Convert geom file formats', 'Variable Calculator']:
            pageList.addItem('\n' + name + '\n')
        pageList.setFlow(QListView.TopToBottom)
        pageList.currentRowChanged.connect(self.panel.layout().setCurrentIndex)

        pageList.setCurrentRow(0)

        splitter = QSplitter()
        left_widget = QWidget()
        vlayout = QVBoxLayout()
        vlayout.addWidget(config_button)
        vlayout.addWidget(pageList)
        left_widget.setLayout(vlayout)
        splitter.addWidget(left_widget)
        splitter.addWidget(self.panel)
        splitter.setHandleWidth(5)
        splitter.setCollapsible(0, False)
        splitter.setCollapsible(1, False)

        handle = splitter.handle(1)
        layout = QVBoxLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        line = QFrame()
        line.setFrameShape(QFrame.VLine)
        line.setFrameShadow(QFrame.Sunken)
        layout.addWidget(line)
        handle.setLayout(layout)

        mainLayout = QHBoxLayout()
        mainLayout.addWidget(splitter)
        mainLayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(mainLayout)

        self.setWindowTitle('PyTelTools :: Classic interface')
        self.setWindowFlags(self.windowFlags() | Qt.CustomizeWindowHint)
        self.frameGeom = self.frameGeometry()
        self.move(self.frameGeom.center())
Esempio n. 21
0
def splitter(first, second, direction=Qt.Vertical, size=None, handle_width=12):
    split_widget = QSplitter(direction)
    split_widget.setHandleWidth(handle_width)

    split_widget.addWidget(first)
    split_widget.addWidget(second)

    if size is not None:
        split_widget.setSizes(size)

    return split_widget
Esempio n. 22
0
    def __init__(self, app, *__args):
        super().__init__(*__args)
        self.app = app

        self.handle_history = []

        box = QVBoxLayout()
        box.setContentsMargins(0, 0, 0, 0)

        self.clazz = QLabel()
        font = QFont()
        font.setBold(True)
        font.setPixelSize(19)
        self.clazz.setMaximumHeight(40)
        self.clazz.setFont(font)
        self.clazz.setStyleSheet('margin: 5px 10px;')
        box.addWidget(self.clazz)

        splitter = QSplitter()
        splitter.setHandleWidth(1)

        left_col = QWidget()
        left_layout = QVBoxLayout()
        left_layout.setContentsMargins(0, 0, 0, 0)
        left_layout.addWidget(QLabel('methods'))
        self.methods = JavaMethodsWidget(self)
        left_layout.addWidget(self.methods)
        left_col.setLayout(left_layout)
        splitter.addWidget(left_col)

        central_col = QWidget()
        central_layout = QVBoxLayout()
        central_layout.setContentsMargins(0, 0, 0, 0)
        central_layout.addWidget(QLabel('native fields'))
        self.native_fields = JavaFieldsWidget(self, ['name', 'value'], True)
        central_layout.addWidget(self.native_fields)
        central_col.setLayout(central_layout)
        splitter.addWidget(central_col)

        right_col = QWidget()
        right_layout = QVBoxLayout()
        right_layout.setContentsMargins(0, 0, 0, 0)
        right_layout.addWidget(QLabel('fields'))
        self.fields = JavaFieldsWidget(self, ['name', 'class'], False)
        right_layout.addWidget(self.fields)
        right_col.setLayout(right_layout)
        splitter.addWidget(right_col)

        splitter.setStretchFactor(0, 2)
        splitter.setStretchFactor(1, 1)
        splitter.setStretchFactor(2, 1)

        box.addWidget(splitter)
        self.setLayout(box)
Esempio n. 23
0
    def init_ui(self):
        glay_lup = QHBoxLayout()
        glay_lup.addWidget(self.btn_fo)
        glay_lup.addWidget(self.btn_pid)
        glay_lup.addWidget(self.btn_uid)
        glay_lup.addWidget(self.btn_snao)

        glay_ldown = QGridLayout()
        glay_ldown.addWidget(QLabel('画廊ID'), 0, 0, 1, 1)
        glay_ldown.addWidget(self.ledit_pid, 0, 1, 1, 5)
        glay_ldown.addWidget(QLabel('用户ID'), 1, 0, 1, 1)
        glay_ldown.addWidget(self.ledit_uid, 1, 1, 1, 5)
        glay_ldown.addWidget(QLabel('数量'), 2, 0, 1, 1)
        glay_ldown.addWidget(self.ledit_num, 2, 1, 1, 1)
        glay_ldown.setColumnStretch(1, 1)
        glay_ldown.setColumnStretch(2, 5)

        vlay_left = QVBoxLayout()
        vlay_left.addLayout(glay_lup)
        vlay_left.addLayout(glay_ldown)
        hlay_thumb = QHBoxLayout()
        hlay_thumb.addLayout(vlay_left)
        hlay_thumb.addWidget(self.thumbnail)
        left_wid = QWidget()
        left_wid.setLayout(hlay_thumb)

        self.thumbnail.setFixedHeight(left_wid.sizeHint().height())
        self.thumbnail.setFixedWidth(150)
        self.thumbnail.setPixmap(self.thumb_default)
        if self.show_thumb_flag:
            self.thumbnail.show()
        else:
            self.thumbnail.hide()

        vlay_right = QVBoxLayout()
        vlay_right.addWidget(self.user_info, alignment=Qt.AlignHCenter)
        vlay_right.addWidget(self.btn_logout)
        vlay_right.addWidget(self.btn_get)
        vlay_right.addWidget(self.btn_dl)
        right_wid = QWidget()
        right_wid.setLayout(vlay_right)

        splitter = QSplitter(Qt.Horizontal)
        splitter.setHandleWidth(3)
        splitter.addWidget(left_wid)
        splitter.addWidget(right_wid)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.handle(1).setDisabled(True)

        vlay_main = QVBoxLayout()
        vlay_main.addWidget(splitter)
        vlay_main.addWidget(self.table_viewer)
        self.setLayout(vlay_main)
Esempio n. 24
0
 def __init__(self):
     super().__init__()
     self.setWindowTitle('paint test')
     self.resize(1000, 600)
     splitter = QSplitter(Qt.Vertical)
     paint_area1 = KlineArea()
     paint_area2 = PaintArea()
     splitter.addWidget(paint_area1)
     splitter.addWidget(paint_area2)
     splitter.setHandleWidth(1)
     self.setCentralWidget(splitter)
Esempio n. 25
0
    def __init__(self, parent=None, project_path=None, ncsize=settings.NCSIZE):
        super().__init__()
        self.parent = parent
        self.table = MultiTable()
        self.view = MultiView(self, self.table)
        self.scene = self.view.scene()

        self.toolbar = QToolBar()
        self.save_act = QAction('Save\n(Ctrl+S)', self, triggered=self.save, shortcut='Ctrl+S')
        self.run_act = QAction('Run\n(F5)', self, triggered=self.run, shortcut='F5')
        self.init_toolbar()

        if project_path is not None:
            self.message_box = CmdMessage()
        else:
            self.message_box = QPlainTextEdit()
        self.message_box.setReadOnly(True)

        # right panel with table and message_box
        right_panel = QSplitter(Qt.Vertical)
        right_panel.addWidget(self.table)
        right_panel.addWidget(self.message_box)
        right_panel.setHandleWidth(10)
        right_panel.setCollapsible(0, False)
        right_panel.setCollapsible(1, False)
        right_panel.setSizes([200, 200])

        # left panel
        left_panel = QWidget()
        layout = QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.view)
        layout.setContentsMargins(0, 0, 0, 0)
        left_panel.setLayout(layout)

        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(left_panel)
        splitter.addWidget(right_panel)
        splitter.setHandleWidth(10)
        splitter.setCollapsible(0, False)
        splitter.setCollapsible(1, False)
        splitter.setSizes([500, 300])

        mainLayout = QHBoxLayout()
        mainLayout.addWidget(splitter)
        self.setLayout(mainLayout)

        self.ncsize = ncsize
        self.worker = worker.Workers(self.ncsize)

        if project_path is not None:
            self.scene.load(project_path)
            self.run()
Esempio n. 26
0
    def build_right_column(self):
        splitter = QSplitter()
        splitter.setHandleWidth(1)
        splitter.setOrientation(Qt.Vertical)
        splitter.setContentsMargins(0, 0, 0, 0)

        from ui.panel_contexts import ContextsPanel
        self.contexts_panel = ContextsPanel(self.app)
        splitter.addWidget(self.contexts_panel)

        from ui.panel_backtrace import BacktracePanel
        self.backtrace_panel = BacktracePanel(self.app)
        splitter.addWidget(self.backtrace_panel)

        return splitter
Esempio n. 27
0
    def build_left_column(self):
        splitter = QSplitter()
        splitter.setHandleWidth(1)
        splitter.setOrientation(Qt.Vertical)
        splitter.setContentsMargins(0, 0, 0, 0)

        from ui.panel_hooks import HooksPanel
        self.hooks_panel = HooksPanel(self.app)
        splitter.addWidget(self.hooks_panel)

        from ui.panel_watchers import WatchersPanel
        self.watchers_panel = WatchersPanel(self.app)
        splitter.addWidget(self.watchers_panel)

        return splitter
Esempio n. 28
0
    def __init__(self, *args, **kwargs):
        super(DeliveryAdminUI, self).__init__(*args, **kwargs)
        main_layout = QHBoxLayout()
        main_layout.setContentsMargins(QMargins(0, 0, 0, 0))
        main_splitter = QSplitter(self)
        # 菜单列表
        self.menu_list = QListWidget(self)
        main_splitter.addWidget(self.menu_list)
        # 显示窗口
        self.stacked_frame = QStackedWidget(self)
        main_splitter.addWidget(self.stacked_frame)

        main_layout.addWidget(main_splitter)
        main_splitter.setSizes([self.width() * 0.2, self.width() * 0.7])
        main_splitter.setHandleWidth(1)
        self.setLayout(main_layout)
Esempio n. 29
0
File: util.py Progetto: jopohl/urh
def set_splitter_stylesheet(splitter: QSplitter):
    splitter.setHandleWidth(4)
    bgcolor = constants.BGCOLOR.lighter(150)
    r, g, b, a = bgcolor.red(), bgcolor.green(), bgcolor.blue(), bgcolor.alpha()
    splitter.setStyleSheet("QSplitter::handle:vertical {{margin: 4px 0px; "
                           "background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, "
                           "stop:0.2 rgba(255, 255, 255, 0),"
                           "stop:0.5 rgba({0}, {1}, {2}, {3}),"
                           "stop:0.8 rgba(255, 255, 255, 0));"
                           "image: url(:/icons/icons/splitter_handle_horizontal.svg);}}"
                           "QSplitter::handle:horizontal {{margin: 4px 0px; "
                           "background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
                           "stop:0.2 rgba(255, 255, 255, 0),"
                           "stop:0.5 rgba({0}, {1}, {2}, {3}),"
                           "stop:0.8 rgba(255, 255, 255, 0));"
                           "image: url(:/icons/icons/splitter_handle_vertical.svg);}}".format(r, g, b, a))
Esempio n. 30
0
def set_splitter_stylesheet(splitter: QSplitter):
    splitter.setHandleWidth(6)
    bgcolor = constants.BGCOLOR.lighter(120)
    r, g, b = bgcolor.red(), bgcolor.green(), bgcolor.blue()
    splitter.setStyleSheet("QSplitter::handle:vertical {{margin: 4px 0px; "
                           "background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, "
                           "stop:0 rgba(255, 255, 255, 0),"
                           "stop:0.5 rgba({0}, {1}, {2}, 255),"
                           "stop:1 rgba(255, 255, 255, 0));"
                           "image: url(:/icons/icons/splitter_handle_horizontal.svg);}}"
                           "QSplitter::handle:horizontal {{margin: 4px 0px; "
                           "background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
                           "stop:0 rgba(255, 255, 255, 0),"
                           "stop:0.5 rgba({0}, {1}, {2}, 255),"
                           "stop:1 rgba(255, 255, 255, 0));"
                           "image: url(:/icons/icons/splitter_handle_vertical.svg);}}".format(r, g, b))
Esempio n. 31
0
    def build_left_column(self):
        splitter = QSplitter()
        splitter.setHandleWidth(1)
        splitter.setOrientation(Qt.Vertical)
        splitter.setContentsMargins(0, 0, 0, 0)

        self.hooks_panel = HooksPanel(self.app)
        splitter.addWidget(self.hooks_panel)

        self.contexts_panel = ContextsPanel(self.app)
        splitter.addWidget(self.contexts_panel)

        self.backtrace_panel = BacktracePanel(self.app)
        splitter.addWidget(self.backtrace_panel)

        return splitter
Esempio n. 32
0
    def build_central_content(self):
        main_panel = QSplitter(self)
        main_panel.setHandleWidth(1)
        main_panel.setOrientation(Qt.Vertical)
        main_panel.setContentsMargins(0, 0, 0, 0)

        self.registers_panel = RegistersPanel(self.app, 0, 0)
        main_panel.addWidget(self.registers_panel)

        self.memory_panel = MemoryPanel(self.app)
        main_panel.addWidget(self.memory_panel)

        self.log_panel = LogPanel(self.app)
        main_panel.addWidget(self.log_panel)

        main_panel.setStretchFactor(0, 1)
        main_panel.setStretchFactor(1, 3)
        main_panel.setStretchFactor(2, 1)
        return main_panel
Esempio n. 33
0
    def setupViews(self):
        splitter = QSplitter()
        splitter.setHandleWidth(5)

        browsers = QTabWidget()

        label = QLabel('Placeholder')
        label.setAlignment(Qt.AlignCenter|Qt.AlignHCenter|Qt.AlignVCenter)

        layout = QHBoxLayout()
        layout.addWidget(label)

        rightPane = QWidget()
        rightPane.setLayout(layout)

        splitter.addWidget(browsers)
        splitter.addWidget(rightPane)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 1)

        self.setCentralWidget(splitter)
Esempio n. 34
0
class VRTWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        try:
            file = open(Registry.CONFIG_FILE_LOCATION, 'r')
            self.store = Serializer.json_to_store(file.read())
        except FileNotFoundError:
            self.store = Store()
        self.invoker = CommandInvoker()

        self._init_ui()
        self._init_menu()

    def _init_ui(self):
        self.main_widget = QFrame()
        self.main_layout = QHBoxLayout()
        self.main_widget.setLayout(self.main_layout)

        self.segment_menu = SegmentMenu(self.store, self.invoker)
        self.video_area = VideoArea(self.store)
        self.tag_menu = TagMenu(self.store, self.invoker)

        self.splitter = QSplitter()
        self.splitter.addWidget(self.segment_menu)
        self.splitter.addWidget(self.video_area)
        self.splitter.addWidget(self.tag_menu)

        self.splitter.setHandleWidth(0)
        self.splitter.setStretchFactor(0, 1)
        self.splitter.setStretchFactor(1, 3)
        self.splitter.setStretchFactor(2, 1)
        self.main_layout.addWidget(self.splitter)
        self.main_layout.setContentsMargins(0, 0, 0, 0)

        self.setCentralWidget(self.main_widget)

    def _init_menu(self):
        self.menubar = MenuBar(self.store, self.invoker)
        self.setMenuBar(self.menubar)
Esempio n. 35
0
class EditorWidget(QWidget):
    device_and_data_signal = pyqtSignal(list, int, name="device_list_signal")
    import_list_signal = pyqtSignal(set, name="import_list_signal")
    close_cancel_signal = pyqtSignal(name="close_cancel_signal")

    def __init__(self, refresh_signal, tester, case_id=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        ui_dir_path = os.path.dirname(__file__)
        ui_file_path = os.path.join(ui_dir_path, 'case_editor.ui')
        uic.loadUi(ui_file_path, self)

        self.dBCommandLineHelper = DBCommandLineHelper()
        self.tester = tester
        self.config = self.tester.get_config()
        self.debug_runner = self.tester.get_debug_runner()
        self.case_id = case_id
        self.refresh_signal = refresh_signal

        self.init_ui()

        self.is_log_show = True
        self.is_running = False
        self.tag_list = []
        self.parsed_line_list = []
        self.case = None
        self.high_lighter = None
        self.tag_manage_widget = None
        self.add_device_widget = None

        self.message_box = QMessageBox()
        self.add_tag_button = SearchButton()
        self.tag_names_line_edit = TagLineEdit("tag_names_line_edit", self.add_tag_button)
        self.set_tag_name_completer()

        self.splitter = QSplitter(Qt.Vertical)

        self.splitter.setHandleWidth(1)  # set handle width
        self.editor_text_edit = TextEdit(self.debug_runner.core)  # case content TextEdit
        self.console = Console()

        # Add the 'editor text edit' and 'console' to splitter
        self.splitter.addWidget(self.editor_text_edit)
        self.splitter.addWidget(self.console)

        # Set the initial scale: 4:1
        self.splitter.setStretchFactor(0, 4)
        self.splitter.setStretchFactor(1, 1)

        self.editor_layout.addWidget(self.splitter)

        self.import_list_signal.connect(self.editor_text_edit.get_import_from_content, Qt.QueuedConnection)
        self.editor_text_edit.parse_error_info_signal.connect(self.add_info_console, Qt.QueuedConnection)

        self.editor_adapter()  # set completer and highlighter
        self.set_case_edit_data()  # update case

        # run status listener
        self.status_listener = EditorRunStatusListener()
        self.status_listener.editor_listener_msg_signal.connect(self.result_handle, Qt.QueuedConnection)
        self.debug_runner.listener = self.status_listener

        self.data_line = None

        # button event
        self.save_btn.clicked.connect(self.save_case)
        self.run_btn.clicked.connect(self.run_btn_event)
        self.console_btn.clicked.connect(self.log_show_hide_event)
        self.edit_data_btn.clicked.connect(self.add_case_data)
        self.add_tag_button.clicked.connect(self.choose_event)
        # case data
        self.case_manager = CaseManager()
        self.case_data_manage = CaseDataManager()
        self.case_data_count = 0  # init case data count
        self.is_case_data_modify = False

    def init_ui(self):
        """
        init ui, include: resize window
        :return:
        """
        screen = QDesktopWidget().screenGeometry()
        self.resize(screen.width() / 2, screen.height() / 2)
        self.init_btn_icon()

        self.id_line_edit.hide()  # hide line_edit
        self.case_name_line_edit.setPlaceholderText("Case Name")

    def init_btn_icon(self):
        """
        init button icon, including: save button、run button、show/hide console button
        :return:
        """
        save_icon = QIcon()
        save_icon.addPixmap(QPixmap(self.config.images + '/save.png'), QIcon.Normal, QIcon.Off)  # save icon
        self.save_btn.setIcon(save_icon)

        run_icon = QIcon()
        run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off)  # run icon
        self.run_btn.setIcon(run_icon)

        console_icon = QIcon()
        console_icon.addPixmap(QPixmap(self.config.images + '/console.png'), QIcon.Normal, QIcon.Off)  # console icon
        self.console_btn.setIcon(console_icon)

        edit_data_icon = QIcon()
        edit_data_icon.addPixmap(QPixmap(self.config.images + '/edit.png'), QIcon.Normal, QIcon.Off)  # console icon
        self.edit_data_btn.setIcon(edit_data_icon)

    def add_case_data(self):
        """
        show case data widget
        :return:
        """
        if hasattr(self, 'case_data_widget'):
            self.case_data_widget.close()
        self.case_data_widget = CaseDataWidget(self.case_id)
        self.case_data_widget.show()

    def choose_event(self):
        """
        choose tag event, show tags
        :return:
        """
        self.tag_manage_widget = TagManageWidget(self.config)
        self.tag_manage_widget.selected_tag_names_signal.connect(self.set_selected_tag_names)
        self.tag_manage_widget.setWindowModality(Qt.ApplicationModal)
        self.tag_manage_widget.show()

    def set_selected_tag_names(self, tag_names):
        """
        set tag names
        :param tag_names:
        :return:
        """
        original_tag_names = self.tag_names_line_edit.text().strip()
        tag_name_set = set(original_tag_names.split(";"))  # original tag name set
        if not tag_names:
            return
        # handle the repeat tag names
        tag_name_list = tag_names.split(";")
        for tag_name in tag_name_list:
            if (tag_name.strip() in original_tag_names) or (not tag_name.strip()):
                continue
            tag_name_set.add(tag_name.strip())  # add new selected tag name
        all_tag_names = ""
        for tag_name in tag_name_set:
            if not tag_name.strip():
                continue
            all_tag_names += tag_name.strip() + ";"

        self.tag_names_line_edit.is_completer = False
        self.tag_names_line_edit.setText(all_tag_names)
        self.tag_names_line_edit.is_completer = True

    def log_show_hide_event(self):
        if self.is_log_show:
            self.console_btn.setText("Show Console")
            self.console.hide()
            self.is_log_show = False
        else:
            self.console_btn.setText("Hide Console")
            self.console.show()
            self.is_log_show = True

    def add_info_console(self, info):
        """
        append error massage to console
        :param info:
        :return:
        """
        self.console.append(info)

    def result_handle(self, msg, is_passed):
        """
        show the debug result in console
        :param is_passed:
        :param msg:
        :return:
        """

        if msg.status == 601:
            self.add_info_console("<font color='green'> Start to install agent.</font>")
        elif msg.status == 602:
            self.add_info_console("<font color='green'> Install agent success.</font>")
        elif msg.status == 603:
            self.add_info_console("<font color='red'> Install agent Fail." + "\r Error Info:\r<pre>" + msg.message +
                                  "</pre></font>")
        elif msg.status == 701:
            self.add_info_console("<font color='green'> Start agent.</font>")
        elif msg.status == 702:
            self.add_info_console("<font color='green'> Stop agent.</font>")
        elif msg.status == 703:
            self.add_info_console("<font color='red'> Agent error." + "\r Error Info:\r<pre>" + msg.message +
                                  "</pre></font>")
        if msg.status == 500:  # fail
            self.add_info_console("<font color='red'> <pre>" + str(msg.message) + "</pre></font>")
        if msg.status == 102 and is_passed:
            self.add_info_console("<font color='green'> The case is Passed.</font>")
        elif msg.status == 102 and not is_passed:
            self.add_info_console("<font color='red'> The case is Failed.</font>")

    def set_case_edit_data(self):
        """
        init data for update case
        :return:
        """
        if not self.case_id:
            return
        self.case = self.dBCommandLineHelper.query_case_by_id(self.case_id)
        self.id_line_edit.setText(self.case_id)
        self.case_name_line_edit.setText(self.case.name)
        tags = ''
        for tag in self.case.tags:
            tags = tags + tag.name + ";"
        self.tag_names_line_edit.setText(tags)
        self.editor_text_edit.setPlainText(self.case.content)

        # 'import' block in the case content
        init_import_set = set()
        for cmd in self.case.content.split("\n"):
            if cmd.strip().find("import") == 0:
                init_import_set.add(cmd.strip())
        # send the init import block to editor's text edit, for init the highlighter and completer
        self.import_list_signal.emit(init_import_set)

    def closeEvent(self, event):
        """
        close window event
        :param event:
        :return:
        """
        case_name = self.case_name_line_edit.text().strip()  # Case Name
        content = self.editor_text_edit.toPlainText().strip()  # Case Content
        tag_list = self.get_tag_list()
        # check case data widget isVisible
        if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible() and (
                not self.case_data_widget.has_modify):
            self.case_data_widget.close()

        if not self.case_id:  # new case
            if (not case_name) and (not content) and (not tag_list):
                self.close()
                return
        elif self.case_id:  # update case
            if not self.check_modify():
                self.close()
                return
        self.handle_message_box_apply(event)

    def handle_message_box_apply(self, event):
        """
        message box
        :param event:
        :return:
        """
        reply = self.message_box.question(self, "Save Changes?", "The case has been modified, save changes?",
                                          QMessageBox.Save | QMessageBox.Cancel | QMessageBox.Discard)

        if reply == QMessageBox.Save:  # update case info
            self.save_case(event)
            # check case data widget isVisible
            if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible():
                self.case_data_widget.close()
        elif reply == QMessageBox.Discard:
            # check case data widget isVisible
            if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible():
                self.case_data_widget.close()
            self.close()
            return
        else:
            self.close_cancel_signal.emit()
            event.ignore()

    def check_modify(self):
        """
        check the changes of the case
        :return:
        """
        is_case_modified = False
        case_db = self.dBCommandLineHelper.query_case_by_id(self.case_id)

        is_name_modified = case_db.name.strip() != self.case_name_line_edit.text().strip()
        is_content_modified = case_db.content.strip() != self.editor_text_edit.toPlainText().strip()

        # tag names in the line edit
        tag_list = self.get_tag_list()
        # tag names in db
        db_tag_list = case_db.tags
        is_tags_names_modify = set(db_tag_list).difference(set(tag_list)) != set(tag_list).difference(set(db_tag_list))

        # check the case data
        if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible():
            self.is_case_data_modify = self.case_data_widget.has_modify

        if is_name_modified or is_content_modified or is_tags_names_modify or self.is_case_data_modify:
            logger.debug('case changed. case name: {}, tags: {}, content: {}, case data: {}'
                         .format(is_name_modified, is_tags_names_modify, is_content_modified, self.is_case_data_modify))
            is_case_modified = True
        return is_case_modified

    def get_tag_list(self):
        """
        get tag list from tag_names_line_edit
        :return:
        """
        # get tag names
        tag_name_list = self.tag_names_line_edit.text().strip().split(";")
        tag_set = set()
        for tag_name in tag_name_list:
            if not tag_name.strip():
                continue
            tag = self.dBCommandLineHelper.query_tag_by_name(tag_name.strip())
            tag_set.add(tag)
        return list(tag_set)

    def run_btn_event(self):
        """
        click run button, show add_device_widget
        :return:
        """
        self.add_device_widget = AddDeviceWidget()  # add device
        self.add_device_widget.setWindowModality(Qt.ApplicationModal)
        self.device_and_data_signal.connect(self.add_device_widget.add_radio_to_widget, Qt.QueuedConnection)
        self.add_device_widget.run_editor_signal.connect(self.run_case, Qt.QueuedConnection)
        devices = []
        if self.is_running:
            self.stop_case()
        try:
            devices = self.tester.devices()
        except Exception as e:
            self.add_info_console("<font color='red'>" + str(e) + "</font>")
        if not devices:  # There is no device connected
            self.message_box.warning(self, "Message", "Please connect the device to your computer.", QMessageBox.Ok)
            return

        # get case data count
        if self.case_id is not None:
            self.case_data_count = self.case_data_manage.get_case_data_count(self.case_id)

        self.device_and_data_signal.emit(devices, self.case_data_count)
        self.add_device_widget.show()

    def run_case(self, devices, data_line_number):
        # change icon
        stop_icon = QIcon()
        stop_icon.addPixmap(QPixmap(self.config.images + '/stop.png'), QIcon.Normal, QIcon.Off)
        self.run_btn.setIcon(stop_icon)
        self.run_btn.setText("Stop")
        self.is_running = True
        if not devices:
            return
        self.tester.select_devices(devices)

        self.data_line = data_line_number
        self.run()  # run

    def stop_case(self):
        # set icon
        run_icon = QIcon()
        run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off)
        self.run_btn.setIcon(run_icon)
        self.run_btn.setText("Run")
        self.is_running = False
        try:
            self.tester.stop()
            self.tester.stop_server()
        except Exception as e:
            self.add_info_console("<font color='red'>" + str(e) + "</font>")

    def run(self):
        """
        run case content
        :return:
        """
        case_content = self.editor_text_edit.toPlainText().strip()

        case_data = None
        try:
            if (self.case_id is not None) and (self.case_data_count > 0):  # case data exist
                case_data = self.case_data_manage.get_run_format_data(self.case_id)  # get all case data

            self.debug_runner.reset()
            self.debug_runner._data = case_data  # set case data
            self.debug_runner.parse(case_content)
            logger.debug("Debug beginning")
            self.debug_runner.execute(case_content, self.data_line)
        except Exception as e:
            logger.exception(str(e))
            self.add_info_console("<font color='red'>" + str(e) + "</font>")
        self.stop_case()

    def save_case(self, event=None):
        """
        save case
        :return:
        """
        case_name = self.case_name_line_edit.text().strip()  # Case Name
        content = self.editor_text_edit.toPlainText()  # Case Content
        if self.check_null():
            if event:
                event.ignore()
            return
        tags = self.get_tag_list()

        if self.check_tag_name():  # check unrecognized tag names
            return

        if self.case_id:
            self.case.name = case_name
            self.case.content = content
            self.case.tags = tags
            try:
                # update case and case data
                if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible():
                    self.case.last_modify_time = datetime.datetime.now()  # update time
                    self.case_manager.update_case(self.case_id, self.case_data_widget.case_data_list,
                                                  self.case_data_widget.delete_data_ids)
                    del self.case_data_widget.delete_data_ids[:]
                    self.case_data_widget.has_modify = False
                else:
                    self.case.last_modify_time = datetime.datetime.now()  # update time
                    self.dBCommandLineHelper.update_case()
            except Exception as e:
                logger.exception(str(e))
                self.message_box.information(self, "Update Case Error", "Update case Fail.\nError Info:\n" + str(e),
                                             QMessageBox.Ok)
        else:
            try:
                # insert case and save case data
                if hasattr(self, 'case_data_widget') and self.case_data_widget.isVisible():
                    case = self.case_manager.insert_case(case_name, content, tags, self.case_data_widget.case_data_list,
                                                         self.case_data_widget.delete_data_ids)
                    del self.case_data_widget.delete_data_ids[:]
                    self.case_data_widget.has_modify = False
                else:
                    case = self.dBCommandLineHelper.insert_case_with_tags(case_name, content, tags)
                self.id_line_edit.setText(str(case.id))
                self.case_id = self.id_line_edit.text().strip()
                self.set_case_edit_data()
            except Exception as e:
                logger.exception(str(e))
                self.message_box.information(self, "Add Case Error", "Add case Fail.\nError Info:\n" + str(e),
                                             QMessageBox.Ok)
        self.refresh_signal.emit()  # refresh the main table

    def check_null(self):
        """
        check the required options
        :return:
        """
        is_none = False
        type_info = ''
        case_name = self.case_name_line_edit.text().strip()
        content = self.editor_text_edit.toPlainText().strip()

        if not case_name:
            is_none = True
            type_info += "Case Name"
        if not content:
            is_none = True
            if not type_info:
                type_info += "Content"
            else:
                type_info += ", Content"
        if is_none:
            self.message_box.warning(self, "Message", type_info + " is required.", QMessageBox.Ok)
        return is_none

    def editor_adapter(self):
        """
        get keywords for the completer and the highlighter
        :return:
        """
        if self.case_id:
            self.parse_import_as()
        func_dict = self.debug_runner.core.kw_func  # get default functions
        cmp = Completer(self.debug_runner)
        self.editor_text_edit.set_completer(cmp)

        # highlighter
        kw_list = []
        for func_name, func in func_dict.items():
            kw_list.append(func_name)
        self.high_lighter = MyHighlighter(self.editor_text_edit, kw_list)
        self.editor_text_edit.set_highlighter(self.high_lighter)

    def parse_import_as(self):
        """
        parse all the 'import' and 'as' block in the case content
        :return:
        """
        self.debug_runner.core.kw_func.clear()
        self.debug_runner.core.kw_func = {**self.debug_runner.core.default_func}
        content_list = self.dBCommandLineHelper.query_case_by_id(self.case_id).content.split("\n")
        if not content_list:
            return
        for line in content_list:
            if line.strip().find("import") == 0:  # parse 'import'
                try:
                    self.debug_runner.core.parse_line(line)
                except Exception as e:
                    self.add_info_console("<font color='red'>" + str(e) + "</font>")
            elif " as " in line.strip():  # parse 'as'
                try:
                    self.debug_runner.core.parse_line(line)
                except Exception as e:
                    self.add_info_console("<font color='red'>" + str(e) + "</font>")

    def set_tag_name_completer(self):
        """
        set completer to tag_names_line_edit
        :return:
        """
        # change button icon
        add_icon = QIcon()
        add_icon.addPixmap(QPixmap(self.config.images + '/add.png'), QIcon.Normal, QIcon.Off)
        self.add_tag_button.setIcon(add_icon)
        self.add_tag_button.setToolTip("add tag")

        self.tag_names_line_edit.setPlaceholderText("Tag Names")
        self.tag_layout.insertWidget(0, self.tag_names_line_edit)

        self.tag_list = self.dBCommandLineHelper.query_tag_all()  # get all tags
        tag_name_list = []
        for tag in self.tag_list:
            tag_name_list.append(tag.name)
        cmp = TagCompleter(tag_name_list)
        self.tag_names_line_edit.setCompleter(cmp)

    def check_tag_name(self):
        """
        check tag name,return unrecognized tag names
        :return:
        """
        tag_name_list = self.tag_names_line_edit.text().strip().split(";")
        unrecognized_tag_names = ""
        has_unrecognized = False
        for tag_name in tag_name_list:
            if not tag_name.strip():
                continue
            tag = self.dBCommandLineHelper.query_tag_by_name(tag_name.strip())
            if not tag:
                unrecognized_tag_names += "\"" + tag_name + "\"" + "、"
        if not unrecognized_tag_names:
            return has_unrecognized
        has_unrecognized = True
        unrecognized_tag_names = unrecognized_tag_names[:-1]
        self.message_box.about(self, "Warning", "Tag name: " + unrecognized_tag_names +
                               " unrecognized, please add it first.")
        return has_unrecognized
Esempio n. 36
0
class OTMainWindow(QWidget):
    def __init__(self, parent=None):
        super(OTMainWindow, self).__init__(parent, Qt.Window)
        self.setWindowTitle('OPC Python Tester')
        self.layout = QVBoxLayout()
        #
        self.tree = QTreeWidget(self)
        self.tree.setHeaderLabel('OPC server tree')
        self.tree_root = QTreeWidgetItem()
        self.tree_root.setText(0, 'not connected')
        self.tree.addTopLevelItem(self.tree_root)
        self.tree.itemDoubleClicked.connect(self.on_tree_item_double_clicked)
        #
        self.table = QTableWidget(self)
        self.table.setRowCount(0)
        self.table_column_labels = [
            'item_id', 'value', 'type', 'access', 'quality', 'timestamp']
        self.table.setColumnCount(len(self.table_column_labels))
        self.table.setHorizontalHeaderLabels(self.table_column_labels)
        self.table.horizontalHeader().setStretchLastSection(True)
        #
        self.splitter = QSplitter(Qt.Horizontal, self)
        self.splitter.setChildrenCollapsible(False)
        self.splitter.setHandleWidth(10)
        self.layout.addWidget(self.splitter)
        # final
        self.splitter.addWidget(self.tree)
        self.splitter.addWidget(self.table)
        self.splitter.setSizes([150, 300])
        self.setLayout(self.layout)

        # self.opcsrv = None
        self.cur_server_info = {}
        self.cur_comp_name = ''
        self.watched_itemids = []

        self.ssdialog = ServerSelectDialog(self)
        ssel_ret = self.ssdialog.exec_()
        if ssel_ret == QDialog.Accepted:
            self.do_connect(self.ssdialog.selected_server, self.ssdialog.selected_comp_name)
        else:
            print('Connection cancelled')

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.on_timer_timeout)
        self.timer.start(1000)  # every 1 second

    def do_connect(self, srv_info: dict, comp_name: str):
        print('Connecting to "{0}" ({1}) on comp: {2}...'.format(
            srv_info['desc'], srv_info['guid'], comp_name))
        self.opcsrv = opc_helper.opc_connect(srv_info['guid'], comp_name)
        if self.opcsrv is None:
            return
        self.cur_comp_name = comp_name
        self.cur_server_info = srv_info
        print(self.opcsrv.get_status())
        self.fill_tree()

    def fill_tree(self):
        self.tree.clear()
        if self.opcsrv is None:
            return
        self.tree_root = QTreeWidgetItem(self.tree)
        self.tree_root.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicatorWhenChildless)
        root_title = '{0}'.format(self.cur_server_info['desc'])
        if self.cur_comp_name != '':
            root_title = '{0} ({1})'.format(self.cur_server_info['desc'], self.cur_comp_name)
        self.tree_root.setText(0, root_title)
        self.tree.addTopLevelItem(self.tree_root)
        server_tree = self.opcsrv.browse(flat=False)
        #
        for oitem in server_tree:
            self.fill_item(oitem, self.tree_root)

    def fill_item(self, item: dict, parent: QTreeWidgetItem):
        tree_item = QTreeWidgetItem()
        tree_item.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicatorWhenChildless)
        tree_item.setText(0, item['name'])
        if item['children'] is None:
            # set userdata = item_id only if this IS a LEAF node
            tree_item.setData(0, Qt.UserRole, item['item_id'])  # column, role, data
        parent.addChild(tree_item)
        # recurse into children
        if item['children'] is not None:
            for oitem in item['children']:
                self.fill_item(oitem, tree_item)

    @pyqtSlot(QTreeWidgetItem, int)
    def on_tree_item_double_clicked(self, item: QTreeWidgetItem, column: int):
        # void	itemDoubleClicked(QTreeWidgetItem * item, int column)
        # virtual QVariant	data(int column, int role) const
        item_data = item.data(0, Qt.UserRole)
        if item_data is None:
            return
        item_id = str(item_data)
        print('Double click on [{0}]'.format(item_id))
        self.opcsrv.get_item(item_id)
        if item_id not in self.watched_itemids:
            self.watched_itemids.append(item_id)

    @pyqtSlot()
    def on_timer_timeout(self):
        num_items = len(self.watched_itemids)
        self.table.setRowCount(num_items)
        i = 0
        while i < num_items:
            item_id = self.watched_itemids[i]
            item_value = self.opcsrv.get_item(item_id)
            item_info = self.opcsrv.get_item_info(item_id)
            #
            twi = QTableWidgetItem(str(item_id))
            self.table.setItem(i, 0, twi)
            #
            twi = QTableWidgetItem(str(item_value))
            self.table.setItem(i, 1, twi)
            #
            twi = QTableWidgetItem(str(item_info['type']))
            self.table.setItem(i, 2, twi)
            #
            twi = QTableWidgetItem(str(item_info['access_rights']))
            self.table.setItem(i, 3, twi)
            #
            twi = QTableWidgetItem(str(item_info['quality']))
            self.table.setItem(i, 4, twi)
            #
            ts_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(item_info['timestamp']))
            twi = QTableWidgetItem(str(ts_str))
            self.table.setItem(i, 5, twi)
            #
            i += 1
Esempio n. 37
0
class MainWindow(QMainWindow):
    def __init__(self, screen_height, screen_width, version, parent=None):
        super(MainWindow, self).__init__(parent)

        self.screen_width = screen_width
        self.screen_height = screen_height
        self.version = version

        # basic main window settings
        self.resize(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT)
        self.setWindowTitle('Linguistica {}'.format(self.version))

        # lexicon and lexicon tree
        self.lexicon = None
        self.lexicon_tree = None
        self.initialize_lexicon_tree()

        # set up major display, parameter window, then load main window
        self.majorDisplay = QWidget()
        self.parameterWindow = QWidget()
        self.load_main_window()

        # 'File' menu and actions
        select_corpus_action = self.create_action(text='&Select corpus...',
                                                  slot=self.corpus_dir_dialog,
                                                  tip='Select a corpus file',
                                                  shortcut='Ctrl+N')
        select_wordlist_action = self.create_action(text='&Select wordlist...',
                                                    slot=self.wordlist_dir_dialog,
                                                    tip='Select a wordlist file',
                                                    shortcut='Ctrl+W')
        run_file_action = self.create_action(text='&Run...',
                                             slot=self.run_file,
                                             tip='Run the input file',
                                             shortcut='Ctrl+D')
        parameters_action = self.create_action(text='&Parameters...',
                                               slot=self.parameters_dialog,
                                               tip='Change parameters',
                                               shortcut='Ctrl+P')

        file_menu = self.menuBar().addMenu('&File')
        file_menu.addAction(select_corpus_action)
        file_menu.addAction(select_wordlist_action)
        file_menu.addAction(run_file_action)
        file_menu.addAction(parameters_action)

        self.status = self.statusBar()
        self.status.setSizeGripEnabled(False)
        self.status.showMessage('No input file loaded. To select one: File --> '
                                'Select corpus... or Select wordlist...')

    def initialize_lexicon_tree(self):
        self.lexicon_tree = QTreeWidget()
        self.lexicon_tree.setEnabled(True)
        self.lexicon_tree.setMinimumWidth(TREEWIDGET_WIDTH_MIN)
        self.lexicon_tree.setMaximumWidth(TREEWIDGET_WIDTH_MAX)
        self.lexicon_tree.setMinimumHeight(TREEWIDGET_HEIGHT_MIN)
        self.lexicon_tree.setHeaderLabel('')
        self.lexicon_tree.setItemsExpandable(True)
        # noinspection PyUnresolvedReferences
        self.lexicon_tree.itemClicked.connect(self.tree_item_clicked)

    def create_action(self, text=None, slot=None, tip=None, shortcut=None):
        """
        This create actions for the File menu, things like
        Read Corpus, Rerun Corpus etc
        """
        action = QAction(text, self)
        if shortcut:
            action.setShortcut(shortcut)
        if tip:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot:
            # noinspection PyUnresolvedReferences
            action.triggered.connect(slot)
        if shortcut:
            # noinspection PyUnresolvedReferences
            QShortcut(QKeySequence(shortcut), self).activated.connect(slot)
        return action

    def _get_filename_from_dialog(self, ftype='input'):
        self.determine_last_file()
        if self.last_file_path and self.last_file_type == ftype:
            open_dir = self.last_file_path
        else:
            open_dir = os.getcwd()
        # noinspection PyTypeChecker,PyCallByClass
        fname = QFileDialog.getOpenFileName(self,
                                            'Select the {} file'.format(ftype),
                                            open_dir)
        process_all_gui_events()

        # HACK: fname is supposed to be a string (at least according to the
        # PyQt5 documentation), but for some reason fname is a tuple.
        # So we need this hack to make sure that fname is a string of a filename
        # -- Jackson Lee, 2015/06/22

        # update: it's turned out that this behavior is due to compatibility
        # between PyQt and PySide. The "tuple" behavior is in line with the
        # newer API2 for PyQt. (PyQt on python 3 uses API2 by default.)
        # more here: http://srinikom.github.io/pyside-bz-archive/343.html
        # so perhaps we keep our current hack for now?
        # -- Jackson Lee, 2015/08/24

        if fname and any(fname) and (type(fname) is tuple):
            return fname[0]
        else:
            # if this hack isn't needed somehow...
            return fname

    def corpus_dir_dialog(self):
        """
        Pop up the "open a file" dialog and ask for which corpus text file
        to use
        """
        self.corpus_filename = self._get_filename_from_dialog(ftype='corpus')

        process_all_gui_events()

        if type(self.corpus_filename) != str:
            return

        # note that self.corpus_filename is an absolute full path
        self.corpus_name = os.path.basename(self.corpus_filename)
        self.corpus_stem_name = Path(self.corpus_name).stem

        self.lexicon = read_corpus(self.corpus_filename)
        self.initialize_lexicon_tree()
        self.load_main_window(major_display=QWidget(),
                              parameter_window=QWidget())
        process_all_gui_events()

        self.status.clearMessage()
        self.status.showMessage(
            'Corpus selected: {}'.format(self.corpus_filename))

    def wordlist_dir_dialog(self):
        """
        Pop up the "open a file" dialog and ask for which corpus text file
        to use
        """
        self.corpus_filename = self._get_filename_from_dialog(ftype='wordlist')

        process_all_gui_events()

        if type(self.corpus_filename) != str:
            return

        # note that self.corpus_filename is an absolute full path
        self.corpus_name = os.path.basename(self.corpus_filename)
        self.corpus_stem_name = Path(self.corpus_name).stem

        self.lexicon = read_wordlist(self.corpus_filename)
        self.initialize_lexicon_tree()
        self.load_main_window(major_display=QWidget(),
                              parameter_window=QWidget())
        process_all_gui_events()

        self.status.clearMessage()
        self.status.showMessage(
            'Wordlist selected: {}'.format(self.corpus_filename))

    def parameters_dialog(self):
        if self.lexicon is None:
            warning = QMessageBox()
            warning.setIcon(QMessageBox.Warning)
            warning.setText('Parameters can only be accessed when an input '
                            'file is specified.')
            warning.setWindowTitle('No input file selected')
            warning.setStandardButtons(QMessageBox.Ok)
            warning.exec_()
            return

        process_all_gui_events()

        parameters = self.lexicon.parameters()
        dialog = QDialog()
        layout = QVBoxLayout()
        layout.addWidget(
            QLabel('Filename: {}'.format(Path(self.corpus_filename).name)))
        file_type = 'Wordlist' if self.lexicon.file_is_wordlist else 'Corpus'
        layout.addWidget(QLabel('Type: {}'.format(file_type)))

        grid = QGridLayout()
        self.parameter_spinboxes = [QSpinBox() for _ in range(len(parameters))]

        for i, parameter_name in enumerate(sorted(parameters.keys())):
            self.parameter_spinboxes[i].setObjectName(parameter_name)
            self.parameter_spinboxes[i].setRange(
                *PARAMETERS_RANGES[parameter_name])
            self.parameter_spinboxes[i].setValue(parameters[parameter_name])
            self.parameter_spinboxes[i].setSingleStep(1)
            # noinspection PyUnresolvedReferences
            self.parameter_spinboxes[i].valueChanged.connect(
                self.update_parameter)

            grid.addWidget(QLabel(parameter_name), i, 0)
            grid.addWidget(self.parameter_spinboxes[i], i, 1)
            grid.addWidget(QLabel(PARAMETERS_HINTS[parameter_name]), i, 2)

        layout.addLayout(grid)

        reset_button = QPushButton()
        reset_button.setText('&Reset')
        # noinspection PyUnresolvedReferences
        reset_button.clicked.connect(self.reset_parameters)

        spacer = QWidget()  # just for padding in tool_bar
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        tool_bar = QHBoxLayout()
        tool_bar.addWidget(spacer)  # so that the buttons are right-aligned
        tool_bar.addWidget(reset_button)

        layout.addLayout(tool_bar)

        dialog.setLayout(layout)
        dialog.setWindowTitle('Parameters')
        dialog.exec_()

    def reset_parameters(self):
        self.lexicon.use_default_parameters()

        for i, (_, value) in \
                enumerate(sorted(self.lexicon.parameters().items())):
            self.parameter_spinboxes[i].setValue(value)

    def update_parameter(self):
        for i in range(len(self.lexicon.parameters())):
            parameter_name, new_value = \
                self.parameter_spinboxes[i].objectName(), \
                self.parameter_spinboxes[i].value()
            self.lexicon.change_parameters(**{parameter_name: new_value})

    def update_progress(self, progress_text, target_percentage):
        """
        Update the progress dialog. This function is triggered by the
        "progress_signal" emitted from the linguistica component worker thread.
        """
        self.progressDialog.setLabelText(progress_text)
        self.progressDialog.setValue(target_percentage)
        process_all_gui_events()

    # noinspection PyProtectedMember
    def run_file(self):
        if self.lexicon is None:
            warning = QMessageBox()
            warning.setIcon(QMessageBox.Warning)
            warning.setText('No input file is selected.')
            warning.setWindowTitle('Error')
            warning.setStandardButtons(QMessageBox.Ok)
            warning.exec_()
            return

        self.status.clearMessage()
        self.status.showMessage('Running the file {} now...'
                                .format(self.corpus_name))

        print('\nInput file in use:\n{}\n'.format(self.corpus_filename),
              flush=True)

        # set up the Linguistica components worker
        # The worker is a QThread. We spawn this thread, and the linguistica
        # components run on this new thread but not the main thread for the GUI.
        # This makes the GUI still responsive
        # while the long and heavy running process of
        # the Linguistica components is ongoing.

        self.lxa_worker = LinguisticaWorker(self.lexicon)
        self.lxa_worker.progress_signal.connect(self.update_progress)

        # set up progress dialog

        process_all_gui_events()
        self.progressDialog = QProgressDialog()
        self.progressDialog.setRange(0, 100)  # it's like from 0% to 100%
        self.progressDialog.setLabelText('Initializing...')
        self.progressDialog.setValue(0)  # initialize as 0 (= 0%)
        self.progressDialog.setWindowTitle(
            'Processing {}'.format(self.corpus_name))
        self.progressDialog.setCancelButton(None)
        self.progressDialog.resize(400, 100)
        process_all_gui_events()

        self.progressDialog.show()

        # We disable the "cancel" button
        # Setting up a "cancel" mechanism may not be a good idea,
        # since it would probably involve killing the linguistica component
        # worker at *any* point of its processing.
        # This may have undesirable effects (e.g., freezing the GUI) -- BAD!

        # make sure all GUI stuff up to this point has been processed before
        # doing the real work of running the Lxa components
        process_all_gui_events()

        # Now the real work begins here!
        self.lxa_worker.start()

        process_all_gui_events()

        self.lexicon = self.lxa_worker.get_lexicon()

        print('\nAll Linguistica components run for the file', flush=True)
        self.status.clearMessage()
        self.status.showMessage('{} processed'.format(self.corpus_name))

        self.load_main_window(major_display=QWidget(),
                              parameter_window=QWidget())
        self.populate_lexicon_tree()
        self.update_last_file()
        process_all_gui_events()

        # display corpus name (in the tree header label)
        file_type = 'wordlist' if self.lexicon.file_is_wordlist else 'corpus'
        header_label = 'File: {}\nFile type: {}\n\n# word types: {:,}\n'.format(
            self.corpus_name, file_type, self.lexicon.number_of_word_types())
        if file_type == 'corpus':
            header_label += '# word tokens: {:,}\n'.format(
                self.lexicon.number_of_word_tokens())
        self.lexicon_tree.setHeaderLabel(header_label)

    @staticmethod
    def ensure_config_dir_exists():
        if not os.path.isdir(CONFIG_DIR):
            os.mkdir(CONFIG_DIR)

    def determine_last_file(self):
        self.last_file_path = None
        self.last_file_type = None
        self.last_file_encoding = None

        if not os.path.isfile(CONFIG_LAST_FILE):
            return

        with open(CONFIG_LAST_FILE, encoding='utf8') as f:
            config_last_file = json.load(f)

        self.last_file_path = config_last_file['last_file_path']
        self.last_file_type = config_last_file['last_file_type']
        self.last_file_encoding = config_last_file['last_file_encoding']

    def update_last_file(self):
        self.ensure_config_dir_exists()
        with open(CONFIG_LAST_FILE, 'w', encoding='utf8') as f:
            if self.lexicon.file_is_wordlist:
                file_type = 'wordlist'
            else:
                file_type = 'corpus'

            config = {'last_file_path': self.lexicon.file_abspath,
                      'last_file_type': file_type,
                      'last_file_encoding': self.lexicon.encoding,
                      }

            json.dump(config, f)

    def populate_lexicon_tree(self):
        self.lexicon_tree.clear()
        process_all_gui_events()

        # wordlist
        ancestor = QTreeWidgetItem(self.lexicon_tree, [WORDLIST])
        self.lexicon_tree.expandItem(ancestor)

        # word ngrams
        ancestor = QTreeWidgetItem(self.lexicon_tree, [WORD_NGRAMS])
        self.lexicon_tree.expandItem(ancestor)
        for item_str in [BIGRAMS, TRIGRAMS]:
            item = QTreeWidgetItem(ancestor, [item_str])
            self.lexicon_tree.expandItem(item)

        # signatures
        ancestor = QTreeWidgetItem(self.lexicon_tree, [SIGNATURES])
        self.lexicon_tree.expandItem(ancestor)
        for item in [SIGS_TO_STEMS, WORDS_TO_SIGS]:
            self.lexicon_tree.expandItem(QTreeWidgetItem(ancestor, [item]))

        # tries
        ancestor = QTreeWidgetItem(self.lexicon_tree, [TRIES])
        self.lexicon_tree.expandItem(ancestor)
        for item in [WORDS_AS_TRIES, SUCCESSORS, PREDECESSORS]:
            self.lexicon_tree.expandItem(QTreeWidgetItem(ancestor, [item]))

        # phonology
        ancestor = QTreeWidgetItem(self.lexicon_tree, [PHONOLOGY])
        self.lexicon_tree.expandItem(ancestor)
        for item in [PHONES, BIPHONES, TRIPHONES]:
            self.lexicon_tree.expandItem(QTreeWidgetItem(ancestor, [item]))

        # manifolds
        ancestor = QTreeWidgetItem(self.lexicon_tree, [MANIFOLDS])
        self.lexicon_tree.expandItem(ancestor)
        for item in [WORD_NEIGHBORS, VISUALIZED_GRAPH]:
            self.lexicon_tree.expandItem(QTreeWidgetItem(ancestor, [item]))

        self.status.clearMessage()
        self.status.showMessage('Navigation tree populated')
        print('Lexicon navigation tree populated', flush=True)

    def load_main_window(self, major_display=None, parameter_window=None):
        """
        Refresh the main window for the updated display content
        (most probably after a click or some event is triggered)
        """
        # get sizes of the three major PyQt objects
        major_display_size = self.majorDisplay.size()
        parameter_window_size = self.parameterWindow.size()
        lexicon_tree_size = self.lexicon_tree.size()

        if major_display:
            self.majorDisplay = major_display
        if parameter_window:
            self.parameterWindow = parameter_window

        # apply sizes to the major three objects
        self.majorDisplay.resize(major_display_size)
        self.parameterWindow.resize(parameter_window_size)
        self.lexicon_tree.resize(lexicon_tree_size)

        # set up:
        # 1) main splitter (b/w lexicon-tree+parameter window and major display)
        # 2) minor splitter (b/w lexicon-tree and parameter window)
        self.mainSplitter = QSplitter(Qt.Horizontal)
        self.mainSplitter.setHandleWidth(10)
        self.mainSplitter.setChildrenCollapsible(False)

        self.minorSplitter = QSplitter(Qt.Vertical)
        self.minorSplitter.setHandleWidth(10)
        self.minorSplitter.setChildrenCollapsible(False)

        self.minorSplitter.addWidget(self.lexicon_tree)
        self.minorSplitter.addWidget(self.parameterWindow)

        self.mainSplitter.addWidget(self.minorSplitter)
        self.mainSplitter.addWidget(self.majorDisplay)

        self.setCentralWidget(self.mainSplitter)

    def sig_to_stems_clicked(self, row):
        signature = self.sig_to_stems_major_table.item(row, 0).text()
        print(signature)
        signature = tuple(signature.split(SEP_SIG))

        stems = sorted(self.lexicon.signatures_to_stems()[signature])
        number_of_stems_per_column = 5

        # create a master list of sublists, where each sublist contains k stems
        # k = number_of_stems_per_column
        stem_rows = list()
        stem_row = list()

        for i, stem in enumerate(stems, 1):
            stem_row.append(stem)
            if not i % number_of_stems_per_column:
                stem_rows.append(stem_row)
                stem_row = list()
        if stem_row:
            stem_rows.append(stem_row)

        # set up the minor table as table widget
        sig_to_stems_minor_table = QTableWidget()
        sig_to_stems_minor_table.horizontalHeader().hide()
        sig_to_stems_minor_table.verticalHeader().hide()
        sig_to_stems_minor_table.clear()
        sig_to_stems_minor_table.setRowCount(len(stem_rows))
        sig_to_stems_minor_table.setColumnCount(number_of_stems_per_column)

        # fill in the minor table
        for row, stem_row in enumerate(stem_rows):
            for col, stem in enumerate(stem_row):
                item = QTableWidgetItem(stem)
                sig_to_stems_minor_table.setItem(row, col, item)

        sig_to_stems_minor_table.resizeColumnsToContents()

        minor_table_title = QLabel('{} (number of stems: {})'
                                   .format(SEP_SIG.join(signature), len(stems)))

        minor_table_widget_with_title = QWidget()
        layout = QVBoxLayout()
        layout.addWidget(minor_table_title)
        layout.addWidget(sig_to_stems_minor_table)
        minor_table_widget_with_title.setLayout(layout)

        new_display = QSplitter(Qt.Horizontal)
        new_display.setHandleWidth(10)
        new_display.setChildrenCollapsible(False)

        new_display.addWidget(self.sig_to_stems_major_table)
        new_display.addWidget(minor_table_widget_with_title)
        new_display_width = self.majorDisplay.width() / 2
        new_display.setSizes(
            [new_display_width * 0.4, new_display_width * 0.6])

        self.load_main_window(major_display=new_display)
        self.status.clearMessage()
        self.status.showMessage('{} selected'.format(signature))

    def unavailable_for_wordlist(self):
        self.load_main_window(major_display=QWidget(),
                              parameter_window=QWidget())
        self.status.showMessage('')
        warning = QMessageBox()
        warning.setIcon(QMessageBox.Warning)
        warning.setText('Unavailable for a wordlist')
        warning.setWindowTitle('Error')
        warning.setStandardButtons(QMessageBox.Ok)
        warning.exec_()

    def tree_item_clicked(self, item):
        """
        Trigger the appropriate action when something in the lexicon tree
        is clicked, and update the major display plus parameter window
        """
        item_str = item.text(0)

        if item_str in {WORD_NGRAMS, SIGNATURES, TRIES, PHONOLOGY, MANIFOLDS}:
            return

        print('loading', item_str, flush=True)

        self.status.clearMessage()
        self.status.showMessage('Loading {}...'.format(item_str))

        new_display = None
        new_parameter_window = None

        if item_str == WORDLIST:
            new_display = self.create_major_display_table(
                self.lexicon.word_phonology_dict().items(),
                key=lambda x: x[1].count, reverse=True,
                headers=['Word', 'Count', 'Frequency', 'Phones',
                         'Unigram plog', 'Avg unigram plog',
                         'Bigram plog', 'Avg bigram plog'],
                row_cell_functions=[
                    lambda x: x[0], lambda x: x[1].count,
                    lambda x: x[1].frequency,
                    lambda x: ' '.join(x[1].phones),
                    lambda x: x[1].unigram_plog,
                    lambda x: x[1].avg_unigram_plog,
                    lambda x: x[1].bigram_plog,
                    lambda x: x[1].avg_bigram_plog],
                cutoff=0)

        elif item_str == BIGRAMS:
            if self.lexicon.file_is_wordlist:
                self.unavailable_for_wordlist()
                return
            new_display = self.create_major_display_table(
                self.lexicon.word_bigram_counter().items(),
                key=lambda x: x[1], reverse=True,
                headers=['Bigram', 'Count'],
                row_cell_functions=[lambda x: SEP_NGRAM.join(x[0]),
                                    lambda x: x[1]],
                cutoff=2000)

        elif item_str == TRIGRAMS:
            if self.lexicon.file_is_wordlist:
                self.unavailable_for_wordlist()
                return
            new_display = self.create_major_display_table(
                self.lexicon.word_trigram_counter().items(),
                key=lambda x: x[1], reverse=True,
                headers=['Trigram', 'Count'],
                row_cell_functions=[lambda x: SEP_NGRAM.join(x[0]),
                                    lambda x: x[1]],
                cutoff=2000)

        elif item_str == SIGS_TO_STEMS:
            self.sig_to_stems_major_table = self.create_major_display_table(
                self.lexicon.signatures_to_stems().items(),
                key=lambda x: len(x[1]), reverse=True,
                headers=['Signature', 'Stem count', 'A few stems'],
                row_cell_functions=[lambda x: SEP_SIG.join(x[0]),
                                    lambda x: len(x[1]),
                                    lambda x: ', '.join(sorted(x[1])[:2]) +
                                              ', ...'],
                cutoff=0)
            # noinspection PyUnresolvedReferences
            self.sig_to_stems_major_table.cellClicked.connect(
                self.sig_to_stems_clicked)
            new_display = self.sig_to_stems_major_table

        elif item_str == WORDS_TO_SIGS:
            new_display = self.create_major_display_table(
                self.lexicon.words_to_signatures().items(),
                key=lambda x: len(x[1]), reverse=True,
                headers=['Word', 'Signature count', 'Signatures'],
                row_cell_functions=[lambda x: x[0],
                                    lambda x: len(x[1]),
                                    lambda x: ', '.join([SEP_SIG.join(sig)
                                                         for sig in
                                                         sorted(x[1])])],
                cutoff=2000)

        elif item_str == WORDS_AS_TRIES:
            words = self.lexicon.broken_words_left_to_right().keys()
            words_to_tries = dict()
            # key: word (str)
            # value: tuple of (str, str)
            # for left-to-right and right-to-left tries

            for word in words:
                l_r = ' '.join(self.lexicon.broken_words_left_to_right()[word])
                r_l = ' '.join(self.lexicon.broken_words_right_to_left()[word])
                words_to_tries[word] = (l_r, r_l)  # left-right, right-left

            new_display = self.create_major_display_table(
                words_to_tries.items(),
                key=lambda x: x[0], reverse=False,
                headers=['Word', 'Reversed word',
                         'Left-to-right trie', 'Right-to-left trie'],
                row_cell_functions=[lambda x: x[0], lambda x: x[0][::-1],
                                    lambda x: x[1][0], lambda x: x[1][1]],
                cutoff=0, set_text_alignment=[(3, Qt.AlignRight)])

        elif item_str == SUCCESSORS:
            new_display = self.create_major_display_table(
                self.lexicon.successors().items(),
                key=lambda x: len(x[1]), reverse=True,
                headers=['String', 'Successor count', 'Successors'],
                row_cell_functions=[lambda x: x[0],
                                    lambda x: len(x[1]),
                                    lambda x: ', '.join(sorted(x[1]))],
                cutoff=0)

        elif item_str == PREDECESSORS:
            new_display = self.create_major_display_table(
                self.lexicon.predecessors().items(),
                key=lambda x: len(x[1]), reverse=True,
                headers=['String', 'Predecessor count', 'Predecessors'],
                row_cell_functions=[lambda x: x[0],
                                    lambda x: len(x[1]),
                                    lambda x: ', '.join(sorted(x[1]))],
                cutoff=0)

        elif item_str == PHONES:
            new_display = self.create_major_display_table(
                self.lexicon.phone_dict().items(),
                key=lambda x: x[1].count, reverse=True,
                headers=['Phone', 'Count', 'Frequency', 'Plog'],
                row_cell_functions=[lambda x: x[0],
                                    lambda x: x[1].count,
                                    lambda x: x[1].frequency,
                                    lambda x: x[1].plog],
                cutoff=0)

        elif item_str == BIPHONES:
            new_display = self.create_major_display_table(
                self.lexicon.biphone_dict().items(),
                key=lambda x: x[1].count, reverse=True,
                headers=['Biphone', 'Count', 'Frequency',
                         'Mutual information (MI)', 'Weighted MI'],
                row_cell_functions=[lambda x: SEP_NGRAM.join(x[0]),
                                    lambda x: x[1].count,
                                    lambda x: x[1].frequency,
                                    lambda x: x[1].MI,
                                    lambda x: x[1].weighted_MI],
                cutoff=0)

        elif item_str == TRIPHONES:
            new_display = self.create_major_display_table(
                self.lexicon.phone_trigram_counter().items(),
                key=lambda x: x[1], reverse=True,
                headers=['Triphone', 'Count'],
                row_cell_functions=[lambda x: SEP_NGRAM.join(x[0]),
                                    lambda x: x[1]],
                cutoff=0)

        elif item_str == WORD_NEIGHBORS:
            if self.lexicon.file_is_wordlist:
                self.unavailable_for_wordlist()
                return
            word_to_freq = self.lexicon.word_unigram_counter()
            new_display = self.create_major_display_table(
                self.lexicon.words_to_neighbors().items(),
                key=lambda x: word_to_freq[x[0]], reverse=True,
                headers=['Word', 'Word count', 'Neighbors'],
                row_cell_functions=[lambda x: x[0],
                                    lambda x: word_to_freq[x[0]],
                                    lambda x: ' '.join(x[1])],
                cutoff=0)

        elif item_str == VISUALIZED_GRAPH:
            if self.lexicon.file_is_wordlist:
                self.unavailable_for_wordlist()
                return

            graph_width = self.screen_width - TREEWIDGET_WIDTH_MAX - 50
            graph_height = self.screen_height - 70
            html_name = 'show_manifold.html'

            manifold_name = '{}_manifold.json'.format(self.corpus_stem_name)
            manifold_filename = os.path.join(CONFIG_DIR, manifold_name)
            print('manifold_filename', manifold_filename)

            manifold_json_data = json_graph.node_link_data(
                self.lexicon.neighbor_graph())
            json.dump(manifold_json_data, open(manifold_filename, 'w'))

            viz_html = os.path.join(CONFIG_DIR, html_name)
            print('viz_html', viz_html)

            # write the show_manifold html file
            with open(viz_html, 'w') as f:
                print(SHOW_MANIFOLD_HTML.format(os.path.dirname(__file__),
                                                graph_width, graph_height,
                                                manifold_filename), file=f)

            url = Path(viz_html).as_uri()
            print('url:', url)

            new_display = QWebView()
            new_display.setUrl(QUrl(url))

        self.load_main_window(major_display=new_display,
                              parameter_window=new_parameter_window)

        self.status.clearMessage()
        self.status.showMessage('{} selected'.format(item_str))

    @staticmethod
    def create_major_display_table(input_iterable,
                                   key=lambda x: x, reverse=False,
                                   headers=None, row_cell_functions=None,
                                   cutoff=0,
                                   set_text_alignment=None):
        """
        This is a general function for creating a tabular display for the
        major display.
        """

        if not input_iterable:
            print('Warning: input is empty', flush=True)
            return

        if not hasattr(input_iterable, '__iter__'):
            print('Warning: input is not an iterable', flush=True)
            return

        number_of_headers = len(headers)
        number_of_columns = len(row_cell_functions)

        if number_of_headers != number_of_columns:
            print('headers and cell functions don\'t match', flush=True)
            return

        len_input = len(input_iterable)

        table_widget = QTableWidget()
        table_widget.clear()
        table_widget.setSortingEnabled(False)

        # set up row count
        if cutoff and cutoff < len_input:
            actual_cutoff = cutoff
        else:
            actual_cutoff = len_input

        table_widget.setRowCount(actual_cutoff)

        # set up column count and table headers
        table_widget.setColumnCount(number_of_headers)
        table_widget.setHorizontalHeaderLabels(headers)

        # fill in the table
        for row, x in enumerate(double_sorted(input_iterable, key=key,
                                              reverse=reverse)):
            for col, fn in enumerate(row_cell_functions):
                cell = fn(x)

                if isinstance(cell, (int, float)):
                    # cell is numeric
                    item = QTableWidgetItem()
                    item.setData(Qt.EditRole, cell)
                else:
                    # cell is not numeric
                    item = QTableWidgetItem(cell)

                if set_text_alignment:
                    for align_col, alignment in set_text_alignment:
                        if col == align_col:
                            item.setTextAlignment(alignment)

                table_widget.setItem(row, col, item)

            if not row < actual_cutoff:
                break

        table_widget.setSortingEnabled(True)
        table_widget.resizeColumnsToContents()

        return table_widget
Esempio n. 38
0
class SignalTabController(QWidget):
    frame_closed = pyqtSignal(SignalFrameController)
    not_show_again_changed = pyqtSignal()
    signal_created = pyqtSignal(Signal)
    files_dropped = pyqtSignal(list)
    frame_was_dropped = pyqtSignal(int, int)

    @property
    def num_frames(self):
        return self.splitter.count() - 1

    @property
    def signal_frames(self):
        """

        :rtype: list of SignalFrameController
        """
        return [self.splitter.widget(i) for i in range(self.num_frames)]

    @property
    def signal_undo_stack(self):
        return self.undo_stack

    def __init__(self, project_manager, parent=None):
        super().__init__(parent)
        self.ui = Ui_Interpretation()
        self.ui.setupUi(self)
        self.splitter = QSplitter()
        self.splitter.setStyleSheet("QSplitter::handle:vertical {\nmargin: 4px 0px; background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, \nstop:0 rgba(255, 255, 255, 0), \nstop:0.5 rgba(100, 100, 100, 100), \nstop:1 rgba(255, 255, 255, 0));\n	image: url(:/icons/data/icons/splitter_handle_horizontal.svg);\n}")
        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.setChildrenCollapsible(True)
        self.splitter.setHandleWidth(6)

        placeholder_widget = QWidget()
        placeholder_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
        self.undo_stack = QUndoStack()
        self.project_manager = project_manager

        self.splitter.addWidget(placeholder_widget)
        self.signal_vlay = QVBoxLayout()
        self.signal_vlay.setContentsMargins(0,0,0,0)
        self.signal_vlay.addWidget(self.splitter)
        self.ui.scrlAreaSignals.setLayout(self.signal_vlay)

        self.drag_pos = None

    def on_files_dropped(self, files):
        self.files_dropped.emit(files)

    def close_frame(self, frame:SignalFrameController):
        self.frame_closed.emit(frame)

    def add_signal_frame(self, proto_analyzer):
        sig_frame = SignalFrameController(proto_analyzer, self.undo_stack, self.project_manager, parent=self)
        sframes = self.signal_frames


        if len(proto_analyzer.signal.filename) == 0:
            # new signal from "create signal from selection"
            sig_frame.ui.btnSaveSignal.show()

        self.__create_connects_for_signal_frame(signal_frame=sig_frame)
        sig_frame.signal_created.connect(self.signal_created.emit)
        sig_frame.not_show_again_changed.connect(self.not_show_again_changed.emit)
        sig_frame.ui.lineEditSignalName.setToolTip(self.tr("Sourcefile: ") + proto_analyzer.signal.filename)
        sig_frame.apply_to_all_clicked.connect(self.on_apply_to_all_clicked)

        prev_signal_frame = sframes[-1] if len(sframes) > 0 else None
        if prev_signal_frame is not None and hasattr(prev_signal_frame, "ui"):
            sig_frame.ui.cbProtoView.setCurrentIndex(prev_signal_frame.ui.cbProtoView.currentIndex())

        sig_frame.blockSignals(True)

        if proto_analyzer.signal.qad_demod_file_loaded:
            sig_frame.ui.cbSignalView.setCurrentIndex(1)
            sig_frame.ui.cbSignalView.setDisabled(True)

        self.splitter.insertWidget(self.num_frames, sig_frame)
        sig_frame.blockSignals(False)

        default_view = constants.SETTINGS.value('default_view', 0, int)
        sig_frame.ui.cbProtoView.setCurrentIndex(default_view)

        return sig_frame

    def __create_connects_for_signal_frame(self, signal_frame: SignalFrameController):
        signal_frame.hold_shift = constants.SETTINGS.value('hold_shift_to_drag', False, type=bool)
        signal_frame.drag_started.connect(self.frame_dragged)
        signal_frame.frame_dropped.connect(self.frame_dropped)
        signal_frame.files_dropped.connect(self.on_files_dropped)
        signal_frame.closed.connect(self.close_frame)

    def add_empty_frame(self, filename: str, proto):
        sig_frame = SignalFrameController(proto_analyzer=proto, undo_stack=self.undo_stack,
                                          project_manager=self.project_manager, proto_bits=proto.decoded_proto_bits_str,
                                          parent=self)

        sig_frame.ui.lineEditSignalName.setText(filename)
        sig_frame.setMinimumHeight(sig_frame.height())
        sig_frame.set_empty_frame_visibilities()
        self.__create_connects_for_signal_frame(signal_frame=sig_frame)

        self.splitter.insertWidget(self.num_frames, sig_frame)

        return sig_frame

    def set_frame_numbers(self):
        for i, f in enumerate(self.signal_frames):
            f.ui.lSignalNr.setText("{0:d}:".format(i + 1))

    @pyqtSlot()
    def save_all(self):
        if self.num_frames == 0:
            return

        settings = constants.SETTINGS
        try:
            not_show = settings.value('not_show_save_dialog', type=bool, defaultValue=False)
        except TypeError:
            not_show = False

        if not not_show:
            cb = QCheckBox("Don't ask me again.")
            msg_box = QMessageBox(QMessageBox.Question, self.tr("Confirm saving all signals"),
                                  self.tr("All changed signal files will be overwritten. OK?"))
            msg_box.addButton(QMessageBox.Yes)
            msg_box.addButton(QMessageBox.No)
            msg_box.setCheckBox(cb)

            reply = msg_box.exec()
            not_show_again = cb.isChecked()
            settings.setValue("not_show_save_dialog", not_show_again)
            self.not_show_again_changed.emit()

            if reply != QMessageBox.Yes:
                return

        for f in self.signal_frames:
            if f.signal is None or f.signal.filename == "":
                continue
            f.signal.save()

    @pyqtSlot()
    def close_all(self):
        for f in self.signal_frames:
            f.my_close()

    @pyqtSlot(Signal)
    def on_apply_to_all_clicked(self, signal: Signal):
        for frame in self.signal_frames:
            if frame.signal is not None:
                frame.signal.noise_min_plot = signal.noise_min_plot
                frame.signal.noise_max_plot = signal.noise_max_plot

                frame.signal.block_protocol_update = True
                proto_needs_update = False

                if frame.signal.modulation_type != signal.modulation_type:
                    frame.signal.modulation_type = signal.modulation_type
                    proto_needs_update = True

                if frame.signal.qad_center != signal.qad_center:
                    frame.signal.qad_center = signal.qad_center
                    proto_needs_update = True

                if frame.signal.tolerance != signal.tolerance:
                    frame.signal.tolerance = signal.tolerance
                    proto_needs_update = True

                if frame.signal.noise_threshold != signal.noise_threshold:
                    frame.signal.noise_threshold = signal.noise_threshold
                    proto_needs_update = True

                if frame.signal.bit_len != signal.bit_len:
                    frame.signal.bit_len = signal.bit_len
                    proto_needs_update = True

                frame.signal.block_protocol_update = False

                if proto_needs_update:
                    frame.signal.protocol_needs_update.emit()

    @pyqtSlot(QPoint)
    def frame_dragged(self, pos: QPoint):
        self.drag_pos = pos

    @pyqtSlot(QPoint)
    def frame_dropped(self, pos: QPoint):
        start = self.drag_pos
        if start is None:
            return

        end = pos
        start_index = -1
        end_index = -1
        if self.num_frames > 1:
            for i, w in enumerate(self.signal_frames):
                if w.geometry().contains(start):
                    start_index = i

                if w.geometry().contains(end):
                    end_index = i

        self.swap_frames(start_index, end_index)
        self.frame_was_dropped.emit(start_index, end_index)

    @pyqtSlot(int, int)
    def swap_frames(self, from_index: int, to_index: int):
        if from_index != to_index:
            start_sig_widget = self.splitter.widget(from_index)
            self.splitter.insertWidget(to_index, start_sig_widget)

    @pyqtSlot()
    def on_participant_changed(self):
        for sframe in self.signal_frames:
            sframe.on_participant_changed()
Esempio n. 39
0
class RunWidget(QWidget):
    running = False
    device_list_signal = pyqtSignal(list, name="device_list_signal")
    cases = []

    def __init__(self, tester, *args, **kwargs):
        super().__init__(*args, **kwargs)
        ui_dir_path = os.path.dirname(__file__)
        ui_file_path = os.path.join(ui_dir_path, 'case_run.ui')
        uic.loadUi(ui_file_path, self)

        # set icon
        run_icon = QIcon()
        self.tester = tester
        self.config = self.tester.get_config()

        run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off)
        self.run_stop_btn.setIcon(run_icon)

        add_icon = QIcon()
        add_icon.addPixmap(QPixmap(self.config.images + '/add.png'), QIcon.Normal, QIcon.Off)
        self.addbtn.setIcon(add_icon)

        self.message_box = QMessageBox()

        self.dBCommandLineHelper = DBCommandLineHelper()

        self.addbtn.clicked.connect(self.click_add_case)
        self.run_stop_btn.clicked.connect(self.click_run_stop_btn)

        self.add_case_widget = None
        self.add_device_widget = None

        self.splitter = None
        self.case_widget = RunnerTableWidget([], [0])
        self.log_area = Console()
        self.splitter_setting()

        self.status_listener = CaseRunStatusListener()
        self.status_listener.listener_msg_signal.connect(self.update_case_name_color, Qt.QueuedConnection)
        self.tester.add_run_status_listener(self.status_listener)

    def splitter_setting(self):
        """
        set splitter
        :return:
        """
        if self.splitter:
            self.splitter = None
        self.splitter = QSplitter(Qt.Vertical)
        self.splitter.setHandleWidth(1)
        # add "case_widget" and "log_area" to splitter
        self.splitter.addWidget(self.case_widget)
        self.splitter.addWidget(self.log_area)

        # set the initial scale: 4:1
        self.splitter.setStretchFactor(0, 4)
        self.splitter.setStretchFactor(1, 1)
        self.case_table_layout.addWidget(self.splitter)

    def click_add_case(self):
        """
        click the button to show add case widget
        :return:
        """
        self.add_case_widget = AddCaseWidget()
        self.add_case_widget.select_case_signal.connect(self.show_cases, Qt.QueuedConnection)
        self.add_case_widget.setWindowModality(Qt.ApplicationModal)
        self.add_case_widget.show()

    def click_run_stop_btn(self):
        """
        start or stop to run case
        :return:
        """
        devices = []
        if self.running:
            self.stop_case()
            return
        if not self.cases:  # cases is null
            self.message_box.warning(self, "Message", "Please add cases first.", QMessageBox.Ok)
            return
        try:
            devices = self.tester.devices()
        except Exception as e:
            self.add_log("<font color='red'>" + str(e) + "</font>")
        if not devices:  # There is no device connected
            self.message_box.warning(self, "Message", "Please connect the device to your computer.", QMessageBox.Ok)
            return
        self.add_device_widget = AddDeviceWidget()
        self.add_device_widget.setWindowModality(Qt.ApplicationModal)
        self.add_device_widget.add_log_signal.connect(self.add_log, Qt.QueuedConnection)
        self.add_device_widget.run_case_signal.connect(self.run_case, Qt.QueuedConnection)
        self.device_list_signal.connect(self.add_device_widget.add_radio_to_widget, Qt.QueuedConnection)
        self.add_device_widget.show()
        try:
            self.device_list_signal.emit(devices)
        except Exception as e:
            self.add_log("<font color='red'><pre>" + str(e) + "</pre></font>")

    def add_log(self, log_info):
        """
        add log to log_area
        :return:
        """
        if self.log_area is None:
            return
        self.log_area.append(log_info)

    def update_case_name_color(self, msg, is_passed):
        """
        update case's font color according to the case's result
        pass: green; fail: red
        :param is_passed:
        :param msg:
        :return:
        """
        if msg.status == 601:
            self.add_log("<font color='green'> Start to install agent.</font>")
        elif msg.status == 602:
            self.add_log("<font color='green'> Install agent success.</font>")
        elif msg.status == 603:
            self.add_log("<font color='red'> Install agent Fail." + "\r Error Info:\r<pre>" + msg.message +
                         "</pre></font>")
        elif msg.status == 701:
            self.add_log("<font color='green'> Start agent.</font>")
        elif msg.status == 702:
            self.add_log("<font color='green'> Stop agent.</font>")
        elif msg.status == 703:
            self.add_log("<font color='red'> Agent error." + "\r Error Info:\r<pre>" + msg.message + "</pre></font>")

        for row_index in range(self.case_widget.dataTableWidget.rowCount()):
            case_id_item = self.case_widget.dataTableWidget.item(row_index, 1)  # get case id from dataTableWidget
            if msg.status == 2:  # test end
                if is_passed:
                    self.add_log("<font color='green'> All cases are Passed.</font>")
                self.stop_case()
                break
            if case_id_item.text() != str(msg.case_id):
                continue
            self.case_widget.dataTableWidget.selectRow(row_index)
            if msg.status == 101:  # default: case pass
                self.update_green(row_index)
            elif msg.status == 500:
                self.update_red(row_index)
                self.add_log("<font color='red'> Case Failed, case id: " + str(msg.case_id) + "</font>")
                self.add_log("<pre><font color='red'>" + str(msg.message) + "</font></pre>")

    def run_case(self, devices):
        kw_case_list = []
        if not self.cases:
            return
        for case_id in self.cases:
            kw_case = KWCase()
            case = self.dBCommandLineHelper.query_case_by_id(case_id)
            kw_case.id = case.id
            kw_case.name = case.name
            kw_case.content = case.content
            kw_case.data = case.data
            kw_case_list.append(kw_case)
        # set icon
        stop_icon = QIcon()
        stop_icon.addPixmap(QPixmap(self.config.images + '/stop.png'), QIcon.Normal, QIcon.Off)
        self.run_stop_btn.setIcon(stop_icon)
        self.run_stop_btn.setText("Stop")
        self.running = True
        if not devices:
            return
        try:
            self.tester.select_devices(devices)
            self.tester.run(kw_case_list)
        except Exception as e:
            self.stop_case()
            self.add_log(str(e))

    def stop_case(self):
        run_icon = QIcon()
        run_icon.addPixmap(QPixmap(self.config.images + '/run.png'), QIcon.Normal, QIcon.Off)
        self.run_stop_btn.setIcon(run_icon)          # change icon
        self.run_stop_btn.setText("Run")
        self.running = False
        try:
            self.tester.stop()
            self.tester.stop_server()
        except Exception as e:
            self.add_log(str(e))

    def show_cases(self, id_list):
        """
        show cases in RunnerTableWidget according to id list
        :param id_list:
        :return:
        """
        self.case_table_layout.removeWidget(self.splitter)
        case_list = []
        self.cases = id_list
        for case_id in id_list:
            case = self.dBCommandLineHelper.query_case_by_id(case_id)
            case_list.append(case)
        self.case_widget = RunnerTableWidget(case_list, [0])
        self.splitter_setting()  # reload splitter

    def update_green(self, row_index):
        """
        update item text color to green by row number
        :param row_index:
        :return:
        """
        brush_green_color = QBrush(QColor(55, 177, 88))
        for column_index in range(self.case_widget.dataTableWidget.columnCount()):
            item = self.case_widget.dataTableWidget.item(row_index, column_index)
            item.setForeground(brush_green_color)

    def update_red(self, row_index):
        """
        update item text color to red by row number
        :param row_index:
        :return:
        """
        brush_red_color = QBrush(QColor(255, 0, 0))
        for column_index in range(self.case_widget.dataTableWidget.columnCount()):
            item = self.case_widget.dataTableWidget.item(row_index, column_index)
            item.setForeground(brush_red_color)
Esempio n. 40
0
class App(QWidget):
    def __init__(self, lang='en'):
        super().__init__()

        self.params = Params(lang)
        self.initUI()

    def initUI(self):
        self.txt2func = {
            'はじめに': Introduction, 'Introduction': Introduction,
            '分析タスク': TypeOfTask, 'Task': TypeOfTask,
            '入力データ': SetFile, 'Input data': SetFile,
            'データの確認': DataCheck, 'Data check': DataCheck,
            '過学習': Overfitting, 'Overfitting': Overfitting,
            '分析の実行': Analysis, 'Analysis': Analysis,
            '結果の確認': Results, 'Results': Results,
            'バイアスとバリアンス': BiasVariance, 'Bias and Variance': BiasVariance,
            '学習曲線': LearningCurve, 'Learning curve': LearningCurve,
            '特徴量選択': FeatureSelection, 'Feature selection': FeatureSelection,
            '結果の確認2': Results2, 'Results 2': Results2,
            '学習曲線2': LearningCurve2, 'Learning curve 2': LearningCurve2,
            '予測': Prediction, 'Prediction': Prediction,
            'Error': Error}

        self.setMinimumSize(1280, 960)
        self.setStyleSheet('background-color: rgb(242, 242, 242)')

        vbox = QVBoxLayout(self)
        vbox.setSpacing(0)
        vbox.setContentsMargins(0, 0, 0, 0)

        top = QFrame(self)
        top.setFrameShape(QFrame.StyledPanel)
        top.setFixedHeight(50)
        top.setStyleSheet('background-color: white')

        self.splitter = QSplitter(Qt.Horizontal, self)
        self.splitter.setHandleWidth(0)

        self.menuview = MenuView(self.splitter, self.update_content,
                                 self.params)
        self.menuview.setWidgetResizable(True)

        self.contentview = Introduction(self.splitter,
                                        self.menuview.edit_button, self.params)
        self.contentview.setWidgetResizable(True)

        self.splitter.addWidget(self.menuview)
        self.splitter.addWidget(self.contentview)

        vbox.addWidget(top)
        vbox.addWidget(self.splitter)

        self.setLayout(vbox)

        self.center()
        # self.showMaximized()
        self.setWindowTitle('MALSS interactive')
        self.show()

    def center(self):
        # Get a rectangle of the main window.
        qr = self.frameGeometry()
        # Figure out the screen resolution; and from this resolution,
        # get the center point (x, y)
        cp = QDesktopWidget().availableGeometry().center()
        # Set the center of the rectangle to the center of the screen.
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def update_content(self, text):
        content = self.splitter.widget(1)
        if content is not None:
            if text in self.txt2func:
                content.hide()
                content.deleteLater()

                self.contentview =\
                    self.txt2func[text](self.splitter,
                                        self.menuview.edit_button,
                                        self.params)
                self.contentview.setWidgetResizable(True)
                self.splitter.addWidget(self.contentview)