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)
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
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)
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 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
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)
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)
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()
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);}" )
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()
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)
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)
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)
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()
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))
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)
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)
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())
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
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)
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)
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)
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()
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
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
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)
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))
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))
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
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
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)
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)
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
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
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
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()
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)
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)