def __init__(self, app, ui): QWidget.__init__(self) center_layout = QVBoxLayout() self.fwidg = QWidget() self.paramfunc = 0 self.c = Communicate() self.c.exec_operation_signal[Myc.FuncCommand].connect(app.exec_command) self.application = app self.setLayout(center_layout) print('ddd') self.ui = ui self.ui.setupUi(self.fwidg) splitter = QSplitter(Qt.Vertical) splitter.addWidget(self.fwidg) buttonExec = QPushButton() buttonExec.setText("Выполнить") center_layout.addWidget(buttonExec) buttonExec.clicked.connect(self.execOperation) splitter.addWidget(buttonExec) center_layout.addWidget(splitter)
def __init__(self): super().__init__() # information widget self.plotWidget = VariantPlotWidget() self.infoWidget = VariantInfoWidget() # splitter settings splitter = QSplitter(Qt.Horizontal) splitter.addWidget(self.plotWidget) splitter.addWidget(self.infoWidget) splitter.setStretchFactor(0, 3) splitter.setStretchFactor(1, 1) # layout layout = QBoxLayout(QBoxLayout.TopToBottom) layout.addWidget(splitter) self.setLayout(layout) # connect signals self.plotWidget.curvePlotted.connect(self.infoWidget.updateResults) self.plotWidget.plotReady.connect(self.infoWidget.showResults) self.plotWidget.cleared.connect(self.infoWidget.clear) self.infoWidget.legendChanged.connect(self.plotWidget.paintCalculation) # translate the graphical user interface self.retranslateUi()
def initUI(self): """Create User Interface. """ sourcePath = self.widgetSourcePath() parameters = self.widgetParameters() scroll = self.widgetImage() debug = self.widgetDebug() vbox1 = QVBoxLayout() vbox1.addLayout(sourcePath) hbox = QHBoxLayout() hbox.addLayout(parameters, 1) hbox.addLayout(scroll, 10) vbox1.addLayout(hbox) upSide = QWidget() upSide.setLayout(vbox1) vbox2 = QVBoxLayout() vbox2.addLayout(debug) downSide = QWidget() downSide.setLayout(vbox2) splitter = QSplitter(QtCore.Qt.Vertical) splitter.addWidget(upSide) splitter.addWidget(downSide) splitter.splitterMoved.connect(self.splitterMoved) mainLayout = QHBoxLayout() mainLayout.addWidget(splitter) self.setLayout(mainLayout) self.setGeometry(300, 300, 300, 150) self.show()
def __init__(self): QWidget.__init__(self) self.sun=1 hbox=QHBoxLayout(self) mainLayout = QSplitter(Qt.Horizontal) # splitter1 = QtGui.QSplitter(QtCore.Qt.Horizontal) self.three_d=display_widget() self.three_d.show() self.frame=layer_widget() self.frame.changed.connect(self.three_d.recalculate) mainLayout.addWidget(self.frame) mainLayout.addWidget(self.three_d) hbox.addWidget(mainLayout) self.setLayout(hbox) if enable_webupdates()==True: print("Looking for updates") self.web_update=update_thread() self.web_update.got_data.connect(self.got_help) self.web_update.start() self.frame.tab.itemSelectionChanged.connect(self.layer_selection_changed)
def __init__(self, parent=None): super(QMainWindow,self).__init__() #--------------------------------------------------------------- statusWin = QLabel(self) #statusWin = QPlainTextEdit(self) # status window #statusWin.appendHtml("<b>hallo<br>hallo2<br>hallo3</b>") tabWin = TabWidgets(self) # tabbed window print('hint status win: {0}'.format(statusWin.sizeHint())) print('hint_tab win: {0}'.format(tabWin.sizeHint())) print('hint main win: {0}'.format(self.sizeHint())) mSize = QFontMetrics(statusWin.font()) rowHt = mSize.lineSpacing() # fixed height for statusWin needed as the sizeHint of tabWin is very small #statusWin.setFixedHeight(4*rowHt+4) # add status window underneath plot Tab Widgets: spltVMain = QSplitter(QtCore.Qt.Vertical) spltVMain.addWidget(tabWin) spltVMain.addWidget(statusWin) # relative initial sizes of subwidgets, this doesn't work here # spltVMain.setStretchFactor(4,1) spltVMain.setSizes([statusWin.sizeHint().height()*2, statusWin.sizeHint().height()*0.05]) spltVMain.setFocus() # make spltVMain occupy the main area of QMainWindow and set inheritance self.setCentralWidget(spltVMain) print('size tabs: {0}'.format(tabWin.size())) print('size status: {0}'.format(statusWin.size())) print('size self: {0}'.format(self.size()))
def init_ui(self): """Initialize all GUI elements and show window.""" self.set_status('Welcome') self.create_menus() canvas_box = self.create_canvas() sequence_form = self.create_sequence_form() # let's have the sequence form over the canvas. vbox = QVBoxLayout() vbox.addLayout(sequence_form, stretch=0) vbox.setAlignment(Qt.AlignTop) vbox.addLayout(canvas_box, stretch=1) splitter = QSplitter(Qt.Horizontal) options = OptionPanel(self.args) for layout in [vbox, options]: widget = QWidget() widget.setLayout(layout) splitter.addWidget(widget) self.setCentralWidget(splitter) self.resize(600, 600) self.setWindowTitle('Dotplot') self.show()
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 __init__(self, signalNames): super(MainWindow, self).__init__() widget = QWidget() self.setCentralWidget(widget) self.consoleView = ConsoleView() self.signalView = SignalView() buttonsWidget = QWidget() scroll = QScrollArea() scroll.setWidget(self.signalView) scroll.setWidgetResizable(True) hboxSignalButtons = QHBoxLayout() self.signalButtons = self.createSignalButtons(signalNames, hboxSignalButtons) buttonsWidget.setLayout(hboxSignalButtons) splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) splitter.addWidget(scroll) splitter.addWidget(self.consoleView) vbox = QVBoxLayout() vbox.addWidget(buttonsWidget) vbox.addWidget(splitter) self.createActions() self.createMenu() widget.setLayout(vbox) self.setWindowTitle("kit")
def __init__(self, parent=None): super().__init__(parent) self.editor = PythonEditor(self) self.resize(650, 500) fileMenu = QMenu(self.tr("&File"), self) fileMenu.addAction(self.tr("&New…"), self.newFile, QKeySequence.New) fileMenu.addAction(self.tr("&Open…"), self.openFile, QKeySequence.Open) fileMenu.addAction(self.tr("&Save"), self.saveFile, QKeySequence.Save) fileMenu.addAction(self.tr("Save &As…"), self.saveFileAs, QKeySequence.SaveAs) fileMenu.addSeparator() fileMenu.addAction(self.tr("&Run…"), self.runScript, "Ctrl+R") fileMenu.addSeparator() fileMenu.addAction(self.tr("&Close"), self.close, platformSpecific.closeKeySequence()) self.menuBar().addMenu(fileMenu) self.fileChooser = FileChooser(self) self.fileChooser.fileOpened.connect(self.openFile) splitter = QSplitter(self) splitter.addWidget(self.fileChooser) splitter.addWidget(self.editor) splitter.setStretchFactor(0, 2) splitter.setStretchFactor(1, 5) splitter.setSizes([0, 1]) self.setCentralWidget(splitter) self.newFile() self.editor.modificationChanged.connect(self.setWindowModified)
class DualFrame(QFrame): def __init__(self, plot_title, finish_creating_plot_gui, is_top_level): QFrame.__init__(self) self.setWindowTitle(plot_title) self.main_layout = QVBoxLayout(self) self.splitter = QSplitter() self.dnd_frame_1 = DndFrame('Output Graphs') self.dnd_frame_2 = DndFrame('Graphs to Display') self.splitter.addWidget(self.dnd_frame_1) self.splitter.addWidget(self.dnd_frame_2) self.main_layout.addWidget(self.splitter) self.button_layout = QHBoxLayout() self.dnd_close_button = PyQtExtras.CommandButton('Close') self.dnd_close_button.set_handler(self.on_close) self.dnd_accept_button = PyQtExtras.CommandButton('Accept') self.dnd_accept_button.set_handler(self.on_accept) self.button_layout.addWidget(self.dnd_close_button) self.button_layout.addWidget(self.dnd_accept_button) self.button_layout.setAlignment(Qt.AlignRight) self.main_layout.addLayout(self.button_layout) self.finish_creating_plot_gui = finish_creating_plot_gui self.is_top_level = is_top_level self.setMinimumSize(QSize(800, 640)) def add_to_first(self, text): self.dnd_frame_1.add_label(text) def add_to_second(self, text): self.dnd_frame_2.add_label(text) def on_accept(self): plots_to_output = self.dnd_frame_1.get_output_plot_filenames() if self.finish_creating_plot_gui != None: self.finish_creating_plot_gui(plots_to_output) self.close() def on_close(self): self.hide() if self.is_top_level: QApplication.exit(0)
def sig_to_stems_clicked(self, row): signature = self.sig_to_stems_major_table.item(row, 0).text() print(signature) signature = tuple(signature.split(SEP_SIG)) stems = sorted(self.lexicon.signatures_to_stems()[signature]) number_of_stems_per_column = 5 # create a master list of sublists, where each sublist contains k stems # k = number_of_stems_per_column stem_rows = list() stem_row = list() for i, stem in enumerate(stems, 1): stem_row.append(stem) if not i % number_of_stems_per_column: stem_rows.append(stem_row) stem_row = list() if stem_row: stem_rows.append(stem_row) # set up the minor table as table widget sig_to_stems_minor_table = QTableWidget() sig_to_stems_minor_table.horizontalHeader().hide() sig_to_stems_minor_table.verticalHeader().hide() sig_to_stems_minor_table.clear() sig_to_stems_minor_table.setRowCount(len(stem_rows)) sig_to_stems_minor_table.setColumnCount(number_of_stems_per_column) # fill in the minor table for row, stem_row in enumerate(stem_rows): for col, stem in enumerate(stem_row): item = QTableWidgetItem(stem) sig_to_stems_minor_table.setItem(row, col, item) sig_to_stems_minor_table.resizeColumnsToContents() minor_table_title = QLabel('{} (number of stems: {})' .format(SEP_SIG.join(signature), len(stems))) minor_table_widget_with_title = QWidget() layout = QVBoxLayout() layout.addWidget(minor_table_title) layout.addWidget(sig_to_stems_minor_table) minor_table_widget_with_title.setLayout(layout) new_display = QSplitter(Qt.Horizontal) new_display.setHandleWidth(10) new_display.setChildrenCollapsible(False) new_display.addWidget(self.sig_to_stems_major_table) new_display.addWidget(minor_table_widget_with_title) new_display_width = self.majorDisplay.width() / 2 new_display.setSizes( [new_display_width * 0.4, new_display_width * 0.6]) self.load_main_window(major_display=new_display) self.status.clearMessage() self.status.showMessage('{} selected'.format(signature))
def getSplitter(self): splitter = QSplitter(Qt.Horizontal) # Give both boxes a minimum size so the minimumSizeHint will be # ignored when splitter.setSizes is called below for widget in self.editBox, self.previewBox: widget.setMinimumWidth(125) splitter.addWidget(widget) splitter.setSizes((50, 50)) splitter.setChildrenCollapsible(False) return splitter
def __init__(self, parent=None): super().__init__(parent) # initialize class attributes self._INPUTS_FIXED_WIDTH = 180 self._BUTTON_MIN_WIDTH = 80 self._OXYGEN_PATH_32 = os.path.join("resources", "icons", "oxygen", "32") # locale and language settings self.language = self.locale().name()[:2] self.qtTl = QTranslator() self.appTl = QTranslator() self.switchTranslator(self.qtTl, "qtbase", self.language) self.switchTranslator(self.appTl, "wuchshuellenrechner", self.language) # TODO(th) self.model = TreeModel() # setup gui self.setMinimumSize(1200, 760) self.createActions() self.createMainMenu() # plot widget self.plotWidget = VariantPlotView() self.plotWidget.setModel(self.model) # create vertical splitter splitter = QSplitter(Qt.Vertical) splitter.setContentsMargins(11, 11, 11, 11) splitter.addWidget(self.createEditBox()) splitter.addWidget(self.plotWidget) self.setCentralWidget(splitter) self.dataWidget.setModel(self.model) selectionModel = QItemSelectionModel(self.model) self.dataWidget.setSelectionModel(selectionModel) self.plotWidget.setSelectionModel(selectionModel) self.retranslateUi() self.model.dataChanged.connect(self.updateInputs) self.model.itemsInserted.connect(self.taxInput.setDisabled) self.model.allItemsRemoved.connect(self.taxInput.setEnabled) self.operationInput.textChanged.connect(self.updateOperation) self.districtInput.textChanged.connect(self.updateDistrict) self.managerInput.textChanged.connect(self.updateManager) self.locationInput.textChanged.connect(self.updateLocation) self.taxInput.stateChanged.connect(self.updateTax)
def create_mid_group(self): self.ddi_tree = QTreeWidget() self.ddi_tree.itemSelectionChanged.connect(self.show_ddi_details) ddi_details = QGroupBox() ddi_details_layout = QGridLayout() ddi_details_layout.setContentsMargins(0,0,0,0) ddi_details_layout.addWidget(self.create_common_ddi_details(), 0, 0, 1, 1) ddi_details_layout.addWidget(self.create_specific_ddi_details(), 1, 0, 3, 1) ddi_details.setLayout(ddi_details_layout) self.step_tree = QTreeWidget() self.step_tree.itemSelectionChanged.connect(self.show_step_details) step_details = QGroupBox() step_details_layout = QGridLayout() step_details_layout.setContentsMargins(0,0,0,0) step_details_layout.addWidget(self.create_common_step_details(), 0, 0, 1, 1) # step_details_layout.addWidget(self.create_specific_step_details(), 1, 0, 3, 1) step_details.setLayout(step_details_layout) splitter = QSplitter(self) splitter.addWidget(self.ddi_tree) splitter.addWidget(ddi_details) splitter.addWidget(self.step_tree) splitter.addWidget(step_details) hbox = QHBoxLayout() hbox.setContentsMargins(0,0,0,0) # self.__mix_to_layout(hbox, self.ddi_tree, ddi_details, self.step_tree, step_details) hbox.addWidget(splitter) # group_box.setLayout(hbox) return hbox
def setup_layout(self): main_widget = QWidget() main_layout = QHBoxLayout() main_layout_splitter = QSplitter(Qt.Horizontal, self) main_widget.setLayout(main_layout) main_layout.addWidget(main_layout_splitter) main_layout_splitter.addWidget(self.selection_list) main_layout_splitter.addWidget(self.view_tabs) main_layout_splitter.setStretchFactor(0, 1) main_layout_splitter.setStretchFactor(1, 10) self.setCentralWidget(main_widget)
def initUI(self): hbox = QHBoxLayout(self) topleft = QFrame(self) topleft.setFrameShape(QFrame.StyledPanel) topright = QFrame(self) topright.setFrameShape(QFrame.StyledPanel) bottom = QFrame(self) bottom.setFrameShape(QFrame.StyledPanel) splitter1 = QSplitter(Qt.Horizontal) splitter1.addWidget(topleft) splitter1.addWidget(topright) splitter2 = QSplitter(Qt.Vertical) splitter2.addWidget(splitter1) splitter2.addWidget(bottom) hbox.addWidget(splitter2) self.setLayout(hbox) self.setGeometry(300, 300, 300, 200) self.setWindowTitle('QSplitter') self.show()
def __init__(self): super(MainWindow, self).__init__() self.createActions() self.createMenus() # self.createToolBars() self.createStatusBar() treeLeft = FileTree() treeRight = FileTree() sp = QSplitter(Qt.Horizontal) sp.addWidget(treeLeft) sp.addWidget(treeRight) self.setCentralWidget(sp) self.resize(640, 480)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.container = QSplitter(self) self.setCentralWidget(self.container) #mon = DMX_Monitor(self) mon = None self.container.addWidget(ControlPanel(self, mon)) if mon: self.container.addWidget(mon) self.createActions() self.createMenus() self.createStatusBar() def about(self): QMessageBox.about(self, "About Application", __main__.__doc__) def createActions(self): self.exitAct = QAction("E&xit", self, shortcut="Ctrl+Q", statusTip="Exit the application", triggered=self.close) self.aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) self.aboutQtAct = QAction("About &Qt", self, statusTip="Show the Qt library's About box", triggered=QApplication.instance().aboutQt) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.exitAct) self.helpMenu = self.menuBar().addMenu("&About") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) def createStatusBar(self): self.statusBar().showMessage("Ready")
def __init__(self, chat_window, nick, parent=None): QWidget.__init__(self, parent) self.chat_window = chat_window self.nick = nick self.disabled = False self.cleared = False self.url_regex = re.compile(URL_REGEX) self.chat_log = QTextBrowser() self.chat_log.setOpenExternalLinks(True) self.chat_input = QTextEdit() self.chat_input.textChanged.connect(self.chatInputTextChanged) self.send_button = QPushButton("Send") self.send_button.clicked.connect(self.sendMessage) # Set the min height for the chatlog and a matching fixed height for the send button chat_input_font_metrics = QFontMetrics(self.chat_input.font()) self.chat_input.setMinimumHeight(chat_input_font_metrics.lineSpacing() * 3) self.send_button.setFixedHeight(chat_input_font_metrics.lineSpacing() * 3) hbox = QHBoxLayout() hbox.addWidget(self.chat_input) hbox.addWidget(self.send_button) # Put the chatinput and send button in a wrapper widget so they may be added to the splitter chat_input_wrapper = QWidget() chat_input_wrapper.setLayout(hbox) chat_input_wrapper.setMinimumHeight(chat_input_font_metrics.lineSpacing() * 3.7) # Put the chat log and chat input into a splitter so the user can resize them at will splitter = QSplitter(Qt.Vertical) splitter.addWidget(self.chat_log) splitter.addWidget(chat_input_wrapper) splitter.setSizes([int(parent.height()), 1]) hbox = QHBoxLayout() hbox.addWidget(splitter) self.setLayout(hbox) self.typing_timer = QTimer() self.typing_timer.setSingleShot(True) self.typing_timer.timeout.connect(self.stoppedTyping)
def create_settings(self): """Create the widget, organized in two parts. Notes ----- When you add widgets in config, remember to update show_settings too """ bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Apply | QDialogButtonBox.Cancel) self.idx_ok = bbox.button(QDialogButtonBox.Ok) self.idx_apply = bbox.button(QDialogButtonBox.Apply) self.idx_cancel = bbox.button(QDialogButtonBox.Cancel) bbox.clicked.connect(self.button_clicked) page_list = QListWidget() page_list.setSpacing(1) page_list.currentRowChanged.connect(self.change_widget) pages = ['General', 'Overview', 'Signals', 'Channels', 'Spectrum', 'Notes', 'Video'] for one_page in pages: page_list.addItem(one_page) self.stacked = QStackedWidget() self.stacked.addWidget(self.config) self.stacked.addWidget(self.parent.overview.config) self.stacked.addWidget(self.parent.traces.config) self.stacked.addWidget(self.parent.channels.config) self.stacked.addWidget(self.parent.spectrum.config) self.stacked.addWidget(self.parent.notes.config) self.stacked.addWidget(self.parent.video.config) hsplitter = QSplitter() hsplitter.addWidget(page_list) hsplitter.addWidget(self.stacked) btnlayout = QHBoxLayout() btnlayout.addStretch(1) btnlayout.addWidget(bbox) vlayout = QVBoxLayout() vlayout.addWidget(hsplitter) vlayout.addLayout(btnlayout) self.setLayout(vlayout)
def setupViews(self): splitter = QSplitter() table = QTableView() self.pieChart = PieView() splitter.addWidget(table) splitter.addWidget(self.pieChart) splitter.setStretchFactor(0, 0) splitter.setStretchFactor(1, 1) table.setModel(self.model) self.pieChart.setModel(self.model) self.selectionModel = QItemSelectionModel(self.model) table.setSelectionModel(self.selectionModel) self.pieChart.setSelectionModel(self.selectionModel) table.horizontalHeader().setStretchLastSection(True) self.setCentralWidget(splitter)
def __init_ui__(self): vbox = QVBoxLayout() splitter = QSplitter() splitter.addWidget(self.file_view) splitter.addWidget(self.overview) vbox.addWidget(splitter, 1) vbox.addWidget(self.lb_path) button_box = QHBoxLayout() button_box.addWidget(self.pb_select) button_box.addStretch(1) button_box.addWidget(self.pb_publish) button_box.addWidget(self.pb_zip) vbox.addLayout(button_box) self.setLayout(vbox)
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)
def main(args): app = QApplication(args) page = QSplitter() data = Model(1000, 10, page) selections = QItemSelectionModel(data) table = QTableView() table.setModel(data) table.setSelectionModel(selections) table.horizontalHeader().setSectionsMovable(True) table.verticalHeader().setSectionsMovable(True) # Set StaticContents to enable minimal repaints on resizes. table.viewport().setAttribute(Qt.WA_StaticContents) page.addWidget(table) tree = QTreeView() tree.setModel(data) tree.setSelectionModel(selections) tree.setUniformRowHeights(True) tree.header().setStretchLastSection(False) tree.viewport().setAttribute(Qt.WA_StaticContents) # Disable the focus rect to get minimal repaints when scrolling on Mac. tree.setAttribute(Qt.WA_MacShowFocusRect, False) page.addWidget(tree) list = QListView() list.setModel(data) list.setSelectionModel(selections) list.setViewMode(QListView.IconMode) list.setSelectionMode(QAbstractItemView.ExtendedSelection) list.setAlternatingRowColors(False) list.viewport().setAttribute(Qt.WA_StaticContents) list.setAttribute(Qt.WA_MacShowFocusRect, False) page.addWidget(list) page.setWindowIcon(QIcon(images_dir + '/interview.png')) page.setWindowTitle("Interview") page.show() return app.exec_()
class TestWindow(QWidget): TMPDIR = "tmp" TMPHTMLFILE = os.path.join(TMPDIR,'tmptext.html') def __init__(self,parent = None): QWidget.__init__(self,parent) if os.path.isdir(TestWindow.TMPDIR) == False: os.mkdir(TestWindow.TMPDIR) self.textEditor = TextEditor(self) self.webViewer = QWebView(self) self.setupUI() self.textEditor.textChangeSignal.connect(self.reloadText) def reloadText(self,dataDict): if self.webViewer.isVisible() == False: self.webViewer.show() with codecs.open( ResourceManager.getResourceAbsPath('template.html'),'r','utf-8' ) as templateFileObj: templateStr = templateFileObj.read() with open( TestWindow.TMPHTMLFILE,'wb' ) as tempFileObj: tempFileObj.write( (templateStr % dataDict[TextEditor.KEY_ORIGINALTXET]).encode('utf-8') ) self.webViewer.load(QUrl( "file:///%s" % os.path.abspath( TestWindow.TMPHTMLFILE ) )) def setupUI(self): self.webViewer.hide() layout = QHBoxLayout(self) self.splitter = QSplitter(self) self.splitter.addWidget(self.textEditor) self.splitter.addWidget(self.webViewer) layout.addWidget(self.splitter) self.textEditor.resize(400,600) self.webViewer.resize(400,600) self.resize(800,600) self.splitter.setStyleSheet("background-color:green;") self.textEditor.setStyleSheet("background-color:white;border:none;") self.webViewer.setStyleSheet("background-color:white;")
def setupViews(self): splitter = QSplitter() self.table = QTableView() self.pieChart = PieView() splitter.addWidget(self.pieChart) splitter.addWidget(self.table) splitter.setStretchFactor(0, 0) splitter.setStretchFactor(1, 0) self.table.setModel(self.model) self.pieChart.setModel(self.model2) self.selectionModel = QItemSelectionModel(self.model2) self.table.setSelectionModel(self.selectionModel) #self.pieChart.setSelectionModel(self.selectionModel) #table.setColumnWidth(0,100) self.setCentralWidget(splitter) self.table.doubleClicked.connect(self.ClickAction_table)
def initUI(self): ''' Example hbox splitter2 splitter1 topleft vbox self.lbl combo topright bottom ''' # splitter hbox = QHBoxLayout(self) topleft = QFrame(self) topleft.setFrameShape(QFrame.StyledPanel) topright = QFrame(self) topright.setFrameShape(QFrame.StyledPanel) bottom = QFrame(self) bottom.setFrameShape(QFrame.StyledPanel) splitter1 = QSplitter(Qt.Horizontal) splitter1.addWidget(topleft) splitter1.addWidget(topright) splitter2 = QSplitter(Qt.Vertical) splitter2.addWidget(splitter1) splitter2.addWidget(bottom) hbox.addWidget(splitter2) self.setLayout(hbox) # combo self.lbl = QLabel("Ubuntu", self) combo = QComboBox(self) combo.addItem("Ubuntu") combo.addItem("Mandriva") combo.addItem("Fedora") combo.addItem("Arch") combo.addItem("Gentoo") combo.activated[str].connect(self.onActivated) # put combo and label into layout into frame vbox = QVBoxLayout(topleft) vbox.addWidget(self.lbl) vbox.addWidget(combo) self.setGeometry(300, 300, 300, 200) self.setWindowTitle('QSplitter') self.show()
def __init__(self, parent=None): super().__init__(parent) self.editor = PythonEditor(self) self.fileChooser = FileChooser(self) self.fileChooser.fileOpened.connect(self.openFile) self.outputEdit = OutputEdit(self) splitter = QSplitter(self) self.vSplitter = QSplitter(Qt.Vertical, splitter) self.vSplitter.addWidget(self.editor) self.vSplitter.addWidget(self.outputEdit) self.vSplitter.setStretchFactor(0, 1) self.vSplitter.setStretchFactor(1, 0) splitter.addWidget(self.fileChooser) splitter.addWidget(self.vSplitter) splitter.setStretchFactor(0, 0) splitter.setStretchFactor(1, 1) statusBar = ScriptingStatusBar(self) self.setCentralWidget(splitter) self.setStatusBar(statusBar) self.newFile() self.editor.modificationChanged.connect(self.setWindowModified) statusBar.setPosition(self.editor.textCursor()) self.editor.cursorPositionChanged.connect( lambda: statusBar.setPosition(self.sender().textCursor())) statusBar.setIndent(self.editor.indent()) self.editor.indentChanged.connect(statusBar.setIndent) statusBar.indentModified.connect(self.editor.setIndent) statusBar.positionClicked.connect(self.gotoLine) statusBar.clearButtonClicked.connect(self.outputEdit.clear) statusBar.runButtonClicked.connect(self.runScript) gotoLineShortcut = QShortcut(QKeySequence("Ctrl+G"), self) gotoLineShortcut.activated.connect(self.gotoLine) self.readSettings() splitter.splitterMoved.connect(self.writeSettings) self.vSplitter.splitterMoved.connect(self.writeSettings)
class WindowUI(object): def widgetTraining(self): return TrainingWidget(self.classes_tree_view) def widgetRecognition(self): return RecognitionWidget(self.classes_tree_view) def widgetDataset(self): return DatasetWidget(self.classes_tree_view) def setupUI(self): """Create User Interface. """ mainWidget = QWidget() mainLayout = QHBoxLayout() tabs = QTabWidget() self.classes_tree_view = ClassesTreeView(self) tabs.addTab(self.widgetDataset(), self.tr("Dataset")) tabs.addTab(self.widgetTraining(), self.tr("Training")) tabs.addTab(self.widgetRecognition(), self.tr("Recognition")) leftLayout, rightLayout = QHBoxLayout(), QHBoxLayout() leftLayout.addWidget(self.classes_tree_view) rightLayout.addWidget(tabs) left, right = QWidget(), QWidget() left.setLayout(leftLayout) right.setLayout(rightLayout) self.hsplitter = QSplitter(QtCore.Qt.Horizontal) self.hsplitter.addWidget(left) self.hsplitter.addWidget(right) self.hsplitter.setStretchFactor(1, 3) mainLayout.addWidget(self.hsplitter) mainWidget.setLayout(mainLayout) self.setCentralWidget(mainWidget)
def splitViewSpace(self, viewspace, orientation): """Split the given view. If orientation == Qt.Horizontal, adds a new view to the right. If orientation == Qt.Vertical, adds a new view to the bottom. """ active = viewspace is self.activeViewSpace() splitter = viewspace.parentWidget() newspace = ViewSpace(self) if splitter.count() == 1: splitter.setOrientation(orientation) size = splitter.sizes()[0] splitter.addWidget(newspace) splitter.setSizes([size / 2, size / 2]) elif splitter.orientation() == orientation: index = splitter.indexOf(viewspace) splitter.insertWidget(index + 1, newspace) else: index = splitter.indexOf(viewspace) newsplitter = QSplitter() newsplitter.setOrientation(orientation) sizes = splitter.sizes() splitter.insertWidget(index, newsplitter) newsplitter.addWidget(viewspace) splitter.setSizes(sizes) size = newsplitter.sizes()[0] newsplitter.addWidget(newspace) newsplitter.setSizes([size / 2, size / 2]) self._viewSpaces.insert(0, newspace) newspace.showDocument(viewspace.document()) if active: newspace.activeView().setFocus() self.actionCollection.window_close_view.setEnabled(self.canCloseViewSpace()) self.actionCollection.window_close_others.setEnabled(self.canCloseViewSpace())
class GuiMain(QMainWindow): def __init__(self): QMainWindow.__init__(self) logger.debug("Initialising GUI ...") self.setObjectName("GuiMain") self.mainConf = nw.CONFIG self.threadPool = QThreadPool() # System Info # =========== logger.info("OS: %s" % self.mainConf.osType) logger.info("Kernel: %s" % self.mainConf.kernelVer) logger.info("Host: %s" % self.mainConf.hostName) logger.info("Qt5 Version: %s (%d)" % ( self.mainConf.verQtString, self.mainConf.verQtValue) ) logger.info("PyQt5 Version: %s (%d)" % ( self.mainConf.verPyQtString, self.mainConf.verPyQtValue) ) logger.info("Python Version: %s (0x%x)" % ( self.mainConf.verPyString, self.mainConf.verPyHexVal) ) # Core Classes # ============ # Core Classes and Settings self.theTheme = GuiTheme(self) self.theProject = NWProject(self) self.theIndex = NWIndex(self.theProject, self) self.hasProject = False self.isFocusMode = False # Prepare Main Window self.resize(*self.mainConf.getWinSize()) self._updateWindowTitle() self.setWindowIcon(QIcon(self.mainConf.appIcon)) # Build the GUI # ============= # Main GUI Elements self.statusBar = GuiMainStatus(self) self.treeView = GuiProjectTree(self) self.docEditor = GuiDocEditor(self) self.viewMeta = GuiDocViewDetails(self) self.docViewer = GuiDocViewer(self) self.treeMeta = GuiItemDetails(self) self.projView = GuiOutline(self) self.projMeta = GuiOutlineDetails(self) self.mainMenu = GuiMainMenu(self) # Minor Gui Elements self.statusIcons = [] self.importIcons = [] # Project Tree View self.treePane = QWidget() self.treeBox = QVBoxLayout() self.treeBox.setContentsMargins(0, 0, 0, 0) self.treeBox.addWidget(self.treeView) self.treeBox.addWidget(self.treeMeta) self.treePane.setLayout(self.treeBox) # Splitter : Document Viewer / Document Meta self.splitView = QSplitter(Qt.Vertical) self.splitView.addWidget(self.docViewer) self.splitView.addWidget(self.viewMeta) self.splitView.setSizes(self.mainConf.getViewPanePos()) # Splitter : Document Editor / Document Viewer self.splitDocs = QSplitter(Qt.Horizontal) self.splitDocs.addWidget(self.docEditor) self.splitDocs.addWidget(self.splitView) # Splitter : Project Outlie / Outline Details self.splitOutline = QSplitter(Qt.Vertical) self.splitOutline.addWidget(self.projView) self.splitOutline.addWidget(self.projMeta) self.splitOutline.setSizes(self.mainConf.getOutlinePanePos()) # Main Tabs : Edirot / Outline self.tabWidget = QTabWidget() self.tabWidget.setTabPosition(QTabWidget.East) self.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;}") self.tabWidget.addTab(self.splitDocs, "Editor") self.tabWidget.addTab(self.splitOutline, "Outline") self.tabWidget.currentChanged.connect(self._mainTabChanged) # Splitter : Project Tree / Main Tabs xCM = self.mainConf.pxInt(4) self.splitMain = QSplitter(Qt.Horizontal) self.splitMain.setContentsMargins(xCM, xCM, xCM, xCM) self.splitMain.addWidget(self.treePane) self.splitMain.addWidget(self.tabWidget) self.splitMain.setSizes(self.mainConf.getMainPanePos()) # Indices of All Splitter Widgets self.idxTree = self.splitMain.indexOf(self.treePane) self.idxMain = self.splitMain.indexOf(self.tabWidget) self.idxEditor = self.splitDocs.indexOf(self.docEditor) self.idxViewer = self.splitDocs.indexOf(self.splitView) self.idxViewDoc = self.splitView.indexOf(self.docViewer) self.idxViewMeta = self.splitView.indexOf(self.viewMeta) self.idxTabEdit = self.tabWidget.indexOf(self.splitDocs) self.idxTabProj = self.tabWidget.indexOf(self.splitOutline) # Splitter Behaviour self.splitMain.setCollapsible(self.idxTree, False) self.splitMain.setCollapsible(self.idxMain, False) self.splitDocs.setCollapsible(self.idxEditor, False) self.splitDocs.setCollapsible(self.idxViewer, True) self.splitView.setCollapsible(self.idxViewDoc, False) self.splitView.setCollapsible(self.idxViewMeta, False) # Editor / Viewer Default State self.splitView.setVisible(False) self.docEditor.closeSearch() # Initialise the Project Tree self.treeView.itemSelectionChanged.connect(self._treeSingleClick) self.treeView.itemDoubleClicked.connect(self._treeDoubleClick) self.rebuildTree() # Set Main Window Elements self.setMenuBar(self.mainMenu) self.setCentralWidget(self.splitMain) self.setStatusBar(self.statusBar) # Finalise Initialisation # ======================= # Set Up Auto-Save Project Timer self.asProjTimer = QTimer() self.asProjTimer.timeout.connect(self._autoSaveProject) # Set Up Auto-Save Document Timer self.asDocTimer = QTimer() self.asDocTimer.timeout.connect(self._autoSaveDocument) # Shortcuts and Actions self._connectMenuActions() keyReturn = QShortcut(self.treeView) keyReturn.setKey(QKeySequence(Qt.Key_Return)) keyReturn.activated.connect(self._treeKeyPressReturn) keyEscape = QShortcut(self) keyEscape.setKey(QKeySequence(Qt.Key_Escape)) keyEscape.activated.connect(self._keyPressEscape) # Forward Functions self.setStatus = self.statusBar.setStatus self.setProjectStatus = self.statusBar.setProjectStatus # Force a show of the GUI self.show() # Check that config loaded fine self.reportConfErr() # Initialise Main GUI self.initMain() self.asProjTimer.start() self.asDocTimer.start() self.statusBar.clearStatus() # Handle Windows Mode self.showNormal() if self.mainConf.isFullScreen: self.toggleFullScreenMode() logger.debug("GUI initialisation complete") # Check if a project path was provided at command line, and if # not, open the project manager instead. if self.mainConf.cmdOpen is not None: logger.debug("Opening project from additional command line option") self.openProject(self.mainConf.cmdOpen) else: if self.mainConf.showGUI: self.showProjectLoadDialog() # Show the latest release notes, if they haven't been shown before if hexToInt(self.mainConf.lastNotes) < hexToInt(nw.__hexversion__): if self.mainConf.showGUI: self.showAboutNWDialog(showNotes=True) self.mainConf.lastNotes = nw.__hexversion__ logger.debug("novelWriter is ready ...") self.setStatus("novelWriter is ready ...") return def clearGUI(self): """Wrapper function to clear all sub-elements of the main GUI. """ # Project Area self.treeView.clearTree() self.treeMeta.clearDetails() # Work Area self.docEditor.clearEditor() self.docEditor.setDictionaries() self.closeDocViewer() self.projMeta.clearDetails() # General self.statusBar.clearStatus() self._updateWindowTitle() return True def initMain(self): """Initialise elements that depend on user settings. """ self.asProjTimer.setInterval(int(self.mainConf.autoSaveProj*1000)) self.asDocTimer.setInterval(int(self.mainConf.autoSaveDoc*1000)) return True ## # Project Actions ## def newProject(self, projData=None): """Create new project via the new project wizard. """ if self.hasProject: if not self.closeProject(): self.makeAlert( "Cannot create new project when another project is open.", nwAlert.ERROR ) return False if projData is None: projData = self.showNewProjectDialog() if projData is None: return False projPath = projData.get("projPath", None) if projPath is None or projData is None: logger.error("No projData or projPath set") return False if os.path.isfile(os.path.join(projPath, self.theProject.projFile)): self.makeAlert( "A project already exists in that location. Please choose another folder.", nwAlert.ERROR ) return False logger.info("Creating new project") if self.theProject.newProject(projData): self.rebuildTree() self.saveProject() self.hasProject = True self.docEditor.setDictionaries() self.rebuildIndex(beQuiet=True) self.statusBar.setRefTime(self.theProject.projOpened) self.statusBar.setProjectStatus(True) self.statusBar.setDocumentStatus(None) self.statusBar.setStatus("New project created ...") self._updateWindowTitle(self.theProject.projName) else: self.theProject.clearProject() return False return True def closeProject(self, isYes=False): """Closes the project if one is open. isYes is passed on from the close application event so the user doesn't get prompted twice to confirm. """ if not self.hasProject: # There is no project loaded, everything OK return True if not isYes: msgYes = self.askQuestion( "Close Project", "Close the current project?<br>Changes are saved automatically." ) if not msgYes: return False if self.docEditor.docChanged: self.saveDocument() if self.theProject.projAltered: saveOK = self.saveProject() doBackup = False if self.theProject.doBackup and self.mainConf.backupOnClose: doBackup = True if self.mainConf.askBeforeBackup: msgYes = self.askQuestion( "Backup Project", "Backup the current project?" ) if not msgYes: doBackup = False if doBackup: self.theProject.zipIt(False) else: saveOK = True if saveOK: self.closeDocument() self.docViewer.clearNavHistory() self.projView.closeOutline() self.theProject.closeProject() self.theIndex.clearIndex() self.clearGUI() self.hasProject = False self.tabWidget.setCurrentWidget(self.splitDocs) return saveOK def openProject(self, projFile): """Open a project from a projFile path. """ if projFile is None: return False # Make sure any open project is cleared out first before we load # another one if not self.closeProject(): return False # Switch main tab to editor view self.tabWidget.setCurrentWidget(self.splitDocs) # Try to open the project if not self.theProject.openProject(projFile): # The project open failed. if self.theProject.lockedBy is None: # The project is not locked, so failed for some other # reason handled by the project class. return False try: lockDetails = ( "<br><br>The project was locked by the computer " "'%s' (%s %s), last active on %s" ) % ( self.theProject.lockedBy[0], self.theProject.lockedBy[1], self.theProject.lockedBy[2], datetime.fromtimestamp( int(self.theProject.lockedBy[3]) ).strftime("%x %X") ) except Exception: lockDetails = "" msgBox = QMessageBox() msgRes = msgBox.warning( self, "Project Locked", ( "The project is already open by another instance of novelWriter, and " "is therefore locked. Override lock and continue anyway?<br><br>" "Note: If the program or the computer previously crashed, the lock " "can safely be overridden. If, however, another instance of " "novelWriter has the project open, overriding the lock may corrupt " "the project, and is not recommended.%s" ) % lockDetails, QMessageBox.Yes | QMessageBox.No, QMessageBox.No ) if msgRes == QMessageBox.Yes: if not self.theProject.openProject(projFile, overrideLock=True): return False else: return False # Project is loaded self.hasProject = True # Load the tag index self.theIndex.loadIndex() # Update GUI self._updateWindowTitle(self.theProject.projName) self.rebuildTree() self.docEditor.setDictionaries() self.docEditor.setSpellCheck(self.theProject.spellCheck) self.mainMenu.setAutoOutline(self.theProject.autoOutline) self.statusBar.setRefTime(self.theProject.projOpened) self.statusBar.setStats(self.theProject.currWCount, 0) # Restore previously open documents, if any if self.theProject.lastEdited is not None: self.openDocument(self.theProject.lastEdited, doScroll=True) if self.theProject.lastViewed is not None: self.viewDocument(self.theProject.lastViewed) # Check if we need to rebuild the index if self.theIndex.indexBroken: self.rebuildIndex() # Make sure the changed status is set to false on all that was # just opened qApp.processEvents() self.docEditor.setDocumentChanged(False) self.theProject.setProjectChanged(False) logger.debug("Project load complete") return True def saveProject(self, autoSave=False): """Save the current project. """ if not self.hasProject: logger.error("No project open") return False # If the project is new, it may not have a path, so we need one if self.theProject.projPath is None: projPath = self.selectProjectPath() self.theProject.setProjectPath(projPath) if self.theProject.projPath is None: return False self.treeView.saveTreeOrder() self.theProject.saveProject(autoSave=autoSave) self.theIndex.saveIndex() return True ## # Document Actions ## def closeDocument(self): """Close the document and clear the editor and title field. """ if not self.hasProject: logger.error("No project open") return False self.docEditor.saveCursorPosition() if self.docEditor.docChanged: self.saveDocument() self.docEditor.clearEditor() return True def openDocument(self, tHandle, tLine=None, changeFocus=True, doScroll=False): """Open a specific document, optionally at a given line. """ if not self.hasProject: logger.error("No project open") return False self.closeDocument() self.tabWidget.setCurrentWidget(self.splitDocs) if self.docEditor.loadText(tHandle, tLine): if changeFocus: self.docEditor.setFocus() self.theProject.setLastEdited(tHandle) self.treeView.setSelectedHandle(tHandle, doScroll=doScroll) else: return False return True def openNextDocument(self, tHandle, wrapAround=False): """Opens the next document in the project tree, following the document with the given handle. Stops when reaching the end. """ if not self.hasProject: logger.error("No project open") return False self.treeView.flushTreeOrder() nHandle = None # The next handle after tHandle fHandle = None # The first file handle we encounter foundIt = False # We've found tHandle, pick the next we see for tItem in self.theProject.projTree: if tItem is None: continue if tItem.itemType != nwItemType.FILE: continue if fHandle is None: fHandle = tItem.itemHandle if tItem.itemHandle == tHandle: foundIt = True elif foundIt: nHandle = tItem.itemHandle break if nHandle is not None: self.openDocument(nHandle, tLine=0, doScroll=True) return True elif wrapAround: self.openDocument(fHandle, tLine=0, doScroll=True) return False return False def saveDocument(self): """Save the current documents. """ if not self.hasProject: logger.error("No project open") return False self.docEditor.saveText() return True def viewDocument(self, tHandle=None, tAnchor=None): """Load a document for viewing in the view panel. """ if not self.hasProject: logger.error("No project open") return False if tHandle is None: logger.debug("Viewing document, but no handle provided") if self.docEditor.hasFocus(): logger.verbose("Trying editor document") tHandle = self.docEditor.theHandle if tHandle is not None: self.saveDocument() else: logger.verbose("Trying selected document") tHandle = self.treeView.getSelectedHandle() if tHandle is None: logger.verbose("Trying last viewed document") tHandle = self.theProject.lastViewed if tHandle is None: logger.verbose("No document to view, giving up") return False # Make sure main tab is in Editor view self.tabWidget.setCurrentWidget(self.splitDocs) logger.debug("Viewing document with handle %s" % tHandle) if self.docViewer.loadText(tHandle): if not self.splitView.isVisible(): bPos = self.splitMain.sizes() self.splitView.setVisible(True) vPos = [0, 0] vPos[0] = int(bPos[1]/2) vPos[1] = bPos[1] - vPos[0] self.splitDocs.setSizes(vPos) self.viewMeta.setVisible(self.mainConf.showRefPanel) self.docViewer.navigateTo(tAnchor) return True def importDocument(self): """Import the text contained in an out-of-project text file, and insert the text into the currently open document. """ if not self.hasProject: logger.error("No project open") return False lastPath = self.mainConf.lastPath extFilter = [ "Text files (*.txt)", "Markdown files (*.md)", "novelWriter files (*.nwd)", "All files (*.*)", ] dlgOpt = QFileDialog.Options() dlgOpt |= QFileDialog.DontUseNativeDialog loadFile, _ = QFileDialog.getOpenFileName( self, "Import File", lastPath, options=dlgOpt, filter=";;".join(extFilter) ) if not loadFile: return False if loadFile.strip() == "": return False theText = None try: with open(loadFile, mode="rt", encoding="utf8") as inFile: theText = inFile.read() self.mainConf.setLastPath(loadFile) except Exception as e: self.makeAlert( ["Could not read file. The file must be an existing text file.", str(e)], nwAlert.ERROR ) return False if self.docEditor.theHandle is None: self.makeAlert( "Please open a document to import the text file into.", nwAlert.ERROR ) return False if not self.docEditor.isEmpty(): msgYes = self.askQuestion("Import Document", ( "Importing the file will overwrite the current content of the document. " "Do you want to proceed?" )) if not msgYes: return False self.docEditor.replaceText(theText) return True def mergeDocuments(self): """Merge multiple documents to one single new document. """ if not self.hasProject: logger.error("No project open") return False dlgMerge = GuiDocMerge(self, self.theProject) dlgMerge.exec_() return True def splitDocument(self): """Split a single document into multiple documents. """ if not self.hasProject: logger.error("No project open") return False dlgSplit = GuiDocSplit(self, self.theProject) dlgSplit.exec_() return True def passDocumentAction(self, theAction): """Pass on document action theAction to the document viewer if it has focus, otherwise pass it to the document editor. """ if self.docViewer.hasFocus(): self.docViewer.docAction(theAction) else: self.docEditor.docAction(theAction) return True ## # Tree Item Actions ## def openSelectedItem(self): """Open the selected documents. """ if not self.hasProject: logger.error("No project open") return False tHandle = self.treeView.getSelectedHandle() if tHandle is None: logger.warning("No item selected") return False logger.verbose("Opening item %s" % tHandle) nwItem = self.theProject.projTree[tHandle] if nwItem.itemType == nwItemType.FILE: logger.verbose("Requested item %s is a file" % tHandle) self.openDocument(tHandle, doScroll=False) else: logger.verbose("Requested item %s is not a file" % tHandle) return True def editItem(self, tHandle=None): """Open the edit item dialog. """ if not self.hasProject: logger.error("No project open") return False if tHandle is None: tHandle = self.treeView.getSelectedHandle() if tHandle is None: logger.warning("No item selected") return tItem = self.theProject.projTree[tHandle] if tItem is None: return if tItem.itemType not in nwLists.REG_TYPES: return logger.verbose("Requesting change to item %s" % tHandle) dlgProj = GuiItemEditor(self, self.theProject, tHandle) dlgProj.exec_() if dlgProj.result() == QDialog.Accepted: self.treeView.setTreeItemValues(tHandle) self.treeMeta.updateViewBox(tHandle) self.docEditor.updateDocInfo(tHandle) self.docViewer.updateDocInfo(tHandle) return def rebuildTree(self): """Rebuild the project tree. """ self._makeStatusIcons() self._makeImportIcons() self.treeView.clearTree() self.treeView.buildTree() return def rebuildIndex(self, beQuiet=False): """Rebuild the entire index. """ if not self.hasProject: logger.error("No project open") return False logger.debug("Rebuilding index ...") qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) tStart = time() self.treeView.saveTreeOrder() self.theIndex.clearIndex() theDoc = NWDoc(self.theProject, self) for nDone, tItem in enumerate(self.theProject.projTree): if tItem is not None: self.setStatus("Indexing: '%s'" % tItem.itemName) else: self.setStatus("Indexing: Unknown item") if tItem is not None and tItem.itemType == nwItemType.FILE: logger.verbose("Scanning: %s" % tItem.itemName) theText = theDoc.openDocument(tItem.itemHandle, showStatus=False) # Build tag index self.theIndex.scanText(tItem.itemHandle, theText) # Get Word Counts cC, wC, pC = self.theIndex.getCounts(tItem.itemHandle) tItem.setCharCount(cC) tItem.setWordCount(wC) tItem.setParaCount(pC) self.treeView.propagateCount(tItem.itemHandle, wC) self.treeView.projectWordCount() tEnd = time() self.setStatus("Indexing completed in %.1f ms" % ((tEnd - tStart)*1000.0)) self.docEditor.updateTagHighLighting() qApp.restoreOverrideCursor() if not beQuiet: self.makeAlert("The project index has been successfully rebuilt.", nwAlert.INFO) return True def rebuildOutline(self): """Force a rebuild of the Outline view. """ if not self.hasProject: logger.error("No project open") return False logger.verbose("Forcing a rebuild of the Project Outline") self.tabWidget.setCurrentWidget(self.splitOutline) self.projView.refreshTree(overRide=True) return True ## # Main Dialogs ## def selectProjectPath(self): """Select where to save project. """ dlgOpt = QFileDialog.Options() dlgOpt |= QFileDialog.ShowDirsOnly dlgOpt |= QFileDialog.DontUseNativeDialog projPath = QFileDialog.getExistingDirectory( self, "Save novelWriter Project", "", options=dlgOpt ) if projPath: return projPath return None def showProjectLoadDialog(self): """Opens the projects dialog for selecting either existing projects from a cache of recently opened projects, or provide a browse button for projects not yet cached. Selecting to create a new project is forwarded to the new project wizard. """ dlgProj = GuiProjectLoad(self) dlgProj.exec_() if dlgProj.result() == QDialog.Accepted: if dlgProj.openState == GuiProjectLoad.OPEN_STATE: self.openProject(dlgProj.openPath) elif dlgProj.openState == GuiProjectLoad.NEW_STATE: self.newProject() return True def showNewProjectDialog(self): """Open the wizard and assemble a project options dict. """ newProj = GuiProjectWizard(self) newProj.exec_() if newProj.result() == QDialog.Accepted: return self._assembleProjectWizardData(newProj) return None def showPreferencesDialog(self): """Open the preferences dialog. """ dlgConf = GuiPreferences(self, self.theProject) dlgConf.exec_() if dlgConf.result() == QDialog.Accepted: logger.debug("Applying new preferences") self.initMain() self.theTheme.updateTheme() self.saveDocument() self.docEditor.initEditor() self.docViewer.initViewer() self.treeView.initTree() self.projView.initOutline() self.projMeta.initDetails() return def showProjectSettingsDialog(self): """Open the project settings dialog. """ if not self.hasProject: logger.error("No project open") return dlgProj = GuiProjectSettings(self, self.theProject) dlgProj.exec_() if dlgProj.result() == QDialog.Accepted: logger.debug("Applying new project settings") self.docEditor.setDictionaries() self._updateWindowTitle(self.theProject.projName) return def showBuildProjectDialog(self): """Open the build project dialog. """ if not self.hasProject: logger.error("No project open") return dlgBuild = getGuiItem("GuiBuildNovel") if dlgBuild is None: dlgBuild = GuiBuildNovel(self, self.theProject) dlgBuild.setModal(False) dlgBuild.show() qApp.processEvents() dlgBuild.viewCachedDoc() return def showWritingStatsDialog(self): """Open the session log dialog. """ if not self.hasProject: logger.error("No project open") return dlgStats = getGuiItem("GuiWritingStats") if dlgStats is None: dlgStats = GuiWritingStats(self, self.theProject) dlgStats.setModal(False) dlgStats.show() qApp.processEvents() dlgStats.populateGUI() return def showAboutNWDialog(self, showNotes=False): """Show the about dialog for novelWriter. """ dlgAbout = GuiAbout(self) dlgAbout.setModal(True) dlgAbout.show() qApp.processEvents() dlgAbout.populateGUI() if showNotes: dlgAbout.showReleaseNotes() return def showAboutQtDialog(self): """Show the about dialog for Qt. """ msgBox = QMessageBox() msgBox.aboutQt(self, "About Qt") return def makeAlert(self, theMessage, theLevel=nwAlert.INFO): """Alert both the user and the logger at the same time. Message can be either a string or an array of strings. """ if isinstance(theMessage, list): popMsg = "<br>".join(theMessage) logMsg = theMessage else: popMsg = theMessage logMsg = [theMessage] # Write to Log if theLevel == nwAlert.INFO: for msgLine in logMsg: logger.info(msgLine) elif theLevel == nwAlert.WARN: for msgLine in logMsg: logger.warning(msgLine) elif theLevel == nwAlert.ERROR: for msgLine in logMsg: logger.error(msgLine) elif theLevel == nwAlert.BUG: for msgLine in logMsg: logger.error(msgLine) # Popup msgBox = QMessageBox() if theLevel == nwAlert.INFO: msgBox.information(self, "Information", popMsg) elif theLevel == nwAlert.WARN: msgBox.warning(self, "Warning", popMsg) elif theLevel == nwAlert.ERROR: msgBox.critical(self, "Error", popMsg) elif theLevel == nwAlert.BUG: popMsg += "<br>This is a bug!" msgBox.critical(self, "Internal Error", popMsg) return def askQuestion(self, theTitle, theQuestion): """Ask the user a Yes/No question. """ msgBox = QMessageBox() msgRes = msgBox.question(self, theTitle, theQuestion) return msgRes == QMessageBox.Yes def reportConfErr(self): """Checks if the Config module has any errors to report, and let the user know if this is the case. The Config module caches errors since it is initialised before the GUI itself. """ if self.mainConf.hasError: self.makeAlert(self.mainConf.getErrData(), nwAlert.ERROR) return True return False ## # Main Window Actions ## def closeMain(self): """Save everything, and close novelWriter. """ if self.hasProject: msgYes = self.askQuestion( "Exit", "Do you want to exit novelWriter?<br>Changes are saved automatically." ) if not msgYes: return False logger.info("Exiting novelWriter") if not self.isFocusMode: self.mainConf.setMainPanePos(self.splitMain.sizes()) self.mainConf.setDocPanePos(self.splitDocs.sizes()) self.mainConf.setOutlinePanePos(self.splitOutline.sizes()) if self.viewMeta.isVisible(): self.mainConf.setViewPanePos(self.splitView.sizes()) self.mainConf.setShowRefPanel(self.viewMeta.isVisible()) self.mainConf.setTreeColWidths(self.treeView.getColumnSizes()) if not self.mainConf.isFullScreen: self.mainConf.setWinSize(self.width(), self.height()) if self.hasProject: self.closeProject(True) self.mainConf.saveConfig() self.reportConfErr() self.mainMenu.closeHelp() qApp.quit() return True def setFocus(self, paneNo): """Switch focus to one of the three main GUI panes. """ if paneNo == 1: self.treeView.setFocus() elif paneNo == 2: self.docEditor.setFocus() elif paneNo == 3: self.docViewer.setFocus() return def closeDocEditor(self): """Close the document edit panel. This does not hide the editor. """ self.closeDocument() self.theProject.setLastEdited(None) return def closeDocViewer(self): """Close the document view panel. """ self.docViewer.clearViewer() self.theProject.setLastViewed(None) bPos = self.splitMain.sizes() self.splitView.setVisible(False) vPos = [bPos[1], 0] self.splitDocs.setSizes(vPos) return not self.splitView.isVisible() def toggleFocusMode(self): """Main GUI Focus Mode hides tree, view pane and optionally also statusbar and menu. """ if self.docEditor.theHandle is None: logger.error("No document open, so not activating Focus Mode") self.mainMenu.aFocusMode.setChecked(self.isFocusMode) return False self.isFocusMode = not self.isFocusMode self.mainMenu.aFocusMode.setChecked(self.isFocusMode) if self.isFocusMode: logger.debug("Activating Focus Mode") self.tabWidget.setCurrentWidget(self.splitDocs) else: logger.debug("Deactivating Focus Mode") isVisible = not self.isFocusMode self.treePane.setVisible(isVisible) self.statusBar.setVisible(isVisible) self.mainMenu.setVisible(isVisible) self.tabWidget.tabBar().setVisible(isVisible) hideDocFooter = self.isFocusMode and self.mainConf.hideFocusFooter self.docEditor.docFooter.setVisible(not hideDocFooter) if self.splitView.isVisible(): self.splitView.setVisible(False) elif self.docViewer.theHandle is not None: self.splitView.setVisible(True) return True def toggleFullScreenMode(self): """Main GUI full screen mode. The mode is tracked by the flag in config. This only tracks whether the window has been maximised using the internal commands, and may not be correct if the user uses the system window manager. Currently, Qt doesn't have access to the exact state of the window. """ self.setWindowState(self.windowState() ^ Qt.WindowFullScreen) winState = self.windowState() & Qt.WindowFullScreen == Qt.WindowFullScreen if winState: logger.debug("Activated full screen mode") else: logger.debug("Deactivated full screen mode") self.mainConf.isFullScreen = winState return ## # Internal Functions ## def _connectMenuActions(self): """Connect to the main window all menu actions that need to be available also when the main menu is hidden. """ # Project self.addAction(self.mainMenu.aSaveProject) self.addAction(self.mainMenu.aExitNW) # Document self.addAction(self.mainMenu.aSaveDoc) self.addAction(self.mainMenu.aFileDetails) # Edit self.addAction(self.mainMenu.aEditUndo) self.addAction(self.mainMenu.aEditRedo) self.addAction(self.mainMenu.aEditCut) self.addAction(self.mainMenu.aEditCopy) self.addAction(self.mainMenu.aEditPaste) self.addAction(self.mainMenu.aSelectAll) self.addAction(self.mainMenu.aSelectPar) # View self.addAction(self.mainMenu.aFocusMode) self.addAction(self.mainMenu.aFullScreen) # Insert self.addAction(self.mainMenu.aInsENDash) self.addAction(self.mainMenu.aInsEMDash) self.addAction(self.mainMenu.aInsEllipsis) self.addAction(self.mainMenu.aInsQuoteLS) self.addAction(self.mainMenu.aInsQuoteRS) self.addAction(self.mainMenu.aInsQuoteLD) self.addAction(self.mainMenu.aInsQuoteRD) self.addAction(self.mainMenu.aInsMSApos) self.addAction(self.mainMenu.aInsHardBreak) self.addAction(self.mainMenu.aInsNBSpace) self.addAction(self.mainMenu.aInsThinSpace) self.addAction(self.mainMenu.aInsThinNBSpace) for mAction, _ in self.mainMenu.mInsKWItems.values(): self.addAction(mAction) # Format self.addAction(self.mainMenu.aFmtEmph) self.addAction(self.mainMenu.aFmtStrong) self.addAction(self.mainMenu.aFmtStrike) self.addAction(self.mainMenu.aFmtDQuote) self.addAction(self.mainMenu.aFmtSQuote) self.addAction(self.mainMenu.aFmtHead1) self.addAction(self.mainMenu.aFmtHead2) self.addAction(self.mainMenu.aFmtHead3) self.addAction(self.mainMenu.aFmtHead4) self.addAction(self.mainMenu.aFmtComment) self.addAction(self.mainMenu.aFmtNoFormat) # Tools self.addAction(self.mainMenu.aSpellCheck) self.addAction(self.mainMenu.aReRunSpell) self.addAction(self.mainMenu.aPreferences) # Help if self.mainConf.hasHelp and self.mainConf.hasAssistant: self.addAction(self.mainMenu.aHelpLoc) self.addAction(self.mainMenu.aHelpWeb) return True def _updateWindowTitle(self, projName=None): """Set the window title and add the project's working title. """ winTitle = self.mainConf.appName if projName is not None: winTitle += " - %s" % projName self.setWindowTitle(winTitle) return True def _autoSaveProject(self): """Triggered by the auto-save project timer to save the project. """ doSave = self.hasProject doSave &= self.theProject.projChanged doSave &= self.theProject.projPath is not None if doSave: logger.debug("Autosaving project") self.saveProject(autoSave=True) return def _autoSaveDocument(self): """Triggered by the auto-save document timer to save the document. """ if self.hasProject and self.docEditor.docChanged: logger.debug("Autosaving document") self.saveDocument() return def _makeStatusIcons(self): """Generate all the item status icons based on project settings. """ self.statusIcons = {} iPx = self.mainConf.pxInt(32) for sLabel, sCol, _ in self.theProject.statusItems: theIcon = QPixmap(iPx, iPx) theIcon.fill(QColor(*sCol)) self.statusIcons[sLabel] = QIcon(theIcon) return def _makeImportIcons(self): """Generate all the item importance icons based on project settings. """ self.importIcons = {} iPx = self.mainConf.pxInt(32) for sLabel, sCol, _ in self.theProject.importItems: theIcon = QPixmap(iPx, iPx) theIcon.fill(QColor(*sCol)) self.importIcons[sLabel] = QIcon(theIcon) return def _assembleProjectWizardData(self, newProj): """Extract the user choices from the New Project Wizard and store them in a dictionary. """ projData = { "projName": newProj.field("projName"), "projTitle": newProj.field("projTitle"), "projAuthors": newProj.field("projAuthors"), "projPath": newProj.field("projPath"), "popSample": newProj.field("popSample"), "popMinimal": newProj.field("popMinimal"), "popCustom": newProj.field("popCustom"), "addRoots": [], "numChapters": 0, "numScenes": 0, "chFolders": False, } if newProj.field("popCustom"): addRoots = [] if newProj.field("addPlot"): addRoots.append(nwItemClass.PLOT) if newProj.field("addChar"): addRoots.append(nwItemClass.CHARACTER) if newProj.field("addWorld"): addRoots.append(nwItemClass.WORLD) if newProj.field("addTime"): addRoots.append(nwItemClass.TIMELINE) if newProj.field("addObject"): addRoots.append(nwItemClass.OBJECT) if newProj.field("addEntity"): addRoots.append(nwItemClass.ENTITY) projData["addRoots"] = addRoots projData["numChapters"] = newProj.field("numChapters") projData["numScenes"] = newProj.field("numScenes") projData["chFolders"] = newProj.field("chFolders") return projData ## # Events ## def closeEvent(self, theEvent): """Capture the closing event of the GUI and call the close function to handle all the close process steps. """ if self.closeMain(): theEvent.accept() else: theEvent.ignore() return ## # Signal Handlers ## def _treeSingleClick(self): """Single click on a project tree item just updates the details panel below the tree. """ sHandle = self.treeView.getSelectedHandle() if sHandle is not None: self.treeMeta.updateViewBox(sHandle) return def _treeDoubleClick(self, tItem, colNo): """The user double-clicked an item in the tree. If it is a file, we open it. Otherwise, we do nothing. """ tHandle = tItem.data(self.treeView.C_NAME, Qt.UserRole) logger.verbose("User double clicked tree item with handle %s" % tHandle) nwItem = self.theProject.projTree[tHandle] if nwItem is not None: if nwItem.itemType == nwItemType.FILE: logger.verbose("Requested item %s is a file" % tHandle) self.openDocument(tHandle, changeFocus=False, doScroll=False) else: logger.verbose("Requested item %s is a folder" % tHandle) return def _treeKeyPressReturn(self): """The user pressed return on an item in the tree. If it is a file, we open it. Otherwise, we do nothing. Pressing return does not change focus to the editor as double click does. """ tHandle = self.treeView.getSelectedHandle() logger.verbose("User pressed return on tree item with handle %s" % tHandle) nwItem = self.theProject.projTree[tHandle] if nwItem is not None: if nwItem.itemType == nwItemType.FILE: logger.verbose("Requested item %s is a file" % tHandle) self.openDocument(tHandle, changeFocus=False, doScroll=False) else: logger.verbose("Requested item %s is a folder" % tHandle) return def _keyPressEscape(self): """When the escape key is pressed somewhere in the main window, do the following, in order: """ if self.docEditor.docSearch.isVisible(): self.docEditor.closeSearch() elif self.isFocusMode: self.toggleFocusMode() return def _mainTabChanged(self, tabIndex): """Activated when the main window tab is changed. """ if tabIndex == self.idxTabEdit: logger.verbose("Editor tab activated") elif tabIndex == self.idxTabProj: logger.verbose("Project outline tab activated") if self.hasProject: self.projView.refreshTree() return
class UploadWindowUI(object): title = "DERIVA File Uploader" def __init__(self, MainWin): # Main Window MainWin.setObjectName("UploadWindow") MainWin.setWindowTitle(MainWin.tr(self.title)) MainWin.resize(1024, 768) self.centralWidget = QWidget(MainWin) self.centralWidget.setObjectName("centralWidget") MainWin.setCentralWidget(self.centralWidget) self.verticalLayout = QVBoxLayout(self.centralWidget) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(6) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QHBoxLayout() self.pathLabel = QLabel("Directory:") self.horizontalLayout.addWidget(self.pathLabel) self.pathTextBox = QLineEdit() self.pathTextBox.setReadOnly(True) self.horizontalLayout.addWidget(self.pathTextBox) self.browseButton = QPushButton("Browse", self.centralWidget) self.browseButton.clicked.connect(MainWin.on_actionBrowse_triggered) self.horizontalLayout.addWidget(self.browseButton) self.verticalLayout.addLayout(self.horizontalLayout) # Splitter for Upload list/Log self.splitter = QSplitter(Qt.Vertical) # Table View (Upload list) self.uploadList = TableWidget(self.centralWidget) self.uploadList.setObjectName("uploadList") self.uploadList.setStyleSheet( """ QTableWidget { border: 2px solid grey; border-radius: 5px; } """) self.uploadList.setEditTriggers(QAbstractItemView.NoEditTriggers) # use NoEditTriggers to disable editing self.uploadList.setAlternatingRowColors(True) self.uploadList.setSelectionBehavior(QAbstractItemView.SelectRows) self.uploadList.setSelectionMode(QAbstractItemView.NoSelection) self.uploadList.verticalHeader().setDefaultSectionSize(18) # tighten up the row size self.uploadList.horizontalHeader().setStretchLastSection(True) self.uploadList.setSortingEnabled(True) # allow sorting self.splitter.addWidget(self.uploadList) # Log Widget self.logTextBrowser = QPlainTextEditLogger(self.centralWidget) self.logTextBrowser.widget.setObjectName("logTextBrowser") self.logTextBrowser.widget.setStyleSheet( """ QPlainTextEdit { border: 2px solid grey; border-radius: 5px; background-color: lightgray; } """) self.splitter.addWidget(self.logTextBrowser.widget) # add splitter self.splitter.setSizes([400, 200]) self.verticalLayout.addWidget(self.splitter) # Actions # Browse self.actionBrowse = QAction(MainWin) self.actionBrowse.setObjectName("actionBrowse") self.actionBrowse.setText(MainWin.tr("Browse")) self.actionBrowse.setToolTip(MainWin.tr("Set the upload directory")) self.actionBrowse.setShortcut(MainWin.tr("Ctrl+B")) # Upload self.actionUpload = QAction(MainWin) self.actionUpload.setObjectName("actionUpload") self.actionUpload.setText(MainWin.tr("Upload")) self.actionUpload.setToolTip(MainWin.tr("Upload files")) self.actionUpload.setShortcut(MainWin.tr("Ctrl+L")) self.actionUpload.setEnabled(False) # Rescan self.actionRescan = QAction(MainWin) self.actionRescan.setObjectName("actionRescan") self.actionRescan.setText(MainWin.tr("Rescan")) self.actionRescan.setToolTip(MainWin.tr("Rescan the upload directory")) self.actionRescan.setShortcut(MainWin.tr("Ctrl+R")) self.actionRescan.setEnabled(False) # Cancel self.actionCancel = QAction(MainWin) self.actionCancel.setObjectName("actionCancel") self.actionCancel.setText(MainWin.tr("Cancel")) self.actionCancel.setToolTip(MainWin.tr("Cancel any upload(s) in-progress")) self.actionCancel.setShortcut(MainWin.tr("Ctrl+C")) # Options self.actionOptions = QAction(MainWin) self.actionOptions.setObjectName("actionOptions") self.actionOptions.setText(MainWin.tr("Options")) self.actionOptions.setToolTip(MainWin.tr("Configuration Options")) self.actionOptions.setShortcut(MainWin.tr("Ctrl+P")) # Login self.actionLogin = QAction(MainWin) self.actionLogin.setObjectName("actionLogin") self.actionLogin.setText(MainWin.tr("Login")) self.actionLogin.setToolTip(MainWin.tr("Login to the server")) self.actionLogin.setShortcut(MainWin.tr("Ctrl+G")) self.actionLogin.setEnabled(False) # Logout self.actionLogout = QAction(MainWin) self.actionLogout.setObjectName("actionLogout") self.actionLogout.setText(MainWin.tr("Logout")) self.actionLogout.setToolTip(MainWin.tr("Logout of the server")) self.actionLogout.setShortcut(MainWin.tr("Ctrl+O")) self.actionLogout.setEnabled(False) # Exit self.actionExit = QAction(MainWin) self.actionExit.setObjectName("actionExit") self.actionExit.setText(MainWin.tr("Exit")) self.actionExit.setToolTip(MainWin.tr("Exit the application")) self.actionExit.setShortcut(MainWin.tr("Ctrl+Z")) # Help self.actionHelp = QAction(MainWin) self.actionHelp.setObjectName("actionHelp") self.actionHelp.setText(MainWin.tr("Help")) self.actionHelp.setToolTip(MainWin.tr("Help")) self.actionHelp.setShortcut(MainWin.tr("Ctrl+H")) # Menu Bar """ self.menuBar = QMenuBar(MainWin) self.menuBar.setObjectName("menuBar") MainWin.setMenuBar(self.menuBar) self.menuBar.setStyleSheet( "QMenuBar{font-family: Arial;font-style: normal;font-size: 10pt;font-weight: bold;};") """ # Tool Bar self.mainToolBar = QToolBar(MainWin) self.mainToolBar.setObjectName("mainToolBar") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.mainToolBar.setContextMenuPolicy(Qt.PreventContextMenu) MainWin.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # Upload self.mainToolBar.addAction(self.actionUpload) self.actionUpload.setIcon(qApp.style().standardIcon(QStyle.SP_FileDialogToParent)) # Rescan self.mainToolBar.addAction(self.actionRescan) self.actionRescan.setIcon(qApp.style().standardIcon(QStyle.SP_BrowserReload)) # Cancel self.mainToolBar.addAction(self.actionCancel) self.actionCancel.setIcon(qApp.style().standardIcon(QStyle.SP_BrowserStop)) self.actionCancel.setEnabled(False) # Options self.mainToolBar.addAction(self.actionOptions) self.actionOptions.setIcon(qApp.style().standardIcon(QStyle.SP_FileDialogDetailedView)) # this spacer right justifies everything that comes after it spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.mainToolBar.addWidget(spacer) # Login self.mainToolBar.addAction(self.actionLogin) self.actionLogin.setIcon(qApp.style().standardIcon(QStyle.SP_DialogApplyButton)) # Logout self.mainToolBar.addAction(self.actionLogout) self.actionLogout.setIcon(qApp.style().standardIcon(QStyle.SP_DialogOkButton)) # Help #self.mainToolBar.addAction(self.actionHelp) self.actionHelp.setIcon(qApp.style().standardIcon(QStyle.SP_MessageBoxQuestion)) # Exit self.mainToolBar.addAction(self.actionExit) self.actionExit.setIcon(qApp.style().standardIcon(QStyle.SP_DialogCancelButton)) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # configure logging self.logTextBrowser.widget.log_update_signal.connect(MainWin.updateLog) self.logTextBrowser.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) logging.getLogger().addHandler(self.logTextBrowser) # finalize UI setup QMetaObject.connectSlotsByName(MainWin)
class App(QWidget): def __init__(self): super().__init__() self.title = 'ARXML Explorer' self.left = 10 self.top = 10 self.width = 800 self.height = 700 self.model_cache = NamespaceCache() self.deploy_cache = NamespaceCache() self.cache = NodeCache() self.views = [] self.initUI() self.help = arxmlHelp() path = './models/demo7' files = [f for f in os.listdir(path) if os.path.isfile(path + '/' + f)] for f in files: if f.endswith('.arxml'): self.parseXML(path + '/' + f) def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.model_tree = ModelTreeView(self) self.detail = MethodArgumentsTreeView("Details", self) self.errorlist = MethodErrorListWidget() self.combo = MethodArgumentEditor() #self.tabs = QTabWidget() self.plaintext_xml = QPlainTextEdit() #self.plaintext_xml.resize(400,150) self.plaintext_help = QPlainTextEdit() #self.plaintext_help.resize(400,150) self.splitter1 = QSplitter(Qt.Vertical) self.splitter1.addWidget(self.model_tree.groupDataTypes) self.splitter1.addWidget(self.detail.groupDataTypes) self.splitter2 = QSplitter(Qt.Horizontal) self.splitter2.addWidget(self.plaintext_xml) self.splitter2.addWidget(self.plaintext_help) self.splitter1.addWidget(self.splitter2) self.splitter2.setStretchFactor(0, 1) self.splitter2.setStretchFactor(1, 0) #self.splitter2.setSizes([0, 1]) #self.splitter1.addWidget(self.tabs) mainLayout = QVBoxLayout() #self.tabs.addTab(self.plaintext_xml,"XML") #self.tabs.addTab(self.plaintext_help,"Help") #self.tabs.addTab(self.errorlist.groupDataTypes, "Possible Errors") self.model_tree.treeView.selectionModel().selectionChanged.connect( self.on_model_tree_selection_changed) #self.detail.treeView.selectionModel().selectionChanged.connect(self.on_detail_tree_selection_changed) self.setLayout(mainLayout) mainLayout.addWidget(self.splitter1) self.show() """ self.view_error = self.add_view(ViewError(self.model_tree.root_node_model, self.model_cache)) self.view_datatype = self.add_view(ViewDataType(self.model_tree.root_node_model)) self.view_method = self.add_view(ViewMethod(self.model_tree.root_node_model, self.model_cache)) self.view_event = self.add_view(ViewEvent(self.model_tree.root_node_model, self.model_cache)) self.view_field = self.add_view(ViewField(self.model_tree.root_node_model, self.model_cache)) self.view_deployment = self.add_view(ViewDeployment(self.model_tree.root_node_deployment, self.deploy_cache)) """ self.view_executable = self.add_view( ViewExecutable(self.model_tree.root_node_application_design, self.cache)) self.view_ethernet = self.add_view( ViewEthernet(self.model_tree.root_node_communication_connector, self.cache)) self.view_machine = self.add_view( ViewMachine(self.model_tree.root_node_machine_manifest, self.cache)) self.view_adaptive_sw_component = self.add_view( ViewAdaptiveSwComponent( self.model_tree.root_node_application_design, self.cache)) self.view_application = self.add_view( ViewApplication(self.model_tree.root_node_application_design, self.cache)) self.view_mode_declaration = self.add_view( ViewModeDeclaration(self.model_tree.root_node_machine_manifest, self.cache)) self.view_startup_config = self.add_view( ViewStartupConfig(self.model_tree.root_node_startup_config_set, self.cache)) self.view_process = self.add_view( ViewProcess(self.model_tree.root_node_execution_manifest, self.cache)) def get_cache_for(self, name): for view in self.views: if view.xml_tag_name == name: return view.cache return None def add_view(self, view): self.views.append(view) return view def handle_selected_main_item(self, index): self.show_help_row(index) xml_node = index.data(Qt.UserRole + 1) self.show_help(index.data(Qt.DisplayRole)) self.detail.clear() if xml_node != None: self.show_xml(xml_node) for item in self.views: if item.show_detail(self.detail.model, xml_node): self.detail.treeView.expandAll() return return self.plaintext_xml.setPlainText('') pass def on_model_tree_selection_changed(self, selected, deselected): a = self.model_tree.treeView.selectedIndexes()[0] self.handle_selected_main_item(a) def show_xml(self, node): str = node.toprettyxml(indent=' ', newl='') self.plaintext_xml.setPlainText(str) def show_help_row(self, index): self.show_help(index.data(RoleHelp)) self.show_xml(index.data(RoleXmlNode)) pass def show_help(self, item): self.set_help_text(self.help.get(item)) def set_help_text(self, str): self.plaintext_help.setPlainText(str) def parseXML(self, file): self.xmldoc = minidom.parse(file) for item in self.views: item.parse(self.xmldoc, file)
def __init__(self): """Initialize Tab with layout and behavior.""" super(Tab, self).__init__() # regex pattern for SQL query block comments self.block_comment_re = re.compile( r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?', re.DOTALL | re.MULTILINE) main_layout = QVBoxLayout(self) # define gdb props self.gdb = None self.gdb_items = None self.gdb_columns_names = None self.gdb_schemas = None # connected geodatabase path toolbar self.connected_gdb_path_label = QLabel('') self.connected_gdb_path_label.setTextInteractionFlags( Qt.TextSelectableByMouse) self.connected_gdb_path_label.setToolTip( 'Connected geodatabase that queries will be run against') self.connected_gdb_path_label.setText(not_connected_to_gdb_message) self.browse_to_gdb = QPushButton('Browse') self.browse_to_gdb.setShortcut(QKeySequence('Ctrl+B')) self.browse_to_gdb.clicked.connect( lambda evt, arg=True: self.connect_to_geodatabase( evt, triggered_with_browse=True)) self.gdb_sql_dialect_combobox = QComboBox() for dialect in sql_dialects_names: self.gdb_sql_dialect_combobox.addItem(dialect) self.gdb_browse_toolbar = QToolBar() self.gdb_browse_toolbar.setMaximumHeight(50) self.gdb_browse_toolbar.addWidget(self.browse_to_gdb) self.gdb_browse_toolbar.addWidget(self.connected_gdb_path_label) self.gdb_browse_toolbar.addSeparator() self.gdb_browse_toolbar.addWidget(self.gdb_sql_dialect_combobox) # table with results self.table = ResultTable() # execute SQL query self.execute = QAction('Execute', self) self.execute.setShortcuts( [QKeySequence('F5'), QKeySequence('Ctrl+Return')]) self.execute.triggered.connect(self.run_query) self.addAction(self.execute) # enter a SQL query self.query = TextEditor() self.query.setPlainText('') font = self.query.font() font.setFamily('Consolas') font.setStyleHint(QFont.Monospace) # TODO: add line numbers to the text editor font.setPointSize(14) self.query.setFont(font) self.query.setTabStopWidth(20) self.highlighter = Highlighter(self.query.document()) # TODO select block of text - Ctrl+/ and they become comments self.completer = Completer() self.query.set_completer(self.completer.completer) # errors panel to show if query fails to execute properly self.errors_panel = QPlainTextEdit() font = self.query.font() font.setPointSize(12) self.errors_panel.setStyleSheet('color:red') self.errors_panel.setFont(font) self.errors_panel.hide() # splitter between the toolbar, query window, and the result set table splitter = QSplitter(Qt.Vertical) splitter.addWidget(self.gdb_browse_toolbar) splitter.addWidget(self.query) splitter.addWidget(self.table) splitter.addWidget(self.errors_panel) # add the settings after the widget have been added splitter.setCollapsible(0, True) splitter.setCollapsible(1, False) splitter.setCollapsible(2, False) splitter.setCollapsible(3, False) splitter.setStretchFactor(0, 3) splitter.setStretchFactor(1, 7) splitter.setSizes((100, 200, 300)) self.table.hide() # TOC self.toc = QTreeWidget() self.toc.setHeaderHidden(True) # second splitter between the TOC to the left and the query/table to the # right toc_splitter = QSplitter(Qt.Horizontal) toc_splitter.addWidget(self.toc) toc_splitter.addWidget(splitter) toc_splitter.setCollapsible(0, True) toc_splitter.setSizes((200, 800)) # set the TOC vs data panel main_layout.addWidget(toc_splitter) margins = QMargins() margins.setBottom(10) margins.setLeft(10) margins.setRight(10) margins.setTop(10) main_layout.setContentsMargins(margins) self.setLayout(main_layout) QApplication.setStyle(QStyleFactory.create('Cleanlooks')) self.show() return
def create_top_group_box(self): top_splitter = QSplitter() top_splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # 좌 top_left_group_box = QGroupBox("레이드 함수 목록") top_left_group_box.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) names = list(map(lambda i: i.get_name(), self._methods)) model = QStringListModel(names) view = QListView() view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) view.setModel(model) view.clicked.connect(self.on_show_method) add_function = QPushButton("함수 추가") layout = QVBoxLayout() layout.addWidget(add_function) layout.addWidget(view) top_left_group_box.setLayout(layout) # 우 top_right_group_box = QGroupBox("레이드 함수") # 우 - 텍스트 tab_method_body = QTabWidget() tab_block = QWidget() tab_plain = QWidget() self._edit_method_body_plain = QTextEdit() tab_hbox_plain = QHBoxLayout() tab_hbox_plain.setContentsMargins(5, 5, 5, 5) tab_hbox_plain.addWidget(self._edit_method_body_plain) self._edit_method_body_block = PyJavaCode() self._edit_method_body_block.set_plain_view( self._edit_method_body_plain) tab_hbox_block = QHBoxLayout() tab_hbox_block.setContentsMargins(5, 5, 5, 5) tab_hbox_block.addWidget(self._edit_method_body_block) tab_block.setLayout(tab_hbox_block) tab_plain.setLayout(tab_hbox_plain) tab_method_body.addTab(tab_block, "&Block") tab_method_body.addTab(tab_plain, "&Plain") # 배치 label_method_name = QLabel("name") self._edit_method_name = QLineEdit() label_method_body = QLabel("body") self._edit_method_body = tab_method_body # layout = QVBoxLayout() layout.addWidget(label_method_name) layout.addWidget(self._edit_method_name) layout.addWidget(label_method_body) layout.addWidget(self._edit_method_body) top_right_group_box.setLayout(layout) # test # top_left_group_box.setStyleSheet("color: blue;" # "background-color: #87CEFA;" # "border-style: dashed;" # "border-width: 3px;" # "border-color: #1E90FF") # # top_right_group_box.setStyleSheet("color: blue;" # "background-color: #87CEFA;" # "border-style: dashed;" # "border-width: 3px;" # "border-color: #1E90FF") # spliter top_splitter.addWidget(top_left_group_box) top_splitter.addWidget(top_right_group_box) return top_splitter
def initUI(self): # TODO: initCanvas()? self.canvas = PlotCanvas(self) self.canvas.setFocusPolicy(Qt.ClickFocus) self.canvas.setFocus() # self.canvas.mpl_connect('button_press_event', self.on_press) # self.canvas.mpl_connect('button_release_event', self.on_release) # self.canvas.mpl_connect('motion_notify_event', self.on_motion) # self.canvas.mpl_connect('scroll_event', self.on_scroll) # self.canvas.mpl_connect('key_release_event', self.on_key_release) menuBar = self.menuBar() openMenu = menuBar.addMenu('Open') showMenu = menuBar.addMenu('Show') allAct = QAction("All", self) allAct.setCheckable(True) allAct.setChecked(True) allAct.triggered.connect(lambda: self.showPts(0)) missAct = QAction("Miss Clf", self) missAct.setCheckable(True) missAct.setChecked(False) missAct.triggered.connect(lambda: self.showPts(1)) noneAct = QAction("None", self) noneAct.setCheckable(True) noneAct.setChecked(False) noneAct.triggered.connect(lambda: self.showPts(2)) showMenu.addAction(allAct) showMenu.addAction(missAct) showMenu.addAction(noneAct) showMenuGroup = QActionGroup(self) showMenuGroup.addAction(allAct) showMenuGroup.addAction(missAct) showMenuGroup.addAction(noneAct) showMenuGroup.setExclusive(True) showMenu.addSeparator() # highlight action hlAct = QAction('Highlight Neighbors', self) hlAct.setShortcut("Ctrl+H") hlAct.setCheckable(True) hlAct.setChecked(False) hlAct.triggered.connect(self.setHLNeighbors) showMenu.addAction(hlAct) freezeAct = QAction('Freeze', self) freezeAct.setShortcut("Ctrl+F") freezeAct.setCheckable(True) freezeAct.setChecked(False) freezeAct.triggered.connect(self.freeze_act) showMenu.addAction(freezeAct) boundaryMapAct = QAction('Show boundary map') boundaryMapAct.setShortcut("Ctrl+B") boundaryMapAct.setCheckable(True) boundaryMapAct.setChecked(True) boundaryMapAct.triggered.connect(lambda: self.show_map(self.BMAP)) showMenu.addAction(boundaryMapAct) distMapAct = QAction('Show dist map', self) distMapAct.setShortcut("Ctrl+D") distMapAct.setCheckable(True) distMapAct.setChecked(False) distMapAct.triggered.connect(lambda: self.show_map(self.DMAP2D)) showMenu.addAction(distMapAct) distMapNDAct = QAction('Show dist map nD', self) distMapNDAct.setCheckable(True) distMapNDAct.setChecked(False) distMapNDAct.triggered.connect(lambda: self.show_map(self.DMAPND)) showMenu.addAction(distMapNDAct) distMapND2Act = QAction('Show dist map nD2', self) distMapND2Act.setCheckable(True) distMapND2Act.setChecked(False) distMapND2Act.triggered.connect(lambda: self.show_map(self.DMAPND2)) showMenu.addAction(distMapND2Act) distMapND3Act = QAction('Show dist map nD3', self) distMapND3Act.setCheckable(True) distMapND3Act.setChecked(False) distMapND3Act.triggered.connect(lambda: self.show_map(self.DMAPND3)) showMenu.addAction(distMapND3Act) distMenuGroup = QActionGroup(self) distMenuGroup.addAction(boundaryMapAct) distMenuGroup.addAction(distMapAct) distMenuGroup.addAction(distMapNDAct) distMenuGroup.addAction(distMapND2Act) distMenuGroup.addAction(distMapND3Act) openProjAct = QAction("Projection", self) openProjAct.setShortcut("Ctrl+O") openProjAct.triggered.connect(self.openProjection) saveAct = QAction('Save', self) saveAct.setShortcut("Ctrl+S") saveAct.triggered.connect(self.save_new_samples) openMenu.addAction(openProjAct) openMenu.addAction(saveAct) self.errUI = ErrUI() splitter = QSplitter(self) splitter.addWidget(self.errUI) splitter.addWidget(self.canvas) splitter.addWidget(self.newsamplesUI) self.setCentralWidget(splitter)
def make_splitter(orientation, *widgets): spl = QSplitter(orientation, self) for w in widgets: spl.addWidget(w) return spl
def __init__(self, parent=None): super(Main, self).__init__(parent) self.dirList = QListWidget() self.fileList = QListWidget() self.setDirList() self.fileName = "" self.dirName = self.dirList.item(0).text() self.path = "/" + self.dirName + "/" self.dirList.itemSelectionChanged.connect(self.selectDir) self.fileList.itemSelectionChanged.connect(self.selectFile) latLabel = QLabel("lat(緯度): ") self.latEdit = QLineEdit() lonLabel = QLabel("lon(経度): ") self.lonEdit = QLineEdit() editLayout = QGridLayout() editLayout.addWidget(latLabel, 0, 0) editLayout.addWidget(self.latEdit, 0, 1) editLayout.addWidget(lonLabel, 1, 0) editLayout.addWidget(self.lonEdit, 1, 1) startButton = QPushButton("Start") startButton.clicked.connect(self.clickedStart) exitButton = QPushButton("Exit") exitButton.clicked.connect(self.clickedExit) buttonLayout = QHBoxLayout() buttonLayout.addWidget(startButton) buttonLayout.addWidget(exitButton) inputLayout = QVBoxLayout() inputLayout.addWidget(self.dirList) inputLayout.addLayout(editLayout) inputLayout.addLayout(buttonLayout) inputWidget = QWidget() inputWidget.setLayout(inputLayout) self.canvas = QLabel(u" ここに地形図が表示されます ") self.canvas.setScaledContents(True) saveButton = QPushButton("Save Figure") saveButton.clicked.connect(self.clickedSave) figureLayout = QVBoxLayout() figureLayout.addWidget(self.canvas) figureLayout.addWidget(saveButton) figureWidget = QWidget() figureWidget.setLayout(figureLayout) splitter = QSplitter(Qt.Horizontal) splitter.addWidget(inputWidget) splitter.addWidget(figureWidget) splitter.setStretchFactor(1, 1) entireLayout = QHBoxLayout() entireLayout.addWidget(splitter) entireLayout.addWidget(self.fileList) self.setLayout(entireLayout)
class MainWindow(QMainWindow, mainwindow.Ui_MainWindow): waterfall_data_signal = QtCore.pyqtSignal() def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) self.setup_window() def setup_window(self): #Dialogs self.Waterfall_Plot = WaterfallPlotter(self) self.Waterfall = Waterfall(self) self.Waterfall_Widget = QWidget() self.Waterfall_Box = QVBoxLayout() self.Waterfall_Splitter = QSplitter(QtCore.Qt.Horizontal) self.Waterfall_Splitter.addWidget(self.Waterfall) self.Waterfall_Splitter.addWidget(self.Waterfall_Plot) self.Waterfall_Box.addWidget(self.Waterfall_Splitter) self.Waterfall_Widget.setLayout(self.Waterfall_Box) self.Spider_Widget = QWidget() self.Spider_Box = QVBoxLayout() self.Spider_Splitter = QSplitter(QtCore.Qt.Horizontal) self.Spider_Plot = SpiderPlotter(self) self.Spider = Spider(self) self.Spider_Splitter.addWidget(self.Spider) self.Spider_Splitter.addWidget(self.Spider_Plot) self.Spider_Box.addWidget(self.Spider_Splitter) self.Spider_Widget.setLayout(self.Spider_Box) self.Swimmer_Widget = QWidget() self.Swimmer_Box = QVBoxLayout() self.Swimmer_Splitter = QSplitter(QtCore.Qt.Horizontal) self.Swimmer_Plot = SwimmerPlotter(self) self.Swimmer = Swimmer(self) self.Swimmer_Splitter.addWidget(self.Swimmer) self.Swimmer_Splitter.addWidget(self.Swimmer_Plot) self.Swimmer_Box.addWidget(self.Swimmer_Splitter) self.Swimmer_Widget.setLayout(self.Swimmer_Box) self.stackedWidget.addWidget(self.Waterfall_Widget) #0 self.stackedWidget.addWidget(self.Spider_Widget) #1 self.stackedWidget.addWidget(self.Swimmer_Widget) #2 self.stackedWidget.hide() #Set up toolBar self.toolBar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) importAction = QAction( QtGui.QIcon(os.path.join(image_dir, 'images\Download.png')), 'Import date template', self) importAction.triggered.connect(self.import_data) importAction.setIconText("Import") self.toolBar.addAction(importAction) self.toolBar.addSeparator() dumpAction = QAction( QtGui.QIcon(os.path.join(image_dir, 'images\Rubbish.png')), 'Import date template', self) #dumpAction.triggered.connect(self.dump_data) dumpAction.setIconText("Dump data") self.toolBar.addAction(dumpAction) self.toolBar.addSeparator() self.waterfallAction = QAction( QtGui.QIcon(os.path.join(image_dir, r'images\waterfall.png')), 'Waterfall plot', self) self.waterfallAction.triggered.connect(self.launch_waterfall) self.waterfallAction.setIconText("Waterfall") self.waterfallAction.setEnabled(False) self.toolBar.addAction(self.waterfallAction) self.spiderAction = QAction( QtGui.QIcon(os.path.join(image_dir, r'images\spider.png')), 'Spider plot', self) self.spiderAction.triggered.connect(self.launch_spider) self.spiderAction.setIconText("Spider") self.spiderAction.setEnabled(False) self.toolBar.addAction(self.spiderAction) self.swimmerAction = QAction( QtGui.QIcon(os.path.join(image_dir, r'images\swimmer_stack.png')), 'Swimmer plot', self) self.swimmerAction.triggered.connect(self.launch_spider) self.swimmerAction.setIconText("Swimmer") self.swimmerAction.setEnabled(False) self.toolBar.addAction(self.swimmerAction) self.toolBar.addSeparator() #Signal interconnections self.waterfall_data_signal.connect( self.Waterfall.on_waterfall_data_signal) self.waterfall_data_signal.connect( self.Waterfall_Plot.on_waterfall_data_signal) self.Waterfall.general_settings_signal.connect( self.Waterfall_Plot.on_general_settings_signal) #Launch functions def launch_waterfall(self): self.stackedWidget.setCurrentIndex(0) self.stackedWidget.show() def launch_spider(self): self.stackedWidget.setCurrentIndex(1) self.stackedWidget.show() def launch_swimmer(self): self.stackedWidget.setCurrentIndex(2) self.stackedWidget.show() def import_data(self): self.file_path = QFileDialog.getOpenFileName(self, "Select Data Template", "C:\\")[0] if self.file_path == '': pass else: self.waterfall_data = import_plot_data(self.file_path) self.waterfall_data_signal.emit(self.waterfall_data) self.waterfallAction.setEnabled(True) self.spiderAction.setEnabled(True) self.swimmerAction.setEnabled(True)
def __init__(self): super().__init__() self.F = MyFigure(width=1, height=1, dpi=100) self.F.plotsin() # 开始: wlayout = QtWidgets.QHBoxLayout() # 全局布局(1个):水平 hlayout = QHBoxLayout() # 局部布局(4个):水平、竖直、网格、表单 vlayout = QGridLayout() vlayout.setDefaultPositioning(100, 100) vlayout.setAlignment(Qt.AlignTop) vlayout.setVerticalSpacing(30) glayout = QGridLayout() glayout.setAlignment(Qt.AlignLeft) glayout.setRowStretch glayout.setHorizontalSpacing(80) flayout = QFormLayout() baud = [ '12800', '115200', '230400', '256000', '460800', '921600', '1382400' ] serials = [ 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'COM10', 'COM11' ] self.fasong_btn1 = QPushButton('发送', self) self.fasong_btn2 = QPushButton('发送', self) self.fasong_btn3 = QPushButton('发送', self) self.receive_btn = QPushButton("接收", self) self.receive_btn.setFixedSize(80, 60) self.com_box = QComboBox() self.com_box.addItems(baud) #self.bel = QLabel("串口选择") self.c_baud = QLabel("波特率") self.line_text1 = QLineEdit() self.line_text2 = QLineEdit() self.line_text3 = QLineEdit() # self.hwg_pic = QLabel(self) # 准备四个部件 # self.hwg_pic.setPixmap(QPixmap("Icon/meidui.jpg")) # self.hwg_pic.setScaledContents(True) # hlayout.addWidget(self.hwg_pic) hlayout.addWidget(self.F) vlayout.setDefaultPositioning(10, 10) #vlayout.addWidget(self.bel,0,0) vlayout.addWidget(self.receive_btn, 0, 0) vlayout.addWidget(self.com_box, 1, 1) vlayout.addWidget(self.c_baud, 1, 0) glayout.addWidget(self.line_text1, 0, 0) glayout.addWidget(self.fasong_btn1, 0, 1) glayout.addWidget(self.line_text2, 1, 0) glayout.addWidget(self.fasong_btn2, 1, 1) glayout.addWidget(self.line_text3, 2, 0) glayout.addWidget(self.fasong_btn3, 2, 1) #菜单和工具栏 tools_bar = QMainWindow(self) menubar = tools_bar.menuBar() #menubar = tools_bar.menuBar() hwg = QFrame(self) hwg.setFrameShape(QFrame.StyledPanel) hwg.setMinimumSize(100, 100) vwg = QFrame(self) vwg.setFrameShape(QFrame.StyledPanel) vwg.setMinimumSize(100, 100) gwg = QFrame(self) gwg.setFrameShape(QFrame.StyledPanel) gwg.setMinimumSize(100, 100) hwg.setLayout(hlayout) vwg.setLayout(vlayout) gwg.setLayout(glayout) splitter1 = QSplitter(Qt.Horizontal) splitter1.addWidget(hwg) splitter1.addWidget(vwg) splitter1.setSizes([600, 140]) splitter2 = QSplitter(Qt.Vertical) splitter2.addWidget(splitter1) splitter2.addWidget(gwg) splitter2.setSizes([600, 140]) wlayout.addWidget(splitter2) self.setLayout(wlayout) # 窗体本尊设置全局布局 self.setGeometry(300, 300, 800, 800) self.setWindowTitle('吴洪岩') self.setWindowIcon(QIcon('Icon/meidui.JPG')) self.show()
def initUI(self): self.statusBar().showMessage('Ready') self.left_action = QAction('上一个', self) self.left_action.setShortcut(QKeySequence.MoveToPreviousChar) self.left_action.triggered.connect(self.analyze_last_one_image) self.right_action = QAction('下一个', self) self.right_action.setShortcut(QKeySequence.MoveToNextChar) self.right_action.triggered.connect(self.analyze_next_one_image) self.rename_image_action = QAction('保存e2e文件名', self) self.rename_image_action.setShortcut(QKeySequence.MoveToPreviousLine) self.rename_image_action.triggered.connect( self.rename_current_image_with_info) self.statusBar() menubar = self.menuBar() fileMenu = menubar.addMenu('&Function') fileMenu.addAction(self.left_action) fileMenu.addAction(self.right_action) fileMenu.addAction(self.rename_image_action) self.image_window_view = HyperLprImageView() table_widget_header_labels = [ "文件名", "分割识别", "置信度", "颜色", "E2E识别", "E2E置信度" ] self.hyperlpr_tableview = QTableWidget(0, len(table_widget_header_labels)) self.hyperlpr_tableview.setHorizontalHeaderLabels( table_widget_header_labels) self.hyperlpr_tableview.setSelectionBehavior( QAbstractItemView.SelectItems) self.hyperlpr_tableview.setSelectionMode( QAbstractItemView.SingleSelection) self.hyperlpr_tableview.setEditTriggers( QAbstractItemView.NoEditTriggers) self.hyperlpr_tableview.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) self.hyperlpr_tableview.setEditTriggers( QAbstractItemView.NoEditTriggers) self.hyperlpr_tableview.cellClicked.connect( self.recognize_one_license_plate) self.left_button = QPushButton("<") self.left_button.setFixedWidth(60) self.right_button = QPushButton(">") self.right_button.setFixedWidth(60) self.left_button.setEnabled(False) self.right_button.setEnabled(False) self.left_button.clicked.connect(self.analyze_last_one_image) self.right_button.clicked.connect(self.analyze_next_one_image) left_right_layout = QHBoxLayout() left_right_layout.addStretch() left_right_layout.addWidget(self.left_button) left_right_layout.addStretch() left_right_layout.addWidget(self.right_button) left_right_layout.addStretch() self.location_label = QLabel("车牌目录", self) self.location_text = QLineEdit(self) self.location_text.setEnabled(False) #self.location_text.setFixedWidth(300) self.location_button = QPushButton("...") self.location_button.clicked.connect(self.select_new_dir) self.location_layout = QHBoxLayout() self.location_layout.addWidget(self.location_label) self.location_layout.addWidget(self.location_text) self.location_layout.addWidget(self.location_button) self.location_layout.addStretch() self.check_box = QCheckBox("与文件名比较车牌") self.check_box.setChecked(True) self.update_file_path_button = QPushButton('批量识别') self.update_file_path_button.clicked.connect( self.batch_recognize_all_images) self.update_file_path_layout = QHBoxLayout() self.update_file_path_layout.addWidget(self.check_box) self.update_file_path_layout.addWidget(self.update_file_path_button) self.update_file_path_layout.addStretch() self.save_as_e2e_filename_button = QPushButton("保存e2e文件名") self.save_as_e2e_filename_button.setEnabled(False) self.save_as_e2e_filename_button.clicked.connect( self.rename_current_image_with_info) self.save_layout = QHBoxLayout() self.save_layout.addWidget(self.save_as_e2e_filename_button) self.save_layout.addStretch() self.top_layout = QVBoxLayout() self.top_layout.addLayout(left_right_layout) self.top_layout.addLayout(self.location_layout) self.top_layout.addLayout(self.update_file_path_layout) self.top_layout.addLayout(self.save_layout) function_groupbox = QGroupBox("功能区") function_groupbox.setLayout(self.top_layout) license_plate_image_label = QLabel("车牌图") self.license_plate_widget = QLabel("") block_image_label = QLabel("分割图") self.block_plate_widget = QLabel("") filename_label = QLabel("文件名:") self.filename_edit = QLineEdit() segmentation_recognition_label = QLabel("分割识别:") self.segmentation_recognition_edit = QLineEdit() self.segmentation_recognition_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.segmentation_recognition_edit.setStyleSheet("color:red") confidence_label = QLabel("分割识别\n置信度") self.confidence_edit = QLineEdit() #self.confidence_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.confidence_edit.setStyleSheet("color:red") plate_color_label = QLabel("车牌颜色") self.plate_color_edit = QLineEdit() self.plate_color_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.plate_color_edit.setStyleSheet("color:red") e2e_recognization_label = QLabel("e2e识别:") self.e2e_recognization_edit = QLineEdit() self.e2e_recognization_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.e2e_recognization_edit.setStyleSheet("color:red") e2e_confidence_label = QLabel("e2e置信度") self.e2e_confidence_edit = QLineEdit() #self.e2e_confidence_edit.setFont(QFont("黑体", 24, QFont.Bold)) # self.e2e_confidence_edit.setStyleSheet("color:red") info_gridlayout = QGridLayout() line_index = 0 info_gridlayout.addWidget(filename_label, line_index, 0) info_gridlayout.addWidget(self.filename_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget(license_plate_image_label, line_index, 0) info_gridlayout.addWidget(self.license_plate_widget, line_index, 1) line_index += 1 info_gridlayout.addWidget(e2e_recognization_label, line_index, 0) info_gridlayout.addWidget(self.e2e_recognization_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget(segmentation_recognition_label, line_index, 0) info_gridlayout.addWidget(self.segmentation_recognition_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget(plate_color_label, line_index, 0) info_gridlayout.addWidget(self.plate_color_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget(block_image_label, line_index, 0) info_gridlayout.addWidget(self.block_plate_widget, line_index, 1) line_index += 1 info_gridlayout.addWidget(confidence_label, line_index, 0) info_gridlayout.addWidget(self.confidence_edit, line_index, 1) line_index += 1 info_gridlayout.addWidget(e2e_confidence_label, line_index, 0) info_gridlayout.addWidget(self.e2e_confidence_edit, line_index, 1) info_widget = QGroupBox("分割识别&e2e") info_widget.setLayout(info_gridlayout) right_splitter = QSplitter(Qt.Vertical) right_splitter.addWidget(self.hyperlpr_tableview) right_splitter.addWidget(function_groupbox) right_splitter.addWidget(info_widget) right_splitter.setStretchFactor(0, 2) right_splitter.setStretchFactor(2, 1) main_splitter = QSplitter(Qt.Horizontal) main_splitter.addWidget(self.image_window_view) main_splitter.addWidget(right_splitter) main_splitter.setStretchFactor(0, 1) self.image_filename_list = [] self.hyperlpr_dir_path = "" self.segmentation_recognition_correct_number = 0 self.color_correct_number = 0 self.e2e_recognization_correct_number = 0 self.current_row = 0 self.batch_recognization_thread = LicenseRecognizationThread() self.batch_recognization_thread.recognization_done_signal.connect( self.recognization_done_slot) self.batch_recognization_thread.start() self.start_init_signal.connect(self.read_path_and_show_one_image) self.setCentralWidget(main_splitter) self.setWindowTitle("HyperLPR车牌识别软件v1.0") self.start_init_signal.emit()
def _init_ui(self): layout = QGridLayout(self) self.polar_viewer = CustomImageViewer(parent=self) self.radial_viewer = RadialFitWidget(parent=self) self.fit_plot = FitPlot(parent=self) self.sliders_widget = SlidersWidget(parent=self) self.fit_button = QPushButton(FitImageButtonStatus.fit.value) self.apply_button = QPushButton('Apply') self.close_button = QPushButton('Close') self.close_button.clicked.connect(self.close) self.multi_fit_window: MultiFitWindow = MultiFitWindow(self.fit_object, self) self.multi_fit_window.sigFitUpdated.connect(self.set_fit) self.multi_fit_window.sigClosed.connect(self._close_multi_fit) self.fit_button.clicked.connect(self._fit_clicked) self.apply_button.clicked.connect(self.apply_results) self.radial_viewer.sigUpdateFit.connect(self._radial_roi_moved) self.radial_viewer.sigUpdateProfile.connect(self._profile_updated) self.sliders_widget.sigValueChanged.connect(self._sliders_changed) self.functions_box = QComboBox(self) self.background_box = QComboBox(self) self.range_strategies_box = QComboBox(self) self.set_as_default_button = QPushButton('Set as default options') self.set_as_default_button.clicked.connect(self._set_as_default) self.range_factor_slider = LabeledSlider('Y range factor', (0, 10), parent=self, decimals=2) self.range_factor_slider.valueChanged.connect(self._on_range_slider_moved) self.sigma_slider = LabeledSlider('Sigma', (0, 10), parent=self, decimals=2) self.sigma_slider.valueChanged.connect(self._on_sigma_slider_moved) self.fit_current_button = QPushButton(CurrentFitButtonStatus.fit.value) self.fit_current_button.clicked.connect(self._fit_current_clicked) self.update_data_button = QPushButton('Update fit') self.update_data_button.clicked.connect(self._update_data_button_clicked) self.functions_box.currentTextChanged.connect(self._change_function) self.background_box.currentTextChanged.connect(self._change_background) self.range_strategies_box.currentTextChanged.connect(self._change_range_strategy) self.functions_box.addItem('Fitting functions') for t in FittingType: self.functions_box.addItem(t.value) self.background_box.addItem('Backgrounds') for t in BackgroundType: self.background_box.addItem(t.value) self.range_strategies_box.addItem('Range strategy') for t in RangeStrategyType: self.range_strategies_box.addItem(t.value) self.selected_fit_label = QLabel('Selected Fit', self) self.current_image_label = QLabel('Current Image', self) single_image_widget = QWidget(self) q_splitter_h1 = QSplitter(orientation=Qt.Vertical, parent=single_image_widget) q_splitter_h1.addWidget(self.polar_viewer) q_splitter_h1.addWidget(self.radial_viewer) s_layout = QGridLayout(single_image_widget) s_layout.addWidget(self.current_image_label, 0, 0, 1, 3) s_layout.addWidget(q_splitter_h1, 1, 0, 1, 3) s_layout.addWidget(self.fit_button, 2, 0) s_layout.addWidget(self.apply_button, 2, 1) s_layout.addWidget(self.close_button, 2, 2) single_roi_widget = QWidget(self) q_scroll_area = QScrollArea(self) q_scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) q_scroll_area.setWidgetResizable(True) q_scroll_area.setGeometry(0, 0, 300, 400) options_widget = QWidget(self) options_widget.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding ) scroll_layout = QGridLayout(options_widget) scroll_layout.addWidget(self.background_box, 0, 0) scroll_layout.addWidget(self.functions_box, 1, 0) scroll_layout.addWidget(self.range_strategies_box, 2, 0) scroll_layout.addWidget(self.range_factor_slider, 3, 0) scroll_layout.addWidget(self.set_as_default_button, 0, 1) scroll_layout.addWidget(self.fit_current_button, 1, 1) scroll_layout.addWidget(self.update_data_button, 2, 1) scroll_layout.addWidget(self.sigma_slider, 3, 1) scroll_layout.addWidget(self.sliders_widget, 4, 0, 2, 2) q_scroll_area.setWidget(options_widget) q_splitter_h2 = QSplitter(orientation=Qt.Vertical, parent=self) q_splitter_h2.addWidget(self.fit_plot) q_splitter_h2.addWidget(q_scroll_area) # q_splitter_h2.addWidget(self.sliders_widget) sr_layout = QGridLayout(single_roi_widget) sr_layout.addWidget(self.selected_fit_label, 0, 0) sr_layout.addWidget(q_splitter_h2, 1, 0) q_splitter_v = QSplitter(orientation=Qt.Horizontal, parent=self) q_splitter_v.addWidget(self.multi_fit_window) q_splitter_v.addWidget(single_image_widget) q_splitter_v.addWidget(single_roi_widget) q_splitter_v.setSizes((300, 600, self.width() - 900)) q_splitter_h1.setSizes((400, self.height() - 400)) q_splitter_h2.setSizes((400, self.height() - 400)) layout.addWidget(q_splitter_v, 0, 0, 2, 2)
class BlockEditor(QWidget, MooseWidget): """ The complete editing widget for a Block. The input file will only change when "Apply changes" has been clicked. Until then all changes only live in the widgets. The exceptions to this are the "Clone" and "Remove" buttons which just sends out signals to let others do work. Signals: needBlockList(list): When the type of a parameter references blocks (for example it is a VariableName), this is used to update the available options since they can change based on what the user does. blockRenamed(object, str): A block has been renamed. This is emitted so that the BlockTree can update the name of the block. blockChanged(object): Apply has been clicked for this block. cloneBlock(object): The user wants to clone the block we are currently editing. removeBlock(object): The user wants to remove the block we are currently editing. editingFinished(): The user is done editing this block. Typically done by closing the window. appliedAndClosed(object): Emit the block when the user hits the "Apply & Close" button """ needBlockList = pyqtSignal(list) # list of paths that we need children for blockRenamed = pyqtSignal(object, str) # block with changes, old path blockChanged = pyqtSignal(object) # block that has changed cloneBlock = pyqtSignal(object) # block to clone removeBlock = pyqtSignal(object) # block to remove editingFinished = pyqtSignal() appliedAndClosed = pyqtSignal(object) def __init__(self, block, type_to_block_map, **kwds): """ Sets up an editor for a block. Input: block[BlockInfo]: Block to be edited. """ super(BlockEditor, self).__init__(**kwds) self.block = block self.comment_edit = CommentEditor() self.comment_edit.setComments(self.block.comments) self.comment_edit.textChanged.connect(self._blockChanged) self.splitter = None self.clone_button = None self.clone_shortcut = None self.remove_button = None self.apply_button = None self.reset_button = None self.new_parameter_button = None self.param_editor = None self.setWindowTitle(block.path) if block.types: self.param_editor = ParamsByType(block, type_to_block_map) elif block.parameters: self.param_editor = ParamsByGroup(block, block.orderedParameters(), type_to_block_map) else: self.param_editor = ParamsTable(block, block.orderedParameters(), type_to_block_map) self.param_editor.needBlockList.connect(self.needBlockList) self.param_editor.changed.connect(self._blockChanged) self.param_editor.blockRenamed.connect(self.blockRenamed) self._createButtons() self.applyChanges() self._current_commands = [] self._command_index = 0 self.user_params = [] self.splitter = QSplitter(self) self.splitter.setOrientation(Qt.Vertical) self.splitter.setChildrenCollapsible(False) self.splitter.addWidget(self.param_editor) self.splitter.addWidget(self.comment_edit) self.splitter.setStretchFactor(0,2) self.splitter.setStretchFactor(1,1) self.top_layout = WidgetUtils.addLayout(vertical=True) self.top_layout.addWidget(self.splitter) self.top_layout.addLayout(self.button_layout) self.setLayout(self.top_layout) self.setup() def _blockChanged(self, enabled=True): """ Sets the Apply and Reset buttons based on enabled. Input: enabled[bool]: Whether to set the buttons to enabled """ self.apply_button.setEnabled(enabled) self.reset_button.setEnabled(enabled) self.setWindowTitle(self.block.path) def setWatchedBlockList(self, path, children): self.param_editor.setWatchedBlockList(path, children) def _createButtons(self): """ Create allowable buttons for this Block. This will depend on whether this is a user added block. """ self.button_layout = WidgetUtils.addLayout() self.close_button = WidgetUtils.addButton(self.button_layout, self, "Apply && Close", self._applyAndClose) self.close_button.setToolTip("Apply any changes and close the window") self.apply_button = WidgetUtils.addButton(self.button_layout, self, "Apply", self.applyChanges) self.apply_button.setEnabled(False) self.apply_button.setToolTip("Apply changes made") self.reset_button = WidgetUtils.addButton(self.button_layout, self, "Reset", self.resetChanges) self.reset_button.setEnabled(False) self.reset_button.setToolTip("Reset changes to when this window was opened") self.new_parameter_button = WidgetUtils.addButton(self.button_layout, self, "Add parameter", self.addUserParamPressed) self.new_parameter_button.setToolTip("Add a non standard parameter") if self.block.user_added: self.clone_button = WidgetUtils.addButton(self.button_layout, self, "Clone Block", self._cloneBlock) self.clone_shortcut = WidgetUtils.addShortcut(self, "Ctrl+N", self._cloneBlock, shortcut_with_children=True) self.clone_button.setToolTip("Clone this block with the same parameters") self.remove_button = WidgetUtils.addButton(self.button_layout, self, "Remove Block", self._removeBlock) self.remove_button.setToolTip("Remove this block") def _findFreeParamName(self, max_params=1000): """ Find a free parameter name that can be safely added. Input: max_params[int]: Maximum number of tries before giving up. """ base = "NewParam" for i in range(max_params): param = '%s%s' % (base, i) if self.param_editor.paramValue(param) == None: return param def addUserParamPressed(self): """ The user wants to add a new user parameter to this block. """ new_name = self._findFreeParamName() self._blockChanged() self.param_editor.addUserParam(new_name) def _cloneBlock(self): """ The user wants to clone this block """ self.cloneBlock.emit(self.block) def _removeBlock(self): """ The user wants to remove this block. We ask to make sure they want to do this. """ button = QMessageBox.question(self, "Confirm remove", "Are you sure you want to delete %s" % self.block.path, QMessageBox.Yes, QMessageBox.No) if button == QMessageBox.Yes: self.removeBlock.emit(self.block) self.hide() self.editingFinished.emit() def applyChanges(self): """ Apply any changes the user has made. """ self.block.comments = self.comment_edit.getComments() self.param_editor.save() self.block.changed_by_user = True self._blockChanged(enabled=False) self.blockChanged.emit(self.block) def _applyAndClose(self): """ Apply any changes the user has made then close the window """ if self.apply_button.isEnabled(): self.applyChanges() self.appliedAndClosed.emit(self.block) self.close() def resetChanges(self): """ Reset any changes the user has made. """ self.comment_edit.setComments(self.block.comments) self.param_editor.reset() self._blockChanged(enabled=False) def updateWatchers(self): """ This should be called after creating a BlockEditor. This isn't called in the constructor because the caller will typically need to hook up the needBlockList signal first. """ self.param_editor.updateWatchers() def closeEvent(self, event): """ The user is done editing. """ self.editingFinished.emit()
def __init__(self): super().__init__() self.setWindowTitle(self.stringName) # Setup layout: base = QHBoxLayout() widget = QWidget() widget.setLayout(base) baseLayout = QSplitter() base.addWidget(baseLayout) self.setWidget(widget) buttonLayout = QVBoxLayout() buttonBox = QWidget() buttonBox.setLayout(buttonLayout) baseLayout.addWidget(buttonBox) # Comic page list and pages model self.comicPageList = QTableView() self.comicPageList.verticalHeader().setSectionsMovable(True) self.comicPageList.verticalHeader().setDragEnabled(True) self.comicPageList.verticalHeader().setDragDropMode( QAbstractItemView.InternalMove) self.comicPageList.setAcceptDrops(True) self.comicPageList.horizontalHeader().setStretchLastSection(True) self.pagesModel = QStandardItemModel() self.comicPageList.doubleClicked.connect(self.slot_open_page) self.comicPageList.setIconSize(QSize(128, 128)) # self.comicPageList.itemDelegate().closeEditor.connect(self.slot_write_description) self.pagesModel.layoutChanged.connect(self.slot_write_config) self.pagesModel.rowsInserted.connect(self.slot_write_config) self.pagesModel.rowsRemoved.connect(self.slot_write_config) self.comicPageList.verticalHeader().sectionMoved.connect( self.slot_write_config) self.comicPageList.setModel(self.pagesModel) pageBox = QWidget() pageBox.setLayout(QVBoxLayout()) zoomSlider = QSlider(Qt.Horizontal, None) zoomSlider.setRange(1, 8) zoomSlider.setValue(4) zoomSlider.setTickInterval(1) zoomSlider.setMinimumWidth(10) zoomSlider.valueChanged.connect(self.slot_scale_thumbnails) self.projectName = Elided_Text_Label() pageBox.layout().addWidget(self.projectName) pageBox.layout().addWidget(zoomSlider) pageBox.layout().addWidget(self.comicPageList) baseLayout.addWidget(pageBox) self.btn_project = QToolButton() self.btn_project.setPopupMode(QToolButton.MenuButtonPopup) self.btn_project.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) menu_project = QMenu() self.action_new_project = QAction(i18n("New Project"), self) self.action_new_project.triggered.connect(self.slot_new_project) self.action_load_project = QAction(i18n("Open Project"), self) self.action_load_project.triggered.connect(self.slot_open_config) menu_project.addAction(self.action_new_project) menu_project.addAction(self.action_load_project) self.btn_project.setMenu(menu_project) self.btn_project.setDefaultAction(self.action_load_project) buttonLayout.addWidget(self.btn_project) # Settings dropdown with actions for the different settings menus. self.btn_settings = QToolButton() self.btn_settings.setPopupMode(QToolButton.MenuButtonPopup) self.btn_settings.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.action_edit_project_settings = QAction(i18n("Project Settings"), self) self.action_edit_project_settings.triggered.connect( self.slot_edit_project_settings) self.action_edit_meta_data = QAction(i18n("Meta Data"), self) self.action_edit_meta_data.triggered.connect(self.slot_edit_meta_data) self.action_edit_export_settings = QAction(i18n("Export Settings"), self) self.action_edit_export_settings.triggered.connect( self.slot_edit_export_settings) menu_settings = QMenu() menu_settings.addAction(self.action_edit_project_settings) menu_settings.addAction(self.action_edit_meta_data) menu_settings.addAction(self.action_edit_export_settings) self.btn_settings.setDefaultAction(self.action_edit_project_settings) self.btn_settings.setMenu(menu_settings) buttonLayout.addWidget(self.btn_settings) self.btn_settings.setDisabled(True) # Add page drop down with different page actions. self.btn_add_page = QToolButton() self.btn_add_page.setPopupMode(QToolButton.MenuButtonPopup) self.btn_add_page.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.action_add_page = QAction(i18n("Add Page"), self) self.action_add_page.triggered.connect(self.slot_add_new_page_single) self.action_add_template = QAction(i18n("Add Page From Template"), self) self.action_add_template.triggered.connect( self.slot_add_new_page_from_template) self.action_add_existing = QAction(i18n("Add Existing Pages"), self) self.action_add_existing.triggered.connect(self.slot_add_page_from_url) self.action_remove_selected_page = QAction(i18n("Remove Page"), self) self.action_remove_selected_page.triggered.connect( self.slot_remove_selected_page) self.action_resize_all_pages = QAction(i18n("Batch Resize"), self) self.action_resize_all_pages.triggered.connect(self.slot_batch_resize) self.btn_add_page.setDefaultAction(self.action_add_page) self.action_show_page_viewer = QAction(i18n("View Page In Window"), self) self.action_show_page_viewer.triggered.connect( self.slot_show_page_viewer) self.action_scrape_authors = QAction(i18n("Scrape Author Info"), self) self.action_scrape_authors.setToolTip( i18n( "Search for author information in documents and add it to the author list. This doesn't check for duplicates." )) self.action_scrape_authors.triggered.connect( self.slot_scrape_author_list) self.action_scrape_translations = QAction( i18n("Scrape Text for Translation"), self) self.action_scrape_translations.triggered.connect( self.slot_scrape_translations) actionList = [] menu_page = QMenu() actionList.append(self.action_add_page) actionList.append(self.action_add_template) actionList.append(self.action_add_existing) actionList.append(self.action_remove_selected_page) actionList.append(self.action_resize_all_pages) actionList.append(self.action_show_page_viewer) actionList.append(self.action_scrape_authors) actionList.append(self.action_scrape_translations) menu_page.addActions(actionList) self.btn_add_page.setMenu(menu_page) buttonLayout.addWidget(self.btn_add_page) self.btn_add_page.setDisabled(True) self.comicPageList.setContextMenuPolicy(Qt.ActionsContextMenu) self.comicPageList.addActions(actionList) # Export button that... exports. self.btn_export = QPushButton(i18n("Export Comic")) self.btn_export.clicked.connect(self.slot_export) buttonLayout.addWidget(self.btn_export) self.btn_export.setDisabled(True) self.btn_project_url = QPushButton(i18n("Copy Location")) self.btn_project_url.setToolTip( i18n( "Copies the path of the project to the clipboard. Useful for quickly copying to a file manager or the like." )) self.btn_project_url.clicked.connect(self.slot_copy_project_url) self.btn_project_url.setDisabled(True) buttonLayout.addWidget(self.btn_project_url) self.page_viewer_dialog = comics_project_page_viewer.comics_project_page_viewer( ) Application.notifier().imageSaved.connect( self.slot_check_for_page_update) buttonLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.MinimumExpanding))
class MainWindow(QMainWindow): # class EventFilter(QObject): # def __init__(self, parent): # super().__init__(parent) # # def eventFilter(self, obj, e): # #print(obj.metaObject().className()) # # if e.type() == QEvent.KeyPress or e.type() == QEvent.ShortcutOverride: # key = e.key() # mod = e.modifiers() # # print(str(e) + ' ' + str(e.type()) ) # # if mod == Qt.AltModifier: # print('*'*30) # print('alt pressed') # if key == Qt.Key_Left or key == Qt.Key_Right: # print('alt-left') if key == Qt.Key_Left else print('alt-right') ## action = QAbstractItemView.MoveLeft if key == Qt.Key_Left else QAbstractItemView.MoveRight ## idx = obj.moveCursor(action, Qt.NoModifier) ## item = obj.itemFromIndex(idx) ## obj.setCurrentItem(item) # return True # # return False PROGRAM_NAME = 'KiCad Schematic Component Manager' #-------------------------------------------------------------------------------- class EventFilter(QObject): def __init__(self, parent): super().__init__(parent) def eventFilter(self, obj, e): if e.type() == QEvent.KeyPress or e.type( ) == QEvent.ShortcutOverride: key = e.key() mod = e.modifiers() #print(obj.focusWidget().metaObject().className()) return False #-------------------------------------------------------------------------------- def scroll_left(self): print('alt-left') if self.ToolIndex == 3 or self.ToolIndex == 2: self.ToolList[self.ToolIndex].finish_edit() self.ToolIndex -= 1 if self.ToolIndex < 0: self.ToolIndex = len(self.ToolList) - 1 print('Tool Index: ' + str(self.ToolIndex)) self.ToolList[self.ToolIndex].setFocus() #-------------------------------------------------------------------------------- def scroll_right(self): print('alt-right') if self.ToolIndex == 3 or self.ToolIndex == 2: self.ToolList[self.ToolIndex].finish_edit() self.ToolIndex += 1 if self.ToolIndex == len(self.ToolList): self.ToolIndex = 0 print('Tool Index: ' + str(self.ToolIndex)) self.ToolList[self.ToolIndex].setFocus() #-------------------------------------------------------------------------------- def mouse_change_tool(self, s): print('Tool ' + s) if s == 'CmpTable': self.ToolIndex = 0 elif s == 'Selector': self.ToolIndex = 1 elif s == 'Inspector': self.ToolIndex = 2 elif s == 'FieldInspector': self.ToolIndex = 3 if self.ToolIndex != 3: self.ToolList[3].finish_edit( ) # save field properties when leave field inspector #-------------------------------------------------------------------------------- def add_user_property(self): self.Inspector.save_cmps() self.FieldInspector.save_fields() self.Inspector.add_property() #-------------------------------------------------------------------------------- def remove_user_property(self): #self.Inspector.save_cmps() self.FieldInspector.save_fields() self.Inspector.remove_property() #-------------------------------------------------------------------------------- def rename_user_property(self): #self.Inspector.save_cmps() self.FieldInspector.save_fields() self.Inspector.rename_property() #-------------------------------------------------------------------------------- def __init__(self): super().__init__() self.initUI() self.installEventFilter(self.EventFilter(self)) self.setFocusPolicy(Qt.WheelFocus) self.setTabOrder(self.CmpTable, self.Inspector) self.setTabOrder(self.Inspector, self.Selector) self.setTabOrder(self.Selector, self.FieldInspector) #self.setTabOrder(self.FieldInspector, self.CmpTable) #---------------------------------------------------- # # Application Hotkeys # self.shortcutLeft = QShortcut(QKeySequence(Qt.ALT + Qt.Key_Left), self) self.shortcutRight = QShortcut(QKeySequence(Qt.ALT + Qt.Key_Right), self) self.shortcutLeft.setContext(Qt.ApplicationShortcut) self.shortcutRight.setContext(Qt.ApplicationShortcut) self.shortcutLeft.activated.connect(self.scroll_left) self.shortcutRight.activated.connect(self.scroll_right) #-------------------------------------------------------------------------------- def initUI(self): #---------------------------------------------------- # # Main Window # work_zone = QWidget(self) Layout = QHBoxLayout(work_zone) self.setCentralWidget(work_zone) openAction = QAction(QIcon(os.path.join(resources_path, 'open24.png')), 'Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open Schematic File') openAction.triggered.connect(self.open_file) saveAction = QAction(QIcon(os.path.join(resources_path, 'save24.png')), 'Save', self) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip('Save Schematic File') saveAction.triggered.connect(self.save_file) saveAsAction = QAction( QIcon(os.path.join(resources_path, 'save-as24.png')), 'Save As...', self) saveAsAction.setShortcut('Ctrl+Shift+S') saveAsAction.setStatusTip('Save Schematic File As...') saveAsAction.triggered.connect(self.save_file_as) exitAction = QAction(QIcon(os.path.join(resources_path, 'exit24.png')), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.close) settingsAction = QAction( QIcon(os.path.join(resources_path, 'settings24.png')), 'Settings', self) settingsAction.setShortcut('Ctrl+Alt+S') settingsAction.setStatusTip('Edit settings') settingsAction.triggered.connect(self.edit_settings) helpAction = QAction( QIcon(os.path.join(resources_path, 'help_book24.png')), 'User\'s Manual', self) helpAction.setShortcut('F1') helpAction.setStatusTip('User\'s Manual') helpAction.triggered.connect(self.show_user_manual_slot) helpSDAction = QAction( QIcon(os.path.join(resources_path, 'gear24.png')), 'Settings Dialog', self) helpSDAction.setShortcut('Ctrl+F1') helpSDAction.setStatusTip('Settings Dialog Help') helpSDAction.triggered.connect(self.show_setting_dialog_help_slot) helpHKAction = QAction( QIcon(os.path.join(resources_path, 'rocket24.png')), 'Hotkeys', self) helpHKAction.setShortcut('Shift+F1') helpHKAction.setStatusTip('Hotkeys Help') helpHKAction.triggered.connect(self.show_hotkeys_help_slot) self.statusBar().showMessage('Ready') #-------------------------------------------- # # Main Menu # menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(openAction) fileMenu.addAction(saveAction) fileMenu.addAction(saveAsAction) fileMenu.addAction(exitAction) #-------------------------------------------- # # Options Menu # optionsMenu = menubar.addMenu('&Options') optionsMenu.addAction(settingsAction) #-------------------------------------------- # # Help Menu # helpMenu = menubar.addMenu('&Help') helpMenu.addAction(helpAction) helpMenu.addAction(helpSDAction) helpMenu.addAction(helpHKAction) #-------------------------------------------- # # Toolbar # toolbar = self.addToolBar('Exit') toolbar.addAction(exitAction) toolbar.addAction(openAction) toolbar.addAction(saveAction) toolbar.addAction(saveAsAction) toolbar.addAction(settingsAction) toolbar.addAction(helpAction) #---------------------------------------------------- # # Settings Dialog # #---------------------------------------------------- # # Components Table # self.CmpTabBox = QGroupBox('Components', self) self.CmpTabLayout = QVBoxLayout(self.CmpTabBox) self.CmpTabLayout.setContentsMargins(4, 10, 4, 4) self.CmpTabLayout.setSpacing(10) self.CmpTabLayout.setSizeConstraint(QVBoxLayout.SetMaximumSize) self.CmpTable = ComponentsTable(self) #self.CmpChooseButton = QPushButton('Choose', self) self.CmpTabLayout.addWidget(self.CmpTable) #self.CmpTabLayout.addWidget(self.CmpChooseButton) #---------------------------------------------------- # # Selector # self.SelectorBox = QGroupBox('Selector', self) self.SelectorLayout = QVBoxLayout(self.SelectorBox) self.SelectorLayout.setContentsMargins(4, 10, 4, 4) self.SelectorLayout.setSpacing(2) self.SelectorBtnWidget = QWidget(self) self.SelectorBtnLayout = QHBoxLayout(self.SelectorBtnWidget) self.SelectorBtnLayout.setContentsMargins(4, 10, 4, 4) self.SelectorBtnLayout.setSpacing(10) self.Selector = Selector(self) self.SelApplyButton = QPushButton('Apply', self) self.SelApplyButton.setToolTip( 'Alt+S: Apply selection patterns to components') self.SelClearButton = QPushButton('Clear', self) self.SelClearButton.setToolTip('Alt+C: Clear selection patterns') self.SelTemplateButton = QPushButton('Use Component', self) self.SelTemplateButton.setToolTip( 'Alt+T: Use Selected Component As Template') self.SelectorLayout.addWidget(self.Selector) self.SelectorBtnLayout.addWidget(self.SelTemplateButton) self.SelectorBtnLayout.addWidget(self.SelApplyButton) self.SelectorBtnLayout.addWidget(self.SelClearButton) self.SelectorLayout.addWidget(self.SelectorBtnWidget) self.shortcutSelApply = QShortcut(QKeySequence(Qt.ALT + Qt.Key_S), self) self.shortcutSelApply.activated.connect(self.Selector.apply_slot) self.shortcutSelClear = QShortcut(QKeySequence(Qt.ALT + Qt.Key_C), self) self.shortcutSelClear.activated.connect(self.Selector.clear_slot) self.shortcutSelTemplate = QShortcut(QKeySequence(Qt.ALT + Qt.Key_T), self) self.shortcutSelTemplate.activated.connect( self.Selector.use_comp_as_template_slot) #---------------------------------------------------- # # Inspector # self.Inspector = Inspector(self) self.FieldInspector = FieldInspector(self) self.InspectorBtnWidget = QWidget(self) self.InspectorBtnLayout = QHBoxLayout(self.InspectorBtnWidget) self.InspectorBtnLayout.setContentsMargins(4, 10, 4, 4) self.InspectorBtnLayout.setSpacing(10) self.AddUserProperty = QPushButton('Add Property', self) self.AddUserProperty.setToolTip('Alt+A: Add new user property') self.DeleteUserProperty = QPushButton('Delete Property', self) self.DeleteUserProperty.setToolTip('Alt+Delete: Delete user property') self.RenameUserProperty = QPushButton('Rename Property', self) self.RenameUserProperty.setToolTip('Alt+R: Rename user property') self.InspectorBox = QGroupBox('Inspector', self) self.InspectorSplit = QSplitter(Qt.Vertical, self) self.InspectorLayout = QVBoxLayout(self.InspectorBox) self.InspectorLayout.setContentsMargins(4, 10, 4, 4) self.InspectorLayout.setSpacing(2) self.InspectorSplit.addWidget(self.Inspector) self.InspectorSplit.addWidget(self.FieldInspector) self.InspectorLayout.addWidget(self.InspectorSplit) self.InspectorBtnLayout.addWidget(self.AddUserProperty) self.InspectorBtnLayout.addWidget(self.DeleteUserProperty) self.InspectorBtnLayout.addWidget(self.RenameUserProperty) self.InspectorLayout.addWidget(self.InspectorBtnWidget) self.shortcutSelApply = QShortcut(QKeySequence(Qt.ALT + Qt.Key_A), self) self.shortcutSelApply.activated.connect(self.add_user_property) self.shortcutSelApply = QShortcut(QKeySequence(Qt.ALT + Qt.Key_Delete), self) self.shortcutSelApply.activated.connect(self.remove_user_property) self.shortcutSelApply = QShortcut(QKeySequence(Qt.ALT + Qt.Key_R), self) self.shortcutSelApply.activated.connect(self.rename_user_property) #---------------------------------------------------- self.Splitter = QSplitter(self) self.Splitter.addWidget(self.CmpTabBox) self.Splitter.addWidget(self.SelectorBox) self.Splitter.addWidget(self.InspectorBox) self.centralWidget().layout().addWidget(self.Splitter) #---------------------------------------------------- # # Signals and Slots connections # self.CmpTable.cells_chosen.connect(self.Inspector.load_cmp) self.CmpTable.cells_chosen.connect(self.Selector.comp_template_slot) self.CmpTable.file_load.connect(self.file_loaded_slot) self.CmpTable.cmps_updated.connect(self.Selector.process_comps_slot) self.CmpTable.cmps_selected.connect(self.set_status_text_slot) self.SelApplyButton.clicked.connect(self.Selector.apply_slot) self.SelClearButton.clicked.connect(self.Selector.clear_slot) self.SelTemplateButton.clicked.connect( self.Selector.use_comp_as_template_slot) self.Selector.select_comps_signal.connect( self.CmpTable.select_comps_slot) self.Inspector.load_field.connect(self.FieldInspector.load_field_slot) self.Inspector.update_comps.connect(self.data_changed_slot) self.Inspector.update_comps.connect(self.CmpTable.update_cmp_list_slot) self.FieldInspector.data_changed.connect(self.data_changed_slot) CmpMgr.file_saved.connect(self.file_saved_slot) self.CmpTable.mouse_click.connect(self.mouse_change_tool) self.Inspector.mouse_click.connect(self.mouse_change_tool) self.FieldInspector.mouse_click.connect(self.mouse_change_tool) self.Inspector.header().sectionResized.connect( self.FieldInspector.column_resize) self.AddUserProperty.clicked.connect(self.add_user_property) self.DeleteUserProperty.clicked.connect(self.remove_user_property) self.RenameUserProperty.clicked.connect(self.rename_user_property) #---------------------------------------------------- self.ToolList = [] self.ToolList.append(self.CmpTable) self.ToolList.append(self.Selector) self.ToolList.append(self.Inspector) self.ToolList.append(self.FieldInspector) self.ToolIndex = 0 #---------------------------------------------------- # # Window # self.setWindowTitle(self.PROGRAM_NAME) Settings = QSettings('kicad-tools', 'Schematic Component Manager') #print(Settings.allKeys()) if Settings.contains('geometry'): self.restoreGeometry(Settings.value('geometry')) else: self.setGeometry(100, 100, 1024, 768) if Settings.contains('cmptable'): w0, w1 = Settings.value('cmptable') self.CmpTable.setColumnWidth(0, int(w0)) self.CmpTable.setColumnWidth(1, int(w1)) if Settings.contains('selector'): w0, w1 = Settings.value('selector') self.Selector.setColumnWidth(0, int(w0)) self.Selector.setColumnWidth(1, int(w1)) if Settings.contains('inspector'): w0, w1 = Settings.value('inspector') self.Inspector.setColumnWidth(0, int(w0)) self.Inspector.setColumnWidth(1, int(w1)) self.FieldInspector.setColumnWidth(0, int(w0)) self.FieldInspector.setColumnWidth(1, int(w1)) #self.Inspector.setColumnWidth( 2, int(w2) ) if Settings.contains('splitter'): self.Splitter.restoreState(Settings.value('splitter')) if Settings.contains('inssplitter'): self.InspectorSplit.restoreState(Settings.value('inssplitter')) #---------------------------------------------------- # # Process command line arguments # if len(sys.argv) > 1: fname = sys.argv[1] if os.path.exists(fname): self.CmpTable.load_file(fname) else: print('E: input file "' + fname + '"does not exist') self.show() #--------------------------------------------------------------------------- def closeEvent(self, event): Settings = QSettings('kicad-tools', 'Schematic Component Manager') Settings.setValue('geometry', self.saveGeometry()) Settings.setValue( 'cmptable', [self.CmpTable.columnWidth(0), self.CmpTable.columnWidth(1)]) Settings.setValue( 'selector', [self.Selector.columnWidth(0), self.Selector.columnWidth(1)]) Settings.setValue( 'inspector', [self.Inspector.columnWidth(0), self.Inspector.columnWidth(1)]) Settings.setValue('splitter', self.Splitter.saveState()) Settings.setValue('inssplitter', self.InspectorSplit.saveState()) QWidget.closeEvent(self, event) #--------------------------------------------------------------------------- def open_file(self): #filename = QFileDialog.getOpenFileName(self, 'Open schematic file', '/opt/cad/kicad', 'KiCad Schematic Files (*.sch)') dialog = QFileDialog(self) dialog.setFileMode(QFileDialog.ExistingFile) dialog.setNameFilter('KiCad Schematic Files (*.sch)') filenames = [] if dialog.exec_(): filenames = dialog.selectedFiles() if len(filenames) == 0: return CmpMgr.set_curr_file_path(filenames[0]) self.CmpTable.load_file(filenames[0]) #--------------------------------------------------------------------------- def save_file(self): self.FieldInspector.save_fields() self.Inspector.save_cmps() curr_file = CmpMgr.curr_file_path() message = 'Save File "' + curr_file + '"' print(message) self.statusBar().showMessage(message) CmpMgr.save_file(curr_file) #--------------------------------------------------------------------------- def save_file_as(self): self.Inspector.save_cmps() self.FieldInspector.save_fields() filenames = QFileDialog.getSaveFileName( self, 'Save File As...', '', 'KiCad Schematic Files (*.sch)') if filenames[0] == '': return print('Save File As "' + filenames[0] + '"') CmpMgr.save_file(filenames[0]) CmpMgr.set_curr_file_path(filenames[0]) #--------------------------------------------------------------------------- def file_loaded_slot(self): text = CmpMgr.curr_file_path() self.set_title(text) #--------------------------------------------------------------------------- def data_changed_slot(self): text = CmpMgr.curr_file_path() + ' *' self.set_title(text) #--------------------------------------------------------------------------- def file_saved_slot(self): text = CmpMgr.curr_file_path() self.set_title(text) #--------------------------------------------------------------------------- def set_title(self, text=''): text = ' - ' + text if len(text) > 0 else '' self.setWindowTitle(self.PROGRAM_NAME + ' v' + VERSION + text) #--------------------------------------------------------------------------- def set_status_text_slot(self, text): self.statusBar().showMessage(text) #--------------------------------------------------------------------------- def edit_settings(self): print('edit settings') SettingsDialog = TSettingsDialog(self) SettingsDialog.resize(400, 400) SettingsDialog.Tabs.setMinimumWidth(800) SettingsDialog.show() #--------------------------------------------------------------------------- def show_user_manual_slot(self): help = THelpForm(self, 'User\'s Manual', 'main.html') #--------------------------------------------------------------------------- def show_setting_dialog_help_slot(self): help = THelpForm(self, 'Settings Dialog', 'settings.html') #--------------------------------------------------------------------------- def show_hotkeys_help_slot(self): help = THelpForm(self, 'Hotkeys', 'hotkeys.html')
class EditorWindow(QMainWindow): def __init__(self): super().__init__() self.resize(settings().value("MainWindow/size") or QSize(1280, 720)) self.setWindowTitle("untitled") if int(settings().value("MainWindow/maximized") or 0): self.showMaximized() self.setCentralWidget(QWidget()) self.setMenuBar(QMenuBar()) self.setStatusBar(QStatusBar()) self.centralWidget().setLayout(QHBoxLayout()) self.centralWidget().layout().setSpacing(0) self.centralWidget().layout().setContentsMargins(0, 0, 0, 0) self.splitter = QSplitter() self.centralWidget().layout().addWidget(self.splitter) self.projectTree = ProjectTree(self) # self.projectTree.hide() self.splitter.addWidget(self.projectTree) self.tabwidget = TabWidget(self) self.splitter.addWidget(self.tabwidget) self.splitter.setSizes((int(settings().value("Sizes/splitter0") or self.splitter.sizeHint().width() * .2), int(settings().value("Sizes/splitter1") or self.splitter.sizeHint().width() * .8))) #menüler self.fileMenu = QMenu(self.tr("File")) self.newFileActionMenu = QMenu(self.tr("New")) self.newPlainFileAction = QAction(self.tr("File"), icon=QIcon(":/img/text-plain.svg")) self.newFileActionMenu.addAction(self.newPlainFileAction) self.newPythonFileAction = QAction(self.tr("Python File"), icon=QIcon(":/img/text-python.svg")) self.newFileActionMenu.addAction(self.newPythonFileAction) self.newDirectoryAction = QAction(self.tr("Directory"), icon=QIcon(":/img/folder.svg")) self.newFileActionMenu.addAction(self.newDirectoryAction) self.newPythonPackageAction = QAction( self.tr("Python Package"), icon=QIcon(":/img/folder-python.svg")) self.newFileActionMenu.addAction(self.newPythonPackageAction) self.newFileActionMenu.addSeparator() self.newHtmlFileAction = QAction(self.tr("Html File"), icon=QIcon(":/img/text-html.svg")) self.newFileActionMenu.addAction(self.newHtmlFileAction) self.newCssFileAction = QAction(self.tr("Css File"), icon=QIcon(":/img/text-css.svg")) self.newFileActionMenu.addAction(self.newCssFileAction) self.newJsFileAction = QAction(self.tr("JavaScript File"), icon=QIcon(":/img/text-javascript.svg")) self.newFileActionMenu.addAction(self.newJsFileAction) self.newJsonFileAction = QAction(self.tr("Json File"), icon=QIcon(":/img/text-plain.svg")) self.newFileActionMenu.addAction(self.newJsonFileAction) self.newXmlFileAction = QAction(self.tr("Xml File"), icon=QIcon(":/img/text-xml.svg")) self.newFileActionMenu.addAction(self.newXmlFileAction) self.newYamlFileAction = QAction(self.tr("Yaml File"), icon=QIcon(":/img/text-plain.svg")) self.newFileActionMenu.addAction(self.newYamlFileAction) self.newSqlFileAction = QAction(self.tr("Sqlite File"), icon=QIcon(":/img/text-sql.svg")) self.newFileActionMenu.addAction(self.newSqlFileAction) self.newMdFileAction = QAction(self.tr("Markdown File"), icon=QIcon(":/img/text-plain.svg")) self.newFileActionMenu.addAction(self.newMdFileAction) self.fileMenu.addMenu(self.newFileActionMenu) self.newProjectAction = QAction(self.tr("New Project")) self.fileMenu.addAction(self.newProjectAction) self.openFileAction = QAction(self.tr("Open File...")) self.openFileAction.setShortcut("Ctrl+O") self.fileMenu.addAction(self.openFileAction) self.openProjectAction = QAction(self.tr("Open Project...")) self.openProjectAction.setShortcut("Ctrl+Alt+O") self.fileMenu.addAction(self.openProjectAction) self.openRecentFileActionMenu = QMenu(self.tr("Open Recent...")) self.fileMenu.addMenu(self.openRecentFileActionMenu) self.saveFileAction = QAction(self.tr("Save")) self.saveFileAction.setShortcut("Ctrl+S") self.fileMenu.addAction(self.saveFileAction) self.saveAsAction = QAction(self.tr("Save As...")) self.saveAsAction.setShortcut("Ctrl+Alt+S") self.fileMenu.addAction(self.saveAsAction) self.fileMenu.addSeparator() self.closeFileAction = QAction(self.tr("Close File")) self.closeFileAction.setShortcut("Ctrl+W") self.fileMenu.addAction(self.closeFileAction) self.closeAllFilesAction = QAction(self.tr("Close All File")) self.fileMenu.addAction(self.closeAllFilesAction) self.fileMenu.addSeparator() self.exitAction = QAction(self.tr("Exit")) self.exitAction.setShortcut("Ctrl+Q") self.fileMenu.addAction(self.exitAction) self.menuBar().addMenu(self.fileMenu) self.editMenu = QMenu(self.tr("Edit")) self.undoAction = QAction(self.tr("Undo")) self.undoAction.setShortcut("Ctrl+Z") self.undoAction.setShortcutVisibleInContextMenu(True) self.editMenu.addAction(self.undoAction) self.redoAction = QAction(self.tr("Redo")) self.redoAction.setShortcut("Ctrl+Y") self.redoAction.setShortcutVisibleInContextMenu(True) self.editMenu.addAction(self.redoAction) self.editMenu.addSeparator() self.copyAction = QAction(self.tr("Copy")) self.copyAction.setShortcutVisibleInContextMenu(True) self.copyAction.setShortcut("Ctrl+C") self.editMenu.addAction(self.copyAction) self.cutAction = QAction(self.tr("Cut")) self.cutAction.setShortcut("Ctrl+X") self.cutAction.setShortcutVisibleInContextMenu(True) self.editMenu.addAction(self.cutAction) self.pasteAction = QAction(self.tr("Paste")) self.pasteAction.setShortcut("Ctrl+V") self.pasteAction.setShortcutVisibleInContextMenu(True) self.editMenu.addAction(self.pasteAction) self.editMenu.addSeparator() # self.wrapActionMenu = QMenu(self.tr("Wrap")) # self.editMenu.addMenu(self.wrapActionMenu) self.menuBar().addMenu(self.editMenu) self.findMenu = QMenu(self.tr("Find")) self.findAction = QAction(self.tr("Find...")) self.findAction.setShortcut("Ctrl+F") self.findMenu.addAction(self.findAction) self.findNextAction = QAction(self.tr("Find Next")) self.findNextAction.setShortcut("F3") self.findMenu.addAction(self.findNextAction) self.findPreviousAction = QAction(self.tr("Find Previous")) self.findPreviousAction.setShortcut("Shift+F3") self.findMenu.addAction(self.findPreviousAction) self.findMenu.addSeparator() self.replaceAction = QAction(self.tr("Replace")) self.replaceAction.setShortcut("Ctrl+H") self.findMenu.addAction(self.replaceAction) self.replaceNextAction = QAction(self.tr("Replace Next")) self.replaceNextAction.setShortcut("Ctrl+Shift+H") self.findMenu.addAction(self.replaceNextAction) self.menuBar().addMenu(self.findMenu) # self.viewMenu = QMenu(self.tr("View")) # self.layoutActionMenu = QMenu(self.tr("Layout")) # self.viewMenu.addMenu(self.layoutActionMenu) # self.groupsActionMenu = QMenu(self.tr("Groups")) # self.viewMenu.addMenu(self.groupsActionMenu) # self.focusGroupActionMenu = QMenu(self.tr("Focus Group")) # self.viewMenu.addMenu(self.focusGroupActionMenu) # self.moveFileGroupActionMenu = QMenu(self.tr("Move File to Group")) # self.viewMenu.addMenu(self.moveFileGroupActionMenu) # self.viewMenu.addSeparator() # self.syntaxActionMenu = QMenu(self.tr("Syntax")) # self.viewMenu.addMenu(self.syntaxActionMenu) # self.indentationActionMenu = QMenu(self.tr("Indentation")) # self.viewMenu.addMenu(self.indentationActionMenu) # self.lineEndingsActionMenu = QMenu(self.tr("Line Endings")) # self.viewMenu.addMenu(self.lineEndingsActionMenu) # self.viewMenu.addSeparator() # self.menuBar().addMenu(self.viewMenu) self.toolsMenu = QMenu(self.tr("Tools")) self.snippetsAction = QAction(self.tr("Snippets...")) self.toolsMenu.addAction(self.snippetsAction) self.toolsMenu.addSeparator() self.runAction = QAction(self.tr("Run")) self.runAction.setShortcut("F5") self.toolsMenu.addAction(self.runAction) self.runWithAction = QAction(self.tr("Run With...")) self.runWithAction.setShortcut("F6") self.toolsMenu.addAction(self.runWithAction) self.toolsMenu.addSeparator() self.recordMacroAction = QAction(self.tr("Record Macro")) self.toolsMenu.addAction(self.recordMacroAction) self.playbackMacroAction = QAction(self.tr("Playback Macro")) self.toolsMenu.addAction(self.playbackMacroAction) self.saveMacroAction = QAction(self.tr("Save Macro...")) self.toolsMenu.addAction(self.saveMacroAction) self.macrosActionMenu = QMenu(self.tr("Macros")) self.toolsMenu.addMenu(self.macrosActionMenu) self.menuBar().addMenu(self.toolsMenu) self.helpMenu = QMenu(self.tr("Help")) self.documentationAction = QAction(self.tr("Documentation")) self.helpMenu.addAction(self.documentationAction) self.donateAction = QAction(self.tr("Donate")) self.helpMenu.addAction(self.donateAction) self.helpMenu.addSeparator() self.checkAction = QAction(self.tr("Check for Updates...")) self.helpMenu.addAction(self.checkAction) self.changelogAction = QAction(self.tr("Changelog...")) self.helpMenu.addAction(self.changelogAction) self.aboutAction = QAction(self.tr("About Untitled Editor")) self.helpMenu.addAction(self.aboutAction) self.menuBar().addMenu(self.helpMenu) def setWindowTitle(self, title): super().setWindowTitle(title + " - " + "Untitled Editor") def closeEvent(self, *args, **kwargs): settings().setValue("Sizes/splitter0", self.projectTree.width()) settings().setValue("Sizes/splitter1", self.tabwidget.width()) settings().setValue("MainWindow/maximized", int(self.isMaximized())) settings().setValue("MainWindow/size", self.size()) settings().sync() def retranslateui(self): pass
class BrowserWindow(QMainWindow): class SavedWindow(object): def __init__(self, window=None): ''' @param: window BrowserWindow ''' self.windowState = QByteArray() self.windowGeometry = QByteArray() self.windowUiState = {} # QString -> QVariant self.virtualDesktop = -1 self.currentTab = -1 self.tabs = [] # WebTab.SavedTab if window: self.init(window) def init(self, window): if window.isFullScreen(): self.windowState = QByteArray() else: self.windowState = window.saveState() self.windowGeometry = window.saveGeometry() self.windowUiState = window._saveUiState() tabsCount = window.tabCount() for idx in range(tabsCount): # TabbedWebView webView = window.weView(idx) if not webView: continue webTab = webView.webTab() if not webTab: continue tab = WebTab.SavedTab(webTab) if not tab.isValid(): continue if webTab.isCurrentTab(): self.currentTab = len(self.tabs) self.tabs.append(tab) def isValid(self): for tab in self.tabs: if not tab.isValid(): return False return self.currentTab > -1 def clear(self): self.windowState.clear() self.windowGeometry.clear() self.virtualDesktop = -1 self.currentTab = -1 self.tabs.clear() def __init__(self, type_, startUrl=QUrl()): super().__init__(None) self._startUrl = startUrl self._homepage = QUrl() self._windowType = type_ self._startTab = None # WebTab self._startPage = None # WebPage self._mainLayout = None # QVBoxLayout self._mainSplitter = None # QSplitter self._tabWidget = None # TabWidget self._sideBar = None # QPointer<SideBar> self._sideBarManager = SideBarManager(self) self._statusBar = None self._navigationContainer = None # NavigationContainer self._navigationToolbar = None # NavigationBar self._bookmarksToolbar = None # BookmarksToolbar self._progressBar = None # ProgressBar self._ipLabel = None # QLabel self._superMenu = None # QMenu self._mainMenu = None # MainMenu self._tabModel = None # TabModel self._tabMruModel = None # TabMruModel self._sideBarWidth = 0 self._webViewWidth = 0 # Shortcuts self._useTabNumberShortcuts = False self._useSpeedDialNumberShortcuts = False self._useSingleKeyShortcuts = False # Remember visibility of menubar and statusbar after entering Fullscreen self._menuBarVisible = False self._statusBarVisible = False self._htmlFullScreenView = None # TabbedWebView self._hideNavigationTimer = None # QTimer self._deleteOnCloseWidgets = [] # QList<QPointer<QWidget>> self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_DontCreateNativeAncestors) self.setObjectName('mainwindow') self.setWindowTitle(const.APPNAME) self.setProperty('private', gVar.app.isPrivate()) self._setupUi() self._setupMenu() self._hideNavigationTimer = QTimer(self) self._hideNavigationTimer.setInterval(1000) self._hideNavigationTimer.setSingleShot(True) self._hideNavigationTimer.timeout.connect(self._hideNavigationSlot) gVar.app.settingsReloaded.connect(self._loadSettings) QTimer.singleShot(0, self._postLaunch) if gVar.app.isPrivate(): gVar.appTools.setWmClass( '%s Browser (Private Window)' % const.APPNAME, self) else: gVar.appTools.setWmClass('%s Browser' % const.APPNAME, self) def __del__(self): gVar.app.plugins().emitMainWindowDeleted(self) for widget in self._deleteOnCloseWidgets: widget.deleteLater() def setStartTab(self, tab): ''' @param: tab WebTab ''' self._startTab = tab def setStartPage(self, page): ''' @param: page WebPage ''' self._startPage = page def restoreWindow(self, window): ''' @param: window SavedWindow ''' self.restoreState(window.windowState) self.restoreGeometry(window.windowGeometry) self._restoreUiState(window.windowUiState) if not gVar.app.isTestModeEnabled(): self.show( ) # Window has to be visible before adding QWebEngineView's self._tabWidget.restoreState(window.tabs, window.currentTab) self._updateStartupFocus() def fullScreenNavigationVisible(self): return self._navigationContainer.isVisible() def showNavigationWithFullScreen(self): if self._htmlFullScreenView: return if self._hideNavigationTimer.isActive(): self._hideNavigationTimer.stop() self._navigationContainer.show() def hideNavigationWithFullScreen(self): if self._tabWidget.isCurrentTabFresh(): return if not self._hideNavigationTimer.isActive(): self._hideNavigationTimer.start() def currentTabChanged(self): view = self.weView() self._navigationToolbar.setCurrentView(view) if not view: return title = view.webTab().title(True) # allowEmpty if not title: self.setWindowTitle(const.APPNAME) else: self.setWindowTitle('%s - %s' % (title, const.APPNAME)) self._ipLabel.setText(view.getIp()) view.setFocus() self.updateLoadingActions() # Settings correct tab order (LocationBar -> WebSearchBar -> WebView) self.setTabOrder(self.locationBar(), self._navigationToolbar.webSearchBar()) self.setTabOrder(self._navigationToolbar.webSearchBar(), view) def updateLoadingActions(self): view = self.weView() if not view: return isLoading = view.isLoading() self._ipLabel.setVisible(not isLoading) self._progressBar.setVisible(isLoading) self.action('View/Stop').setEnabled(isLoading) self.action('View/Reload').setEnabled(not isLoading) if isLoading: self._progressBar.setValue(view.loadingProgress()) self._navigationToolbar.showStopButton() else: self._navigationToolbar.showReloadButton() def addBookmark(self, url, title): BookmarksTools.addBookmarkDilaog(self, url, title) def addDeleteOnCloseWidget(self, widget): ''' @param: widget QWidget ''' if widget not in self._deleteOnCloseWidgets: self._deleteOnCloseWidgets.append(widget) def createToolbarsMenu(self, menu): self.removeActions(menu.actions()) menu.clear() action = menu.addAction('&Menu Bar', self.toggleShowMenubar) action.setCheckable(True) action.setChecked(self.menuBar().isVisible()) action = menu.addAction('&Navigation Toolbar', self.toggleShowNavigationToolbar) action.setCheckable(True) action.setChecked(self._navigationToolbar.isVisible()) action = menu.addAction('&Bookmarks Toolbar', self.toggleShowBookmarksToolbar) action.setCheckable(True) action.setChecked(Settings().value( 'Browser-View-Settings/showBookmarksToolbar', True)) menu.addSeparator() action = menu.addAction('&Tabs on Top', self.toggleTabsOnTop) action.setCheckable(True) action.setChecked(gVar.appSettings.tabsOnTop) self.addActions(menu.actions()) def createSidebarsMenu(self, menu): self._sideBarManager.createMenu(menu) def createEncodingMenu(self, menu): isoCodecs = [] utfCodecs = [] windowsCodecs = [] isciiCodecs = [] ibmCodecs = [] otherCodecs = [] allCodecs = [] for mib in QTextCodec.availableMibs(): codecName = QTextCodec.codecForMib(mib).name() codecName = codecName.data().decode('utf8') if codecName in allCodecs: continue allCodecs.append(codecName) if codecName.startswith('ISO'): isoCodecs.append(codecName) elif codecName.startswith('UTF'): utfCodecs.append(codecName) elif codecName.startswith('windows'): windowsCodecs.append(codecName) elif codecName.startswith('Iscii'): isciiCodecs.append(codecName) elif codecName.startswith('IBM'): ibmCodecs.append(codecName) else: otherCodecs.append(codecName) if not menu.isEmpty(): menu.addSeperator() self._createEncodingSubMenu('ISO', isoCodecs, menu) self._createEncodingSubMenu('UTF', utfCodecs, menu) self._createEncodingSubMenu('Windows', windowsCodecs, menu) self._createEncodingSubMenu('Iscii', isciiCodecs, menu) self._createEncodingSubMenu('IBM', ibmCodecs, menu) self._createEncodingSubMenu('Other', otherCodecs, menu) def removeActions(self, actions): ''' @param: actions QList<QAction*> ''' for action in actions: self.removeAction(action) def addSideBar(self): ''' @return SideBar* ''' if self._sideBar: return self._sideBar self._sideBar = SideBar(self._sideBarManager, self) self._mainSplitter.insertWidget(0, self._sideBar) self._mainSplitter.setCollapsible(0, False) self._mainSplitter.setSizes([self._sideBarWidth, self._webViewWidth]) return self._sideBar def setSideBarNone(self): ''' @note: when sideBar is notified destroyed, we should clean python ref in window ''' self._sideBar = None def saveSideBarSettings(self): if self._sideBar: # That +1 is important here, without it, the sidebar width would # decrease by 1 pixel every close self._sideBarWidth = self._mainSplitter.sizes()[0] + 1 self._webViewWidth = self.width() - self._sideBarWidth Settings().setValue('Browser-View-Settings/SideBar', self._sideBarManager.activeSideBar()) def tabCount(self): return self._tabWidget.count() def weView(self, index=None): ''' @return TabbedWebView ''' if index is None: index = self._tabWidget.currentIndex() webTab = self._tabWidget.widget(index) if not webTab: return None return webTab.webView() def windowType(self): ''' @return const.BrowserWindowType ''' return self._windowType def locationBar(self): ''' @return LocationBar ''' return self._tabWidget.locationBars().currentWidget() def tabWidget(self): return self._tabWidget def bookmarksToolbar(self): ''' @return BookmarksToolbar ''' return self._bookmarksToolbar def statusBar(self): ''' @return StatusBar ''' return self._statusBar def navigationBar(self): ''' @return NavigationBar ''' return self._navigationToolbar def sideBarManager(self): ''' @return SideBarManager ''' return self._sideBarManager def ipLabel(self): ''' @return QLabel ''' return self._ipLabel def superMenu(self): ''' @return QMenu ''' return self._superMenu def homepageUrl(self): return self._homepage def action(self, name): ''' @return QAction ''' return self._mainMenu.action(name) def tabModel(self): ''' @return TabModel ''' return self._tabModel def tabMruModel(self): ''' @return TabMruModel ''' return self._tabMruModel # public Q_SIGNALS: startingCompleted = pyqtSignal() aboutToClose = pyqtSignal() # public Q_SLOTS: def addTab(self): self._tabWidget.addViewByUrl(QUrl(), const.NT_SelectedNewEmptyTab, True) self._tabWidget.setCurrentTabFresh(True) if self.isFullScreen(): self.showNavigationWithFullScreen() def goHome(self): self.loadAddress(self._homepage) def goHomeInNewTab(self): self._tabWidget.addViewByUrl(self._homepage, const.NT_SelectedTab) def goBack(self): self.weView().back() def goForward(self): self.weView().forward() def reload(self): self.weView().reload() def reloadBypassCache(self): self.weView().reloadBypassCache() def setWindowTitle(self, title): if gVar.app.isPrivate(): title = '%s (Private Browsing)' % title super().setWindowTitle(title) def showWebInspector(self): webView = self.weView() if webView and webView.webTab(): webView.webTab().showWebInspector() def toggleWebInspector(self): webView = self.weView() if webView and webView.webTab(): webView.webTab().toggleWebInspector() def showHistoryManager(self): gVar.app.browsingLibrary().showHistory(self) def toggleShowMenubar(self): self.setUpdatesEnabled(False) menuBar = self.menuBar() menuBar.setVisible(not menuBar.isVisible()) self._navigationToolbar.setSuperMenuVisible(not menuBar.isVisible()) self.setUpdatesEnabled(True) Settings().setValue('Browser-View-Settings/showMenuBar', menuBar.isVisible()) # Make sure we show Navigation Toolbar when Menu Bar is hidden if not self._navigationToolbar.isVisible() and not menuBar.isVisible(): self.toggleShowNavigationToolbar() def toggleShowStatusBar(self): self.setUpdatesEnabled(False) self._statusBar.setVisible(not self._statusBar.isVisible()) self.setUpdatesEnabled(True) Settings().setValue('Browser-View-Settings/showStatusBar', self._statusBar.isVisible()) def toggleShowBookmarksToolbar(self): self.setUpdatesEnabled(False) self._bookmarksToolbar.setVisible( not self._bookmarksToolbar.isVisible()) self.setUpdatesEnabled(True) Settings().setValue('Browser-View-Settings/showBookmarksToolbar', self._bookmarksToolbar.isVisible()) Settings().setValue('Browser-View-Settings/instantBookmarksToolbar', False) def toggleShowNavigationToolbar(self): self.setUpdatesEnabled(False) self._navigationToolbar.setVisible( not self._navigationToolbar.isVisible()) self.setUpdatesEnabled(True) Settings().setValue('Browser-View-Settings/showNavigationToolbar', self._navigationToolbar.isVisible()) # Make sure we show Navigation Toolbar when Menu Bar is hidden if not self._navigationToolbar.isVisible() and not self.menuBar( ).isVisible(): self.toggleShowMenubar() def toggleTabsOnTop(self, enable): gVar.appSettings.tabsOnTop = enable self._navigationContainer.toggleTabsOnTop(enable) def toggleFullScreen(self): if self._htmlFullScreenView: self.weView().triggerPageAction(QWebEnginePage.ExitFullScreen) return if self.isFullScreen(): self.setWindowState(self.windowState() & ~Qt.WindowFullScreen) else: self.setWindowState(self.windowState() | Qt.WindowFullScreen) def requestHtmlFullScreen(self, view, enable): ''' @param: view TabbedWebView @param: enable bool ''' if enable: self.setWindowState(self.windowState() | Qt.WindowFullScreen) else: self.setWindowState(self.windowState() & ~Qt.WindowFullScreen) if self._sideBar: self._sideBar.setHidden(enable) self._htmlFullScreenView = enable and view or None def loadActionUrl(self, obj=None): if not obj: obj = self.sender() action = obj if isinstance(action, QAction): self.loadAddress(action.data().toUrl()) def loadActionUrlInNewTab(self, obj=None): if not obj: obj = self.sender() action = obj if isinstance(action, QAction): self.loadAddress(action.data().toUrl(), const.NT_SelectedTabAtTheEnd) def bookmarkPage(self): view = self.weView() BookmarksTools.addBookmarkDialog(self, view.url(), view.title()) def bookmarkAllTabs(self): BookmarksTools.bookmarkAllTabsDialog(self, self._tabWidget) def loadAddress(self, url): webView = self.weView() if webView.webTab().isPinned(): index = self._tabWidget.addViewByUrl( url, gVar.appSettings.newTabPosition) self.weView(index).setFocus() else: webView.setFocus() webView.loadByReq(LoadRequest(url)) def showSource(self, view=None): if not view: view = self.weView() if not view: return view.showSource() # private Q_SLOTS: def _openLocation(self): if self.isFullScreen(): self.showNavigationWithFullScreen() self.locationBar().setFocus() self.locationBar().selectAll() def _openFile(self): fileTypes = ("%s(*.html *.htm *.shtml *.shtm *.xhtml);;" "%s(*.png *.jpg *.jpeg *.bmp *.gif *.svg *.tiff);;" "%s(*.txt);;" "%s(*.*)") fileTypes %= ("HTML files", "Image files", "Text files", "All files") filePath = gVar.appTools.getOpenFileName("MainWindow-openFile", self, "Open file...", QDir.homePath(), fileTypes) if filePath: self.loadAddress(QUrl.fromLocalFile(filePath)) def _closeWindow(self): if const.OS_MAC: self.close() return if gVar.app.windowCount() > 1: self.close() def _closeTab(self): # Don't close pinned tabs with keyboard shortcuts (Ctrl+w, Ctrl+F4) webView = self.weView() if webView and not webView.webTab().isPinned(): self._tabWidget.requestCloseTab() def _loadSettings(self): settings = Settings() # Url settings settings.beginGroup('Web-URL-Settings') self._homepage = settings.value('homepage', 'app:start', type=QUrl) settings.endGroup() # Browser Window settings settings.beginGroup('Browser-View-Settings') showStatusBar = settings.value('showStatusBar', False) showBookmarksToolbar = settings.value('showBookmarksToolbar', False) showNavigationToolbar = settings.value('showNavigationToolbar', True) showMenuBar = settings.value('showMenuBar', False) # Make sure both menubar and navigationbar are not hidden if not showNavigationToolbar: showMenuBar = True settings.setValue('showMenubar', True) settings.endGroup() settings.beginGroup('Shortcuts') self._useTabNumberShortcuts = settings.value('useTabNumberShortcuts', True) self._useSpeedDialNumberShortcuts = settings.value( 'useSpeedDialNumberShortcuts', True) self._useSingleKeyShortcuts = settings.value('useSingleKeyShortcuts', False) settings.endGroup() settings.beginGroup('Web-Browser-Settings') quitAction = self._mainMenu.action('Standard/Quit') if settings.value('closeAppWithCtrlQ', True): quitAction.setShortcut( gVar.appTools.actionShortcut(QKeySequence.Quit, QKeySequence('Ctrl+Q'))) else: quitAction.setShortcut(QKeySequence()) settings.endGroup() self._statusBarVisible = showStatusBar self.statusBar().setVisible(not self.isFullScreen() and showStatusBar) self._bookmarksToolbar.setVisible(showBookmarksToolbar) self._navigationToolbar.setVisible(showNavigationToolbar) if not const.OS_MACOS: self._menuBarVisible = showMenuBar self.menuBar().setVisible(not self.isFullScreen() and showMenuBar) showSuperMenu = self.isFullScreen() or not showMenuBar # TODO: debug code showSuperMenu = True self._navigationToolbar.setSuperMenuVisible(showSuperMenu) def _postLaunch(self): # noqa C901 self._loadSettings() addTab = True startUrl = QUrl() from .MainApplication import MainApplication afterLaunch = gVar.app.afterLaunch() if afterLaunch == MainApplication.OpenBlankPage: startUrl = QUrl() elif afterLaunch == MainApplication.OpenSpeedDial: startUrl = QUrl('app:speeddial') elif afterLaunch in (MainApplication.OpenHomePage, MainApplication.RestoreSession, MainApplication.SelectSession): startUrl = QUrl(self._homepage) if not gVar.app.isTestModeEnabled(): self.show() if self._windowType == const.BW_FirstAppWindow: if gVar.app.isStartingAfterCrash(): addTab = False startUrl.clear() self._tabWidget.addViewByUrl(QUrl('app:restore'), const.NT_CleanSelectedTabAtTheEnd) elif afterLaunch in (MainApplication.SelectSession, MainApplication.RestoreSession): addTab = self._tabWidget.count() <= 0 elif self._windowType in (const.BW_NewWindow, const.BW_MacFirstWindow): addTab = True elif self._windowType == const.BW_OtherRestoredWindow: addTab = False if not self._startUrl.isEmpty(): startUrl = QUrl(self._startUrl) addTab = True if self._startTab: addTab = False self._tabWidget.addViewByTab(self._startTab, const.NT_SelectedTab) if self._startPage: addTab = False self._tabWidget.addViewByUrl(QUrl()) self.weView().setPage(self._startPage) if addTab: self._tabWidget.addViewByUrl(startUrl, const.NT_CleanSelectedTabAtTheEnd) if not startUrl or startUrl == 'app:speeddial': self.locationBar().setFocus() # Someting went really wrong .. add one tab if self._tabWidget.count() <= 0: self._tabWidget.addViewByUrl(self._homepage, const.NT_SelectedTabAtTheEnd) gVar.app.plugins().emitMainWindowCreated(self) self.startingCompleted.emit() self.raise_() self.activateWindow() self._updateStartupFocus() def _webSearch(self): self._navigationToolbar.webSearchBar().setFocus() self._navigationToolbar.webSearchBar().selectAll() def _searchOnPage(self): webView = self.weView() if webView and webView.webTab(): searchText = webView.page().selectedText() if '\n' not in searchText: webView.webTab().showSearchToolBar(searchText) else: webView.webTab().showSearchToolBar() def _changeEncoding(self): action = self.sender() if action: encoding = action.data() gVar.app.webSettings().setDefaultTextEncoding(encoding) Settings().setValue('Web-Browser-Settings/DefaultEncoding', encoding) self.weView().reload() def _printPage(self): self.weView().printPage() def _saveSettings(self): if gVar.app.isPrivate(): return settings = Settings() settings.beginGroup('Browser-View-Settings') settings.setValue('WindowGeometry', self.saveGeometry()) state = self._saveUiState() for key, val in state.items(): settings.setValue(key, val) settings.endGroup() def _hideNavigationSlot(self): view = self.weView() mouseInView = view and view.underMouse() if self.isFullScreen() and mouseInView: self._navigationContainer.hide() # private # override def event(self, event): ''' @param: event QEvent ''' if event.type() == QEvent.WindowStateChange: e = event assert (isinstance(e, QWindowStateChangeEvent)) if not (e.oldState() & Qt.WindowFullScreen) and ( self.windowState() & Qt.WindowFullScreen): # Enter fullscreen self._statusBarVisible = self._statusBar.isVisible() if not const.OS_MACOS: self._menuBarVisible = self.menuBar().isVisible() self.menuBar().hide() self._statusBar.hide() self._navigationContainer.hide() self._navigationToolbar.enterFullScreen() # Show main menu button since menubar is hidden self._navigationToolbar.setSuperMenuVisible(True) elif (e.oldState() & Qt.WindowFullScreen ) and not (self.windowState() & Qt.WindowFullScreen): # Leave fullscreen self._statusBar.setVisible(self._statusBarVisible) if not const.OS_MACOS: self.menuBar().setVisible(self._menuBarVisible) self._navigationContainer.show() self._navigationToolbar.setSuperMenuVisible( not self._menuBarVisible) self._navigationToolbar.leaveFullScreen() self._htmlFullScreenView = None if self._hideNavigationTimer: self._hideNavigationTimer.stop() return super().event(event) # override def resizeEvent(self, event): ''' @param: event QResizeEvent ''' self._bookmarksToolbar.setMaximumWidth(self.width()) super().resizeEvent(event) # override def keyPressEvent(self, event): # noqa C901 ''' @param: event QKeyEvent ''' if gVar.app.plugins().processKeyPress(const.ON_BrowserWindow, self, event): return number = -1 # TabbedWebView view = self.weView() evtKey = event.key() if evtKey == Qt.Key_Back: if view: view.back() event.accept() elif evtKey == Qt.Key_Forward: if view: view.forward() event.accept() elif evtKey == Qt.Key_Stop: if view: view.stop() event.accept() elif evtKey in (Qt.Key_Reload, Qt.Key_Refresh): if view: view.reload() event.accept() elif evtKey == Qt.Key_HomePage: self.goHome() event.accept() elif evtKey == Qt.Key_Favorites: gVar.app.browsingLibrary().showBookmarks(self) event.accept() elif evtKey == Qt.Key_Search: self.searchOnPage() event.accept() elif evtKey in (Qt.Key_F6, Qt.Key_OpenUrl): self.openLocation() event.accept() elif evtKey == Qt.Key_History: self.showHistoryManager() event.accept() elif evtKey == Qt.Key_AddFavorite: self.bookmarkPage() event.accept() elif evtKey == Qt.Key_News: self.action("Tools/RssReader").trigger() event.accept() elif evtKey == Qt.Key_Tools: self.action("Standard/Preferences").trigger() event.accept() elif evtKey == Qt.Key_Tab: if event.modifiers() == Qt.ControlModifier: self._tabWidget.event(event) elif evtKey == Qt.Key_Backtab: if event.modifiers() == Qt.ControlModifier + Qt.ShiftModifier: self._tabWidget.event(event) elif evtKey == Qt.Key_PageDown: if event.modifiers() == Qt.ControlModifier: self._tabWidget.nextTab() event.accept() elif evtKey == Qt.Key_PageUp: if event.modifiers() == Qt.ControlModifier: self._tabWidget.previousTab() event.accept() elif evtKey == Qt.Key_Equal: if view and event.modifiers() == Qt.ControlModifier: view.zoomIn() event.accept() elif evtKey == Qt.Key_I: if event.modifiers() == Qt.ControlModifier: self.action("Tools/SiteInfo").trigger() event.accept() elif evtKey == Qt.Key_U: if event.modifiers() == Qt.ControlModifier: self.action("View/PageSource").trigger() event.accept() elif evtKey == Qt.Key_F: if event.modifiers() == Qt.ControlModifier: self.action("Edit/Find").trigger() event.accept() elif evtKey == Qt.Key_Slash: if self._useSingleKeyShortcuts: self.action("Edit/Find").trigger() event.accept() elif evtKey == Qt.Key_1: number = 1 elif evtKey == Qt.Key_2: number = 2 elif evtKey == Qt.Key_3: number = 3 elif evtKey == Qt.Key_4: number = 4 elif evtKey == Qt.Key_5: number = 5 elif evtKey == Qt.Key_6: number = 6 elif evtKey == Qt.Key_7: number = 7 elif evtKey == Qt.Key_8: number = 8 elif evtKey == Qt.Key_9: number = 9 if number != -1: modifiers = event.modifiers() if modifiers & Qt.AltModifier and self._useTabNumberShortcuts: if number == 9: number = self._tabWidget.count() self._tabWidget.setCurrentIndex(number - 1) event.accept() return if modifiers & Qt.ControlModifier and self._useSpeedDialNumberShortcuts: # QUrl url = gVar.app.plugins().speedDial().urlForShortcut(number - 1) if url.isValid(): self.loadAddress(url) event.accept() return if modifiers == Qt.NoModifier and self._useSingleKeyShortcuts: if number == 1: self._tabWidget.previousTab() if number == 2: self._tabWidget.nextTab() super().keyPressEvent(event) # override def keyReleaseEvent(self, event): ''' @param: event QKeyEvent ''' if gVar.app.plugins().processKeyRelease(const.ON_BrowserWindow, self, event): return evtKey = event.key() if evtKey == Qt.Key_F: if event.modifiers() == Qt.ControlModifier: self.action('Edit/Find').trigger() event.accept() super().keyReleaseEvent(event) # override def closeEvent(self, event): ''' @param: event QCloseEvent ''' if gVar.app.isClosing(): self._saveSettings() return settings = Settings() askOnClose = settings.value('Browser-Tabs-Settings/AskOnClosing', True) from .MainApplication import MainApplication if gVar.app.afterLaunch() in (MainApplication.SelectSession, MainApplication.RestoreSession ) and gVar.app.windowCount() == 1: askOnClose = False if askOnClose and self._tabWidget.normalTabsCount() > 1: dialog = CheckBoxDialog(QMessageBox.Yes | QMessageBox.No, self) dialog.setDefaultButton(QMessageBox.No) dialog.setText( "There are still %s open tabs and your session won't be stored.\n" % self._tabWidget.count() + "Are you sure you want to close this window?") dialog.setCheckBoxText("Don't ask again") dialog.setWindowTitle('There are still open tabs') dialog.setIcon(QMessageBox.Warning) if dialog.exec_() != QMessageBox.Yes: event.ignore() return if dialog.isChecked(): settings.setValue('Browser-Tabs-Settings/AskOnClosing', False) self.aboutToClose.emit() self._saveSettings() gVar.app.closedWindowsManager().saveWindow(self) if gVar.app.windowCount() == 1: gVar.app.quitApplication() event.accept() # == private == def _setupUi(self): settings = Settings() settings.beginGroup('Browser-View-Settings') windowGeometry = settings.value('WindowGeometry', b'') keys = [ ('LocationBarWidth', int), ('WebSearchBarWidth', int), ('SideBarWidth', int), ('WebViewWidth', int), ('SideBar', str), ] uiState = {} for key, typ in keys: if settings.contains(key): uiState[key] = typ(settings.value(key)) settings.endGroup() widget = QWidget(self) widget.setCursor(Qt.ArrowCursor) self.setCentralWidget(widget) self._mainLayout = QVBoxLayout(widget) self._mainLayout.setContentsMargins(0, 0, 0, 0) self._mainLayout.setSpacing(0) self._mainSplitter = QSplitter(self) self._mainSplitter.setObjectName('sidebar-splitter') self._tabWidget = TabWidget(self) self._superMenu = QMenu(self) self._navigationToolbar = NavigationBar(self) self._bookmarksToolbar = BookmarksToolbar(self) self._tabModel = TabModel(self, self) self._tabMruModel = TabMruModel(self, self) self._tabMruModel.setSourceModel(self._tabModel) self._navigationContainer = NavigationContainer(self) self._navigationContainer.addWidget(self._navigationToolbar) self._navigationContainer.addWidget(self._bookmarksToolbar) self._navigationContainer.setTabBar(self._tabWidget.tabBar()) self._mainSplitter.addWidget(self._tabWidget) self._mainSplitter.setCollapsible(0, False) self._mainLayout.addWidget(self._navigationContainer) self._mainLayout.addWidget(self._mainSplitter) self._statusBar = StatusBar(self) self._statusBar.setObjectName('mainwindow-statusbar') self._statusBar.setCursor(Qt.ArrowCursor) self.setStatusBar(self._statusBar) self._progressBar = ProgressBar(self._statusBar) self._ipLabel = QLabel(self) self._ipLabel.setObjectName('statusbar-ip-label') self._ipLabel.setToolTip('IP Address of current page') self._statusBar.addPermanentWidget(self._progressBar) self._statusBar.addPermanentWidget(self.ipLabel()) downloadsButton = DownloadsButton(self) self._statusBar.addButton(downloadsButton) self._navigationToolbar.addToolButton(downloadsButton) desktop = gVar.app.desktop() windowWidth = desktop.availableGeometry().width() / 1.3 windowHeight = desktop.availableGeometry().height() / 1.3 # Let the WM decides where to put new browser window if self._windowType not in (const.BW_FirstAppWindow, const.BW_MacFirstWindow) and \ gVar.app.getWindow(): if const.OS_WIN: # Windows WM places every new window in the middle of screen .. for some reason p = gVar.app.getWindow().geometry().topLeft() p.setX(p.x() + 30) p.setY(p.y() + 30) if not desktop.availableGeometry( gVar.app.getWindow()).contains(p): p.setX( desktop.availableGeometry(gVar.app.getWindow()).x() + 30) p.setY( desktop.availableGeometry(gVar.app.getWindow()).y() + 30) self.setGeometry(QRect(p, gVar.app.getWindow().size())) else: self.resize(gVar.app.getWindow().size()) elif not self.restoreGeometry(windowGeometry): if const.OS_WIN: self.setGeometry( QRect( desktop.availableGeometry(gVar.app.getWindow()).x() + 30, desktop.availableGeometry(gVar.app.getWindow()).y() + 30, windowWidth, windowHeight)) else: self.resize(windowWidth, windowHeight) self._restoreUiState(uiState) # Set some sane minimum width self.setMinimumWidth(300) def _setupMenu(self): if const.OS_MACOS: macMainMenu = None if not macMainMenu: macMainMenu = MainMenu(self, 0) macMainMenu.initMenuBar(QMenuBar(0)) gVar.app.activeWindowChanged.connect(macMainMenu.setWindow) else: macMainMenu.setWindow(self) else: self.setMenuBar(MenuBar(self)) self._mainMenu = MainMenu(self, self) self._mainMenu.initMenuBar(self.menuBar()) self._mainMenu.initSuperMenu(self._superMenu) # Setup other shortcuts reloadBypassCacheAction = QShortcut(QKeySequence('Ctrl+F5'), self) reloadBypassCacheAction2 = QShortcut(QKeySequence('Ctrl+Shift+R'), self) reloadBypassCacheAction.activated.connect(self.reloadBypassCache) reloadBypassCacheAction2.activated.connect(self.reloadBypassCache) closeTabAction = QShortcut(QKeySequence('Ctrl+W'), self) closeTabAction2 = QShortcut(QKeySequence('Ctrl+F4'), self) closeTabAction.activated.connect(self._closeTab) closeTabAction2.activated.connect(self._closeTab) reloadAction = QShortcut(QKeySequence('Ctrl+R'), self) reloadAction.activated.connect(self.reload) openLocationAction = QShortcut(QKeySequence('Alt+D'), self) openLocationAction.activated.connect(self._openLocation) inspectorAction = QShortcut(QKeySequence('F12'), self) inspectorAction.activated.connect(self.toggleWebInspector) restoreClosedWindow = QShortcut(QKeySequence('Ctrl+Shift+N'), self) restoreClosedWindow.activated.connect( gVar.app.closedWindowsManager().restoreClosedWindow) def _updateStartupFocus(self): def _updateStartupFocusCb(): # Scroll to current tab self.tabWidget().tabBar().ensureVisible() # Update focus page = self.weView().page() url = page.requestedUrl() if not self._startPage and not LocationBar.convertUrlToText(url): self.locationBar().setFocus() else: self.weView().setFocus() QTimer.singleShot(500, _updateStartupFocusCb) def _createEncodingAction(self, codecName, activeCodecName, menu): ''' @param: codecName QString @param: activeCodecName QString @param: menu QMenu ''' action = QAction(codecName, menu) action.setData(codecName) action.setCheckable(True) action.triggered.connect(self._changeEncoding) if activeCodecName.lower() == codecName.lower(): action.setChecked(True) return action def _createEncodingSubMenu(self, name, codecNames, menu): ''' @param: name QString @param: codecName QStringList @param: menu QMenu ''' if not codecNames: return codecNames.sort() subMenu = QMenu(name, menu) activeCodecName = gVar.app.webSettings().defaultTextEncoding() group = QActionGroup(subMenu) for codecName in codecNames: act = self._createEncodingAction(codecName, activeCodecName, subMenu) group.addAction(act) subMenu.addAction(act) menu.addMenu(subMenu) def _saveUiState(self): ''' @return: QHash<QStirng, QVariant> ''' self.saveSideBarSettings() state = {} state['LocationBarWidth'] = self._navigationToolbar.splitter().sizes( )[0] state['WebSearchBarWidth'] = self._navigationToolbar.splitter().sizes( )[1] state['SideBarWidth'] = self._sideBarWidth state['WebViewWidth'] = self._webViewWidth state['SideBar'] = self._sideBarManager.activeSideBar() return state def _restoreUiState(self, state): ''' @param: state QHash<QString, QVariant> ''' locationBarWidth = state.get('LocationBarWidth', 480) webSearchBarWidth = state.get('WebSearchBarWidth', 140) self._navigationToolbar.setSplitterSizes(locationBarWidth, webSearchBarWidth) self._sideBarWidth = state.get('SideBarWidth', 250) self._webViewWidth = state.get('WebViewWidth', 2000) if self._sideBar: self._mainSplitter.setSizes( [self._sideBarWidth, self._webViewWidth]) activeSideBar = state.get('SideBar') if not activeSideBar and self._sideBar: self._sideBar.close() else: self._sideBarManager.showSideBar(activeSideBar, False)
class MainWindowGUI(QMainWindow): def __init__(self, refresh_time=30): super().__init__() uic.loadUi( os.path.join(os.path.dirname(os.path.abspath(__file__)), 'designer', 'MainWindow.ui'), self) self.logger = get_logger(name=__name__) self.central_layout = QHBoxLayout(self.centralwidget) self.widget_splitter = QSplitter() self.camera_viewer_widget = CameraViewerWidget() self.analysis_dock_widget = AnalysisDockWidget(self) self.widget_splitter.addWidget(self.camera_viewer_widget) self.widget_splitter.addWidget(self.analysis_dock_widget) self.widget_splitter.setSizes((750, 750)) self.central_layout.addWidget(self.widget_splitter) self.config_widget = ConfigWidget() self.config_tracking_widget = ConfigTrackingWidget() self.refresh_timer = QTimer() self.refresh_timer.timeout.connect(self.update_gui) self.refresh_timer.start(refresh_time) self.showMaximized() self.connect_actions() self.connect_buttons() self.connect_signals() def update_gui(self): self.logger.error('Update gui not defined') def connect_signals(self): self.config_tracking_widget.apply_config.connect( self.update_tracking_config) self.config_widget.apply_config.connect(self.update_config) def connect_buttons(self): self.analysis_dock_widget.button_histogram.clicked.connect( self.calculate_histogram) self.analysis_dock_widget.button_tracks.clicked.connect( self.update_tracks) def connect_actions(self): self.actionClose.triggered.connect(self.safe_close) self.actionLoad_Config.triggered.connect(self.load_config) self.actionSave_Image.triggered.connect(self.save_image) self.actionLoad_Data.triggered.connect(self.load_data) self.actionSnap_Photo.triggered.connect(self.snap) self.actionStart_Movie.triggered.connect(self.start_movie) self.actionStop_Movie.triggered.connect(self.stop_movie) self.actionStart_Continuous_Saves.triggered.connect( self.start_continuous_saves) self.actionStop_Continuous_Saves.triggered.connect( self.stop_continuous_saves) self.actionSet_ROI.triggered.connect(self.set_roi) self.actionClear_ROI.triggered.connect(self.clear_roi) self.actionConfiguration.triggered.connect(self.configure) self.actionToggle_bg_reduction.triggered.connect( self.background_reduction) self.actionStart_Tracking.triggered.connect(self.start_tracking) self.actionStop_Tracking.triggered.connect(self.stop_tracking) self.actionStart_Linking.triggered.connect(self.start_linking) self.actionStop_Linking.triggered.connect(self.stop_linking) self.actionSave_Tracks.triggered.connect(self.start_saving_tracks) self.actionShow_Cheatsheet.triggered.connect(self.show_cheat_sheet) self.actionAbout.triggered.connect(self.show_about) self.actionInitialize_Camera.triggered.connect(self.initialize_camera) self.actionUpdate_Histogram.triggered.connect(self.calculate_histogram) self.actionTracking_Config.triggered.connect( self.config_tracking_widget.show) self.actionConfiguration.triggered.connect(self.config_widget.show) self.actionAdd_Monitor_Point.triggered.connect(self.add_monitor_point) self.actionClear_All.triggered.connect(self.clear_monitor_points) def add_monitor_point(self): self.logger.debug('Add monitor point') def clear_monitor_points(self): self.logger.debug('Clear all monitor points') def initialize_camera(self): self.logger.debug('Initialize Camera') def show_about(self): self.logger.debug('Showing About') def load_config(self): self.logger.debug('Loading config') def snap(self): self.logger.debug('Snapped a photo') def save_image(self): self.logger.debug('Saved an image') def start_movie(self): self.logger.debug('Start a movie') def stop_movie(self): self.logger.error('Stop movie not defined') def start_continuous_saves(self): self.logger.debug('Started continuous saves') def stop_continuous_saves(self): self.logger.error('Stop continuous Saves not implemented') def start_tracking(self): self.logger.debug('Started tracking particles') def stop_tracking(self): self.logger.debug('Stopped tracking particles') def start_saving_tracks(self): self.logger.debug('Started saving tracks') def stop_saving_tracks(self): self.logger.debug('Stopped saving tracks') def start_linking(self): self.logger.debug('Started linking particles') def stop_linking(self): self.logger.debug('Stopped linking') def configure(self): self.logger.debug('Showed the config window') def set_roi(self): self.logger.debug('Setting the ROI') def clear_roi(self): self.logger.debug('Resetting the ROI') def background_reduction(self): self.logger.debug('Setting background reduction') def show_cheat_sheet(self): self.logger.debug('Showing the cheat sheet') def load_data(self): self.logger.debug('Loading data') def safe_close(self): self.logger.debug('Closing the program') self.close() def calculate_histogram(self): self.logger.error('Update Histogram method not defiend') def update_tracks(self): self.logger.error('Update tracks method not defined') def update_tracking_config(self, config): self.logger.error('Update Tracking config method not defined') def update_config(self, config): self.logger.error('Update Config method not defined') def closeEvent(self, *args, **kwargs): self.config_widget.close() self.config_tracking_widget.close() super(MainWindowGUI, self).closeEvent(*args, **kwargs)
def initUI(self): # pg.setConfigOption('background', 'w') self.lblTit = pg.LabelItem(justify='right') #Variables self.data_dir='' self.nom_dir = [] self.numEp=1 self.grafi=[] self.tam=0 self.puntos=0 self.sizes = np.asarray([120, 60, 30, 15]) datos = QVBoxLayout() contain=QSplitter(Qt.Horizontal) ima = QVBoxLayout() self.glw = pg.PlotWidget() btn_data_dir = QPushButton('Load Files') btn_data_dir.clicked.connect(self.openFile) self.lblDataDir=QLabel('') self.lytEpoch = QFormLayout() self.cmbEpoch = QComboBox() self.cmbEpoch.addItem("120") self.cmbEpoch.addItem("60") self.cmbEpoch.addItem("30") self.cmbEpoch.addItem("15") self.lytEpoch.addRow("Epoch size: ", self.cmbEpoch) self.lytFrec = QFormLayout() self.txtFrec = QLineEdit('200') self.lytFrec.addRow("Frecuencia: ",self.txtFrec) btn_do = QPushButton('DO') btn_do.clicked.connect(self.showDialog) self.lytEpo = QFormLayout() self.cmbEpo = QComboBox() self.cmbEpo.setCurrentIndex=1 self.cmbEpo.activated[str].connect(self.graficaX) self.lytEpo.addRow("Número de época: ", self.cmbEpo) datos.addWidget(btn_data_dir) datos.addWidget(self.lblDataDir) datos.addLayout(self.lytEpoch) datos.addLayout(self.lytFrec) datos.addWidget(btn_do) ima.addWidget(self.glw) ima.addLayout(self.lytEpo) bot = QWidget() bot.setLayout(datos) gra = QWidget() gra.setLayout(ima) contain.addWidget(bot) contain.addWidget(gra) self.addWidget(contain)
class MainWinBase(QMainWindow): def __init__(self): super().__init__() self.resize(1024, 720) self.menubar = self.menuBar() self.statusbar = self.statusBar() self.mainTabWidget = QTabWidget() self.actions = {} self.menus = {} self.submenus = {} self.contexMenus = {} self.toolbars = {} self.status = {} self.docks = {} self.documents = {} self.createActions() self.themeCombo = QComboBox() self.createMenubar() self.createContexMenus() self.createToolbars() self.createStatusBar() self.createDocks() self.createMainWidget() self.setupUiActions() def createActions(self): def createAct(text, tip=None, shortcut=None, iconimg=None, checkable=False, slot=None): action = QAction(self.tr(text), self) if iconimg is not None: action.setIcon(QIcon(iconimg)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: tip = self.tr(tip) action.setToolTip(tip) action.setStatusTip(tip) if checkable: action.setCheckable(True) if slot is not None: action.triggered.connect(slot) return action def keys2str(standardkey): return "".join(("(", QKeySequence(standardkey).toString(), ")")) # self.actions["new"] = createAct(self.tr("&New", "&New"), # self.tr("new") + keys2str(QKeySequence.New), QKeySequence.New, # ':appres.img/NewDocument.png') self.actions["import"] = createAct(self.tr("&Import Image"), self.tr("Import Image"), None, ':appres.img/importimage.png') self.actions["replaceimage"] = createAct( self.tr("&Replace Image"), self.tr("Replace Image"), None, ':appres.img/replaceimage.png') self.actions["open"] = createAct( self.tr("&Open Project"), self.tr("Open") + keys2str(QKeySequence.Open), QKeySequence.Open, ':appres.img/open.png') self.actions["save"] = createAct( self.tr("&Save"), self.tr("Save") + keys2str(QKeySequence.Save), QKeySequence.Save, ':appres.img/save.png') self.actions["saveas"] = createAct(self.tr("&Save as..."), self.tr("Save as..."), None, ':appres.img/SaveAs.png') self.actions["export"] = createAct( self.tr("&ExportCurves"), self.tr("Export digitized curves data"), "Ctrl+Alt+E", ':appres.img/export.png') self.actions["close"] = createAct(self.tr("&Close"), self.tr("Close")) self.actions["exit"] = createAct(self.tr("&Exit"), self.tr("Exit"), "Ctrl+Q") self.actions["undo"] = createAct( self.tr("&Undo"), self.tr("Undo") + keys2str(QKeySequence.Undo), QKeySequence.Undo, ':appres.img/undo.png') self.actions["redo"] = createAct( self.tr("&Redo"), self.tr("Redo") + keys2str(QKeySequence.Redo), QKeySequence.Redo, ':appres.img/redo.png') self.actions["cut"] = createAct( self.tr("&Cut"), self.tr("Cut") + keys2str(QKeySequence.Cut), QKeySequence.Cut, ':appres.img/cut.png') self.actions["copy"] = createAct( self.tr("&Copy"), self.tr("Copy") + keys2str(QKeySequence.Copy), QKeySequence.Copy, ':appres.img/copy.png') self.actions["paste"] = createAct( self.tr("&Paste"), self.tr("Paste") + keys2str(QKeySequence.Paste), QKeySequence.Paste, ':appres.img/paste.png') self.actions["zoomin"] = createAct(self.tr("&ZoomIn"), self.tr("Zoom In"), "Ctrl++", ':appres.img/zoomin.png') self.actions["zoomout"] = createAct(self.tr("&ZoomOut"), self.tr("Zoom Out"), "Ctrl+-", ':appres.img/zoomout.png') self.actions["showgrid"] = createAct(self.tr("Show Axes &Grid"), self.tr("Show AxesGrid"), None, ':appres.img/grid.png', checkable=True) self.actions["showgrid"].setChecked(True) self.actions["select"] = createAct(self.tr("Select Mode"), self.tr("Select Mode"), None, ':appres.img/select.png', checkable=True) self.actions["axesx"] = createAct(self.tr("Set x axis postions"), self.tr("Set x axis position"), None, ':appres.img/axesx.png', checkable=True) self.actions["axesy"] = createAct(self.tr("Set y axis postions"), self.tr("Set y axis position"), None, ':appres.img/axesy.png', checkable=True) self.actions["curve"] = createAct(self.tr("&AddCurve"), self.tr("Add Curve"), None, ':appres.img/curve.png', checkable=True) self.actions["del"] = createAct(self.tr("&del point or axis"), self.tr("delete"), QKeySequence.Delete, ':appres.img/delete.png') self.actions["addcurve"] = createAct(self.tr("add a new curve"), self.tr("add a new curve"), None, ':appres.img/new.png') self.actions["renamecurve"] = createAct( self.tr("change curve name"), self.tr("change current curve name"), None, ':appres.img/edit.png') self.actions["delcurve"] = createAct(self.tr("&del curve"), self.tr("delete selected curve"), QKeySequence.Delete, ':appres.img/delete.png') self.actions["scalegraph"] = createAct( self.tr("set graph image scale"), self.tr("scale the graph image(background)"), None, ":appres.img/resizeimage.png") self.actions["gridsetting"] = createAct( self.tr("grid settings"), self.tr("set grid range and step"), None, ":appres.img/gridsetting.png") # self.actions["DisableQss"] = createAct(self.tr("&DisableQss"), self.tr("DisableQss"), checkable=True) # self.actions["DisableQss"].setChecked(False) # self.actions["ShowColor"] = createAct(self.tr("&ColorPanel"), # self.tr("ShowColorPanel"), # None, # ":appres.img/color.png", # checkable=True) # self.actions["ShowColor"].setChecked(True) self.actions["showcurves"] = createAct( self.tr("&CurvePanel"), self.tr("ShowCurvesPanel"), None, ":appres.img/view2col2right.png", checkable=True) self.actions["showfit"] = createAct( self.tr("Show Fit&&Interpolation Panel"), self.tr("ShowCurve Fit&Interpolation Panel"), None, None, checkable=True) self.actions["showcurves"].setChecked(True) self.actions["hidegraph"] = createAct( self.tr("Hide Graph"), self.tr("Hide the graph(background image)"), None, None, checkable=True) self.actions["showoriginalgraph"] = createAct( self.tr("Original Graph"), self.tr("Show the original graph(background image)"), None, None, checkable=True) self.actions["config"] = createAct(self.tr("&Config"), self.tr("settings"), None, ":appres.img/config.png") self.actions["about"] = createAct(self.tr("&About"), self.tr("About")) self.actions["help"] = createAct(self.tr("&Help"), self.tr("Help")) # self.exitAct.triggered.connect(qApp.exit)#等价于qApp.quit self.actions["exit"].triggered.connect(self.close) def createMenubar(self): self.menus["File"] = QMenu(self.tr("&File")) self.menus["Edit"] = QMenu(self.tr("&Edit")) self.menus["Digit"] = QMenu(self.tr("&Digit")) self.menus["View"] = QMenu(self.tr("&View")) self.menus["Config"] = QMenu(self.tr("&Config")) self.menus["Help"] = QMenu(self.tr("&Help")) editMenu = QMenu(self.tr("Text"), self.menus["Edit"]) editMenu.setIcon(QIcon(":appres.img/edit_whitepage.png")) editMenu.addAction(self.actions["undo"]) editMenu.addAction(self.actions["redo"]) # editMenu.addSeparator() # editMenu.addAction(self.actions["cut"]) # editMenu.addAction(self.actions["copy"]) # editMenu.addAction(self.actions["paste"]) self.menus["File"].addAction(self.actions["import"]) self.menus["File"].addAction(self.actions["replaceimage"]) self.menus["File"].addAction(self.actions["open"]) self.menus["File"].addAction(self.actions["save"]) self.menus["File"].addAction(self.actions["saveas"]) self.menus["File"].addAction(self.actions["export"]) self.menus["File"].addAction(self.actions["close"]) self.menus["File"].addSeparator() self.menus["File"].addAction(self.actions["exit"]) self.menus["Edit"].addAction(self.actions["undo"]) self.menus["Edit"].addAction(self.actions["redo"]) self.menus["Digit"].addAction(self.actions["select"]) self.menus["Digit"].addAction(self.actions["axesx"]) self.menus["Digit"].addAction(self.actions["axesy"]) self.menus["Digit"].addAction(self.actions["curve"]) self.menus["Digit"].addSeparator() self.menus["Digit"].addAction(self.actions["addcurve"]) self.menus["Digit"].addAction(self.actions["renamecurve"]) self.menus["Digit"].addAction(self.actions["del"]) self.menus["View"].addAction(self.actions["zoomin"]) self.menus["View"].addAction(self.actions["zoomout"]) self.menus["View"].addSeparator() background = QMenu(self.tr("Graph Background"), self.menus["View"]) background.addAction(self.actions["hidegraph"]) background.addAction(self.actions["showoriginalgraph"]) self.menus["View"].addMenu(background) self.menus["View"].addAction(self.actions["showgrid"]) self.menus["View"].addSeparator() self.menus["View"].addAction(self.actions["showcurves"]) self.menus["View"].addAction(self.actions["showfit"]) self.menus["View"].addSeparator() self.menus["Config"].addAction(self.actions["config"]) self.menus["Help"].addAction(self.actions["help"]) self.menus["Help"].addSeparator() self.menus["Help"].addAction(self.actions["about"]) for m in self.menus.values(): self.menubar.addMenu(m) def createContexMenus(self): self.contexMenus["Edit"] = QMenu(self.tr("Edit")) self.contexMenus["Edit"].addAction(self.actions["cut"]) self.contexMenus["Edit"].addAction(self.actions["copy"]) self.contexMenus["Edit"].addAction(self.actions["paste"]) def createToolbars(self): themeLabel = QLabel(self.tr("Theme ")) # self.themeCombo = QComboBox() themeLabel.setToolTip(self.tr("Using system style.")) self.themeCombo.setToolTip(self.tr("Select system style.")) self.themeCombo.addItems(QStyleFactory.keys()) self.themeCombo.setMinimumWidth(105) theme = QApplication.style().objectName() self.themeCombo.setCurrentIndex( self.themeCombo.findText(theme, Qt.MatchFixedString)) # self.themeCombo.setEnabled(False) # themeCombo.activated[str].connect(qApp.setStyle) # themeCombo.currentTextChanged.connect(qApp.setStyle) # checkbox.stateChanged.connect(self.themeCombo.setEnabled) # checkbox.stateChanged.connect(lambda x:self.actions["DisableQss"].setChecked(checkbox.isChecked())) self.toolbars["Main"] = QToolBar(self.tr("Main", "toolbar")) self.toolbars["Main"].addWidget(themeLabel) self.toolbars["Main"].addWidget(self.themeCombo) self.toolbars["File"] = QToolBar(self.tr("File")) self.toolbars["File"].addAction(self.actions["import"]) self.toolbars["File"].addAction(self.actions["open"]) self.toolbars["File"].addAction(self.actions["save"]) # self.toolbars["File"].addAction(self.actions["saveas"]) self.toolbars["File"].addAction(self.actions["export"]) self.toolbars["Edit"] = QToolBar(self.tr("Edit")) self.toolbars["Edit"].addAction(self.actions["undo"]) self.toolbars["Edit"].addAction(self.actions["redo"]) self.toolbars["Edit"].addAction(self.actions["del"]) self.toolbars["Digitize"] = QToolBar(self.tr("Digitize")) self.toolbars["Digitize"].addAction(self.actions["select"]) self.toolbars["Digitize"].addAction(self.actions["axesx"]) self.toolbars["Digitize"].addAction(self.actions["axesy"]) self.toolbars["Digitize"].addAction(self.actions["curve"]) self.toolbars["Display"] = QToolBar(self.tr("Display")) self.toolbars["Display"].addAction(self.actions["zoomin"]) self.toolbars["Display"].addAction(self.actions["zoomout"]) self.toolbars["Display"].addAction(self.actions["showgrid"]) self.toolbars["Setting"] = QToolBar(self.tr("Setting")) self.toolbars["Setting"].addAction(self.actions["scalegraph"]) self.toolbars["Setting"].addAction(self.actions["gridsetting"]) self.toolbars["Setting"].addAction(self.actions["config"]) self.toolbars["View"] = QToolBar(self.tr("View")) self.toolbars["View"].addAction(self.actions["showcurves"]) for t in self.toolbars.values(): self.addToolBar(t) def createStatusBar(self): self.statusbar.showMessage(self.tr("Ready")) # self.statusbar.addWidget(QWidget(),1) # self.status["date"] = QLabel() # self.statusbar.addPermanentWidget(self.status["date"]) # self.status["date"].setText(QDate.currentDate().toString()) # self.status["date"].setVisible(False) self.status["point"] = QLabel(self.tr("Point Coordinate: 0,0")) self.status["pixel"] = QLabel(self.tr("Pixel Location: 0,0")) self.status["point"].setMinimumWidth(200) self.status["pixel"].setMinimumWidth(200) # self.status["coding"].setAlignment(Qt.AlignCenter) self.statusbar.addPermanentWidget(self.status["point"]) self.statusbar.addPermanentWidget(self.status["pixel"]) def createDocks(self): self.docks["curves"] = QDockWidget(self.tr("Axes and Curves")) self.docks["curves"].setMinimumSize(QSize(200, 200)) self.docks["curves"].setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self.addDockWidget(Qt.LeftDockWidgetArea, self.docks["curves"]) self.docks["fit"] = FitDockWidget(self.tr("Poly Fit")) self.docks["fit"].setMinimumSize(QSize(200, 200)) self.docks["fit"].setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self.addDockWidget(Qt.RightDockWidgetArea, self.docks["fit"]) #self.tabifyDockWidget(self.docks["curves"], self.docks["fit"]) #self.docks["curves"].raise_() self.docks["fit"].setVisible(False) self.docks["curves"].visibilityChanged.connect( self.actions["showcurves"].setChecked) self.docks["fit"].visibilityChanged.connect( self.actions["showfit"].setChecked) self.docktabwidget = QTabWidget(self.docks["curves"]) self.docks["curves"].setWidget(self.docktabwidget) self.docktabwidget.setTabPosition(QTabWidget.South) self.axesTab = QSplitter(Qt.Vertical) # QScrollArea() self.curveTab = QSplitter(Qt.Vertical) self.docktabwidget.addTab(self.axesTab, "axes") self.docktabwidget.addTab(self.curveTab, "curve") self.docktabwidget.setCurrentIndex(1) self.axesxTable = QTableView() self.axesyTable = QTableView() self.axesTab.addWidget(self.axesxTable) self.axesTab.addWidget(self.axesyTable) self.curveTable = QTableView() self.pointsTable = QTableView() # self.axesTab.setWidgetResizable(True) w = QWidget() lay = QVBoxLayout() lay.setContentsMargins(0, 0, 0, 0) self.curvePanelToolbar = QToolBar(self.curveTab) lay.addWidget(self.curvePanelToolbar) lay.addWidget(self.curveTable) w.setLayout(lay) self.curveTab.addWidget(w) self.curveTab.addWidget(self.pointsTable) self.curvePanelToolbar.addAction(self.actions["addcurve"]) self.curvePanelToolbar.addAction(self.actions["renamecurve"]) self.curvePanelToolbar.addAction(self.actions["delcurve"]) def createMainWidget(self): self.setCentralWidget(self.mainTabWidget) self.mainTabWidget.setTabBarAutoHide(True) def setupUiActions(self): self.actions["showcurves"].triggered.connect( self.docks["curves"].setVisible) self.actions["showfit"].triggered.connect(self.docks["fit"].setVisible) self.themeCombo.currentTextChanged.connect(qApp.setStyle) # misc func def updatePixelCoordStatus(self, ptorx, y=None): if isinstance(ptorx, QPoint) or isinstance(ptorx, QPointF): self.status["pixel"].setText("Pixel Coordinate: {},{}".format( ptorx.x(), ptorx.y())) else: self.status["pixel"].setText("Pixel Coordinate: {},{}".format( ptorx, y)) def updatePointCoordStatus(self, ptorx, y=None): if isinstance(ptorx, QPoint) or isinstance(ptorx, QPointF): self.status["point"].setText( "Point Coordinate: {:.0f},{:.0f}".format(ptorx.x(), ptorx.y())) else: self.status["point"].setText( "Point Coordinate: {:.0f},{:.0f}".format(ptorx, y))
class bridgePanel(QMainWindow, QObject): start = pyqtSignal() stop = pyqtSignal() def __init__(self, app): super().__init__() self.bridgetreasureChest = bridgetreasureChest.bridgetreasureChest() self.app = app self.translate = QCoreApplication.translate self.__v2rayshellVersion = "20180302" self.__windowTitile = "V2Ray-shell" + " " + self.__v2rayshellVersion self.runv2raycore = False self.iconStart = QIcon() self.iconStop = QIcon() self.__iconSize = QSize(32, 32) self.iconStart.addPixmap(QPixmap(filePath + "/icons/start.png"), QIcon.Normal, QIcon.On) self.iconStop.addPixmap(QPixmap(filePath + "/icons/stop.png"), QIcon.Disabled, QIcon.On) self.currentRowRightClicked = False self.v2rayshellTrayIcon = QSystemTrayIcon() self.v2rayshellTrayIcon.setIcon(self.iconStart) self.v2rayshellTrayIcon.show() self.radioButtonGroup = QButtonGroup() self.setV2RayshellLanguage() self.trytimes = self.bridgetreasureChest.getConnectiontrytimes() self.interval = self.bridgetreasureChest.getConnectioninterval() self.proxyTryConnect = proxyTryconnect() if v2rayshellDebug: self.proxyTryConnect.setresetTime(6, 3) else: self.proxyTryConnect.setresetTime(self.interval, self.trytimes) self.labelBridge = (self.translate("bridgePanel", "Start/Stop"), self.translate("bridgePanel", "Host Name"), self.translate("bridgePanel", "Config Name"), self.translate("bridgePanel", "Proxy"), self.translate("bridgePanel", "Time Lag")) self.checkTrayicon = QTimer() self.createBridgePanel() def createBridgePanel(self): self.setWindowTitle(self.__windowTitile) self.setWindowIcon(self.iconStart) menubar = self.menuBar() self.statusBar() self.actionNewV2rayConfigFile = QAction( self.translate("bridgePanel", "Add V2Ray-core Config File"), self) self.actionNewV2rayConfigFile.setShortcut(QKeySequence.New) self.actionNewV2rayConfigFile.setStatusTip( self.translate("bridgePanel", "Add V2Ray-core Config File")) self.actionSaveV2rayshellConfigFile = QAction( self.translate("bridgePanel", "Save V2Ray-shell Config File"), self) self.actionSaveV2rayshellConfigFile.setShortcut(QKeySequence.Save) self.actionSaveV2rayshellConfigFile.setStatusTip( self.translate("bridgePanel", "Save V2Ray-shell Config File")) self.actionReloadV2rayshellConfigFile = QAction( self.translate("bridgePanel", "Open V2Ray-shell Config File"), self) self.actionReloadV2rayshellConfigFile.setShortcut(QKeySequence.Open) self.actionReloadV2rayshellConfigFile.setStatusTip( self.translate("bridgePanel", "Open V2Ray-shell Config File")) self.actionQuitV2rayshellPanel = QAction( self.translate("bridgePanel", "Quit"), self) if sys.platform.startswith('win'): self.actionQuitV2rayshellPanel.setShortcut("Ctrl+Q") else: self.actionQuitV2rayshellPanel.setShortcut(QKeySequence.Quit) self.actionQuitV2rayshellPanel.setStatusTip( self.translate("bridgePanel", "Quit V2Ray-shell")) fileMenu = menubar.addMenu(self.translate("bridgePanel", "&File")) fileMenu.addAction(self.actionNewV2rayConfigFile) fileMenu.addSeparator() fileMenu.addAction(self.actionReloadV2rayshellConfigFile) fileMenu.addAction(self.actionSaveV2rayshellConfigFile) fileMenu.addSeparator() fileMenu.addAction(self.actionQuitV2rayshellPanel) self.texteditBridge = QTextEdit(self) self.texteditBridge.setReadOnly(True) self.tableWidgetBridge = QTableWidget() self.tableWidgetBridge.setRowCount(0) self.tableWidgetBridge.setColumnCount(5) self.tableWidgetBridge.setHorizontalHeaderLabels(self.labelBridge) self.tableWidgetBridge.setSelectionMode( QAbstractItemView.SingleSelection) self.tableWidgetBridge.setSelectionBehavior( QAbstractItemView.SelectRows) self.tableWidgetBridge.setEditTriggers( QAbstractItemView.NoEditTriggers) #self.tableWidgetBridge.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.tableWidgetBridge.setContextMenuPolicy(Qt.CustomContextMenu) self.popMenu = popMenu = QMenu(self.tableWidgetBridge) self.actionpopMenuAddV2rayConfigFile = QAction( self.translate("bridgePanel", "Add V2Ray Config File"), self) self.actionpopMenuAddV2rayConfigFile.setShortcut("Ctrl+n") self.actionpopMenuEditV2rayConfigFile = QAction( self.translate("bridgePanel", "Edit V2Ray Config File"), self) self.actionpopMenuProxyCheckTimeLag = QAction( self.translate("bridgePanel", "Proxy Time Lag Check..."), self) self.actionpopMenuDeleteRow = QAction( self.translate("bridgePanel", "Delete"), self) popMenu.addAction(self.actionpopMenuAddV2rayConfigFile) popMenu.addAction(self.actionpopMenuEditV2rayConfigFile) popMenu.addAction(self.actionpopMenuProxyCheckTimeLag) popMenu.addAction(self.actionpopMenuDeleteRow) self.actionopenV2rayshellPreferencesPanel = QAction( self.translate("bridgePanel", "preferences"), self) self.actionopenV2rayshellPreferencesPanel.setStatusTip( self.translate("bridgePanel", "Setting V2Ray-shell")) optionMenu = menubar.addMenu(self.translate("bridgePanel", "&options")) optionMenu.addAction(self.actionpopMenuProxyCheckTimeLag) optionMenu.addAction(self.actionopenV2rayshellPreferencesPanel) helpMenu = menubar.addMenu(self.translate("bridgePanel", "&help")) self.actioncheckv2raycoreupdate = QAction( self.translate("bridgePanel", "check V2Ray-core update"), self) self.actionv2rayshellBugreport = QAction( self.translate("bridgePanel", "Bug Report"), self) self.actionaboutv2rayshell = QAction( self.translate("bridgePanel", "About"), self) helpMenu.addAction(self.actioncheckv2raycoreupdate) helpMenu.addAction(self.actionv2rayshellBugreport) helpMenu.addAction(self.actionaboutv2rayshell) toolBar = QToolBar() self.actionV2rayStart = QAction(self.translate("bridgePanel", "Start")) self.actionV2rayStart.setIcon(self.style().standardIcon( getattr(QStyle, "SP_MediaPlay"))) self.actionV2rayStop = QAction(self.translate("bridgePanel", "Stop")) self.actionV2rayStop.setIcon(self.style().standardIcon( getattr(QStyle, "SP_MediaStop"))) toolBar.addAction(self.actionV2rayStart) toolBar.addAction(self.actionV2rayStop) self.addToolBar(toolBar) self.trayIconMenu = QMenu() self.v2rayshellTrayIcon.setContextMenu(self.trayIconMenu) self.trayIconMenushowhidePanel = QAction( self.translate("bridgePanel", "Show/Hide")) self.trayIconMenuclosePanel = QAction( self.translate("bridgePanel", "Quit")) self.trayIconMenu.addAction(self.trayIconMenushowhidePanel) self.trayIconMenu.addSeparator() self.trayIconMenu.addAction(self.trayIconMenuclosePanel) self.splitterBridge = QSplitter(Qt.Vertical) self.splitterBridge.addWidget(self.tableWidgetBridge) self.splitterBridge.addWidget(self.texteditBridge) self.setCentralWidget(self.splitterBridge) self.createBridgePanelSignals() self.onloadV2rayshellConfigFile(init=True) self.onv2raycoreStart() self.autocheckv2raycoreUpdate() def createBridgePanelSignals(self): self.actionNewV2rayConfigFile.triggered.connect( self.tableWidgetBridgeAddNewV2rayConfigFile) self.actionReloadV2rayshellConfigFile.triggered.connect( self.onloadV2rayshellConfigFile) self.actionSaveV2rayshellConfigFile.triggered.connect( self.onsaveV2rayshellConfigFile) self.actionopenV2rayshellPreferencesPanel.triggered.connect( self.createBridgepreferencesPanel) self.actionpopMenuAddV2rayConfigFile.triggered.connect( self.tableWidgetBridgeAddNewV2rayConfigFile) self.actionpopMenuEditV2rayConfigFile.triggered.connect( self.oncreatenauticalChartPanel) self.actionpopMenuDeleteRow.triggered.connect( self.tableWidgetBridgeDelete) self.actionpopMenuProxyCheckTimeLag.triggered.connect( self.onproxyserverTimeLagTest) self.actioncheckv2raycoreupdate.triggered.connect( self.onopenv2rayupdatePanel) self.actionv2rayshellBugreport.triggered.connect(self.bugReportPanel) self.actionQuitV2rayshellPanel.triggered.connect(self.close) self.actionV2rayStart.triggered.connect(self.onv2raycoreStart) self.actionV2rayStop.triggered.connect(self.onv2raycoreStop) self.actionaboutv2rayshell.triggered.connect(self.about) self.radioButtonGroup.buttonClicked.connect(self.onradioButtonClicked) self.tableWidgetBridge.cellDoubleClicked.connect( self.ontableWidgetBridgecellDoubleClicked) self.tableWidgetBridge.customContextMenuRequested.connect( self.ontableWidgetBridgeRightClicked) self.v2rayshellTrayIcon.activated.connect(self.restorebridgePanel) self.trayIconMenushowhidePanel.triggered.connect( self.onsystemTrayIconMenushowhidebridgePanel) self.trayIconMenuclosePanel.triggered.connect(self.close) self.proxyTryConnect.reconnectproxy.connect(self.swapNextConfigFile) self.start.connect(self.onupdateinstallFinishedstartNewV2raycore) self.stop.connect(self.onv2raycoreStop) self.checkTrayicon.timeout.connect(self.checkSystemTrayIconStatus) self.checkTrayicon.start(1000 * 60) def checkSystemTrayIconStatus(self): """ maybe auto startup will missing trayicon """ if not self.v2rayshellTrayIcon.isVisible(): self.v2rayshellTrayIcon.show() else: self.checkTrayicon.disconnect() def setV2RayshellLanguage(self): self.trans = QTranslator() language = self.bridgetreasureChest.getLanguage() allLanguages = self.bridgetreasureChest.getAllLanguage() if language and allLanguages: if language in allLanguages: self.trans.load(allLanguages[language]) self.app.installTranslator(self.trans) def autocheckv2raycoreUpdate(self): self.bridgeSingal = (self.start, self.stop) self.v2rayshellautoUpdate = updatePanel.autoCheckUpdate( bridgetreasureChest=self.bridgetreasureChest, bridgeSingal=self.bridgeSingal) def event(self, event): if (event.type() == QEvent.WindowStateChange and self.isMinimized()): self.setWindowFlags(self.windowFlags() & ~Qt.Tool) self.v2rayshellTrayIcon.show() return True else: return super(bridgePanel, self).event(event) def onsystemTrayIconMenushowhidebridgePanel(self): if self.isHidden(): self.showNormal() elif self.isVisible(): self.hide() def restorebridgePanel(self, reason): if reason == QSystemTrayIcon.Trigger: if self.isVisible(): self.hide() elif self.isHidden(): self.showNormal() def close(self): super(bridgePanel, self).close() self.v2rayshellTrayIcon.hide() self.onv2raycoreStop() def closeEvent(self, event): self.close() event.accept() sys.exit(self.app.exec_()) def onv2raycoreStop(self): if (self.runv2raycore): self.runv2raycore.stop.emit() try: # force stop checking proxy time lag del self.autoCheckTimer except Exception: pass def onupdateinstallFinishedstartNewV2raycore(self): self.onloadV2rayshellConfigFile(init=True) self.onv2raycoreStart() def onv2raycoreStart(self): currentActiveRow = False rowCount = self.tableWidgetBridge.rowCount() for i in range(rowCount): currentActiveRow = self.tableWidgetBridge.cellWidget(i, 0) if currentActiveRow.isChecked(): self.texteditBridge.clear() option = self.tableWidgetBridge.item(i, 2) if option: option = '-config="{}" -format=json'.format(option.text()) else: option = "" filePath = self.bridgetreasureChest.getV2raycoreFilePath() if (filePath == False or filePath == ""): filePath = "v2ray" self.runv2raycore = runV2raycore.runV2raycore( outputTextEdit=self.texteditBridge, v2rayPath=filePath, v2rayOption=option, bridgetreasureChest=self.bridgetreasureChest) self.runv2raycore.start.emit() self.autocheckProxy(i) break else: del currentActiveRow def autocheckProxy(self, row): # TODO """ Frequent access to the server may cause suspicion of DDOS attacks, which may put the VPS server at risk. """ enableAutoCheck = self.bridgetreasureChest.getConnectionEnable() if (enableAutoCheck): self.proxyStatus = proxyTest.proxyStatus() self.autoCheckTimer = QTimer() invervalTime = self.bridgetreasureChest.getConnectioninterval() timeout = self.bridgetreasureChest.getConnectiontimeout() proxyAddress = self.getProxyAddressFromTableWidget(row) if proxyAddress: self.autoCheckTimer.timeout.connect( lambda: self.startCheckProxy(timeout=timeout, proxyAddress=proxyAddress, row=row, proxyStatus=self.proxyStatus)) self.bridgetreasureChest.setProxy(proxyAddress) if v2rayshellDebug: self.autoCheckTimer.start(6000) else: self.autoCheckTimer.start(1000 * invervalTime) self.autoCheckTimer.singleShot( 100, lambda: self.startCheckProxy(timeout=timeout, proxyAddress=proxyAddress, row=row, proxyStatus=self.proxyStatus)) def setTableWidgetTimelag(self, row, proxyStatus): newlabelTimelag = self.setlabelTimeLagColor(proxyStatus) oldlabelTimelag = self.tableWidgetBridge.cellWidget(row, 4) del oldlabelTimelag self.tableWidgetBridge.setCellWidget(row, 4, newlabelTimelag) self.tableWidgetBridge.resizeColumnsToContents() def startCheckProxy(self, timeout, proxyAddress, row, proxyStatus): if (proxyAddress): proxyStatus.clear() proxyStatus.signal.connect( lambda: self.setTableWidgetTimelag(row, proxyStatus)) self.proxy = proxyTest.proxyTest(proxyprotocol=proxyAddress[0], proxyhostname=proxyAddress[1], proxyhostport=int( proxyAddress[2]), getproxyStatus=proxyStatus, timeout=int(timeout)) def setlabelTimeLagColor(self, proxyStatus=False): labelTimeLag = QLabel() if (proxyStatus and not proxyStatus.getProxyError()): labelFont = QFont() labelFont.setPointSize(12) labelFont.setBold(True) labelTimeLag.setFont(labelFont) forestGreen = "QLabel {color: rgb(34, 139, 34)}" darkOrange = "QLabel {color: rgb(255, 140, 0)}" red = "QLabel {color: rgb(194,24,7)}" if (proxyStatus.getElapsedTime() < 260): labelTimeLag.setStyleSheet(forestGreen) elif (proxyStatus.getElapsedTime() > 420): labelTimeLag.setStyleSheet(red) else: labelTimeLag.setStyleSheet(darkOrange) labelTimeLag.setText("{} ms".format( str(proxyStatus.getElapsedTime()))) return labelTimeLag elif (proxyStatus and proxyStatus.getProxyError()): labelTimeLag.setText("{}:{}".format( proxyStatus.getProxyErrorString(), proxyStatus.getProxyErrorCode())) self.proxyTryConnect.trytimesDecrease() return labelTimeLag def swapNextConfigFile(self): self.onv2raycoreStop() try: self.trytimes = self.bridgetreasureChest.getConnectiontrytimes() self.interval = self.bridgetreasureChest.getConnectioninterval() self.proxyTryConnect.stopperiodicCheckProxyStatus() if v2rayshellDebug: self.proxyTryConnect.setresetTime(6, 3) else: self.proxyTryConnect.setresetTime(self.interval, self.trytimes) except Exception: self.proxyTryConnect.setresetTime(60, 3) if (self.bridgetreasureChest.connectionisSwitch()): ### swap next row's configFile buttons = self.radioButtonGroup.buttons() buttonsNumber = len(buttons) activeRow = False for i in range(buttonsNumber): if buttons[i].isChecked(): buttons[i].setChecked(False) if i == buttonsNumber - 1: buttons[0].setChecked(True) activeRow = 0 break else: buttons[i + 1].setChecked(True) activeRow = i + 1 break ### change the row icons for i in range(buttonsNumber): widget = self.tableWidgetBridge.cellWidget(i, 0) if (widget): widget.setIcon(self.iconStop) widget.setIconSize(self.__iconSize) if (widget.isChecked()): pass widget = self.tableWidgetBridge.cellWidget(activeRow, 0) if widget: widget.setIcon(self.iconStart) widget.setIconSize(self.__iconSize) self.onv2raycoreStart() def onopenv2rayupdatePanel(self): currentActiveRow = False rowCount = self.tableWidgetBridge.rowCount() currentRow = False for i in range(rowCount): currentActiveRow = self.tableWidgetBridge.cellWidget(i, 0) if currentActiveRow.isChecked(): currentRow = i break if (currentActiveRow and currentActiveRow.isChecked()): proxy = self.tableWidgetBridge.item(currentRow, 3) proxy = proxy.text().split(":") protocol = QNetworkProxy.Socks5Proxy if (proxy[0] == "socks"): protocol = QNetworkProxy.Socks5Proxy elif (proxy[0] == "http"): protocol = QNetworkProxy.HttpProxy hostName = proxy[1] hostPort = int(proxy[2]) v2rayAPI = updatePanel.v2rayAPI() self.createupdatePanel = updatePanel.v2rayUpdatePanel( v2rayapi=v2rayAPI, protocol=protocol, proxyhostName=hostName, port=hostPort, bridgetreasureChest=self.bridgetreasureChest) self.createupdatePanel.createPanel() self.createupdatePanel.setAttribute(Qt.WA_DeleteOnClose) self.createupdatePanel.setWindowIcon(self.iconStart) self.createupdatePanel.setWindowTitle( self.translate("bridgePanel", "Check V2Ray-core update")) self.createupdatePanel.resize(QSize(1024, 320)) self.createupdatePanel.move( QApplication.desktop().screen().rect().center() - self.createupdatePanel.rect().center()) self.createupdatePanel.show() self.createupdatePanel.exec_() else: self.noPoxyServerRunning() def ontableWidgetBridgeRightClicked(self, pos): index = self.tableWidgetBridge.indexAt(pos) clickedRow.rightClickedRow = index.row() clickedRow.mousePos = QCursor().pos() self.popMenu.move(QCursor().pos()) self.popMenu.show() def ontableWidgetBridgecellDoubleClicked(self, row, column): if (column == 1): hostName, ok = QInputDialog.getText( self, self.translate("bridgePanel", 'Host Name'), self.translate("bridgePanel", 'Enter Host Name:')) if (ok): self.tableWidgetBridge.setItem(row, column, QTableWidgetItem(str(hostName))) self.tableWidgetBridge.resizeColumnsToContents() elif (column == 2): fileNames = self.onopenV2rayConfigJSONFile() if (fileNames): for fileName in fileNames: self.tableWidgetBridge.setItem( row, column, QTableWidgetItem(str(fileName))) self.tableWidgetBridge.resizeColumnsToContents() elif (column == 3): self.onproxyserverTimeLagTest() elif (column == 4): self.onproxyserverTimeLagTest() def getProxyAddressFromTableWidget(self, row): proxy = self.tableWidgetBridge.item(row, 3) try: proxy = proxy.text().split(":") except Exception: return False if (proxy[0] == "socks"): proxy[0] = QNetworkProxy.Socks5Proxy elif (proxy[0] == "http"): proxy[0] = QNetworkProxy.HttpProxy if len(proxy) < 3: return False else: return proxy def onproxyserverTimeLagTest(self): proxyStatus = proxyTest.proxyStatus() """ right clicked mouse button pop a menu check proxy """ currentActiveRow = False rowCount = self.tableWidgetBridge.rowCount() currentRow = False for i in range(rowCount): currentActiveRow = self.tableWidgetBridge.cellWidget(i, 0) if currentActiveRow.isChecked(): currentRow = i break if (currentActiveRow and currentActiveRow.isChecked()): proxy = self.getProxyAddressFromTableWidget(currentRow) protocol = proxy[0] hostName = proxy[1] hostPort = int(proxy[2]) proxy = proxyTest.proxyTestPanel(proxyhostname=hostName, proxyhostport=hostPort, proxyprotocol=protocol, getproxyStatus=proxyStatus) proxy.createproxyTestPanel() proxy.setAttribute(Qt.WA_DeleteOnClose) proxy.setWindowTitle( self.translate("bridgePanel", "Proxy Time Lag Check")) proxy.setWindowIcon(self.iconStart) proxy.resize(QSize(600, 480)) proxy.move(QApplication.desktop().screen().rect().center() - proxy.rect().center()) proxy.show() proxy.exec_() else: self.noPoxyServerRunning() def noPoxyServerRunning(self): warningPanel = QDialog() warningPanel.setAttribute(Qt.WA_DeleteOnClose) warningPanel.setWindowTitle(self.translate("bridgePanel", "Warnnig...")) warningPanel.setWindowIcon(self.iconStop) labelMsg = QLabel( self.translate( "bridgePanel", "There no any server is running, \n[File]->[Add V2Ray-core Config File] (Ctrl+n) add a config.json." )) vbox = QVBoxLayout() vbox.addWidget(labelMsg) warningPanel.setLayout(vbox) warningPanel.move(QApplication.desktop().screen().rect().center() - warningPanel.rect().center()) warningPanel.open() warningPanel.exec_() def getProxyAddressFromJSONFile(self, filePath): from bridgehouse.editMap.port import treasureChest, openV2rayJSONFile tempTreasureChest = treasureChest.treasureChest() openV2rayJSONFile.openV2rayJSONFile( filePath, tempTreasureChest, disableLog=True).initboundJSONData() inbound = tempTreasureChest.getInbound() if (inbound): protocol = inbound["protocol"] ipAddress = inbound["listen"] port = inbound["port"] if (protocol == "socks" or protocol == "http"): return "{}:{}:{}".format(protocol, ipAddress, port) else: return False else: return False def onradioButtonClicked(self, e): rowCount = self.tableWidgetBridge.rowCount() #radioButtonClickedRow = 0 for i in range(rowCount): widget = self.tableWidgetBridge.cellWidget(i, 0) if (widget): widget.setIcon(self.iconStop) widget.setIconSize(self.__iconSize) if (widget.isChecked()): #radioButtonClickedRow = i pass e.setIcon(self.iconStart) e.setIconSize(self.__iconSize) def onloadV2rayshellConfigFile(self, init=False): """ when the script first start, and auto load v2ray-shell config file. """ if init: self.settingv2rayshelltableWidget() else: def openV2rayshellConfigFile(): options = QFileDialog.Options() filePath, _ = QFileDialog.getOpenFileName( self, self.translate("bridgePanel", "Open V2Ray-sehll Config File"), "", "V2Ray-shell config file (*.v2rayshell)", options=options) if (filePath): self.bridgetreasureChest.clear() self.tableWidgetBridge.setRowCount(0) self.bridgetreasureChest.initbridgeJSONData( v2rayshellConfigFileName=filePath) self.settingv2rayshelltableWidget() openV2rayshellConfigFile() def onopenV2rayConfigJSONFile(self): """ open a new v2ray config file to tabelWidget """ options = QFileDialog.Options() filePaths, _ = QFileDialog.getOpenFileNames( self, self.translate("bridgePanel", "Open V2Ray-core Config File"), "", """ V2Ray config file (*.json);; All File (*);; """, options=options) if (filePaths): return filePaths else: return False def createBridgepreferencesPanel(self): self.createpreferencesPanel = bridgePreference.bridgepreferencesPanel( self.bridgetreasureChest) self.createpreferencesPanel.setAttribute(Qt.WA_DeleteOnClose) self.createpreferencesPanel.createpreferencesPanel() self.createpreferencesPanel.setWindowIcon(self.iconStart) self.createpreferencesPanel.move( QApplication.desktop().screen().rect().center() - self.createpreferencesPanel.rect().center()) self.createpreferencesPanel.open() self.createpreferencesPanel.exec_() def settingv2rayshelltableWidget(self): v2rayConfigFiles = self.bridgetreasureChest.getV2raycoreconfigFiles() if not v2rayConfigFiles: return v2rayConfigFilesNumber = len(v2rayConfigFiles) if (v2rayConfigFilesNumber > 0): self.tableWidgetBridge.setRowCount(0) for i in range(v2rayConfigFilesNumber): try: enable = bool(v2rayConfigFiles[i]["enable"]) hostName = str(v2rayConfigFiles[i]["hostName"]) configFileName = str(v2rayConfigFiles[i]["configFileName"]) except Exception: pass radioButtonStopStart = QRadioButton(self) radioButtonStopStart.setIcon( self.iconStop if not enable else self.iconStart) radioButtonStopStart.setChecked(True if enable else False) radioButtonStopStart.setIconSize(self.__iconSize) self.radioButtonGroup.addButton(radioButtonStopStart) self.tableWidgetBridge.setRowCount(i + 1) self.tableWidgetBridge.setCellWidget(i, 0, radioButtonStopStart) self.tableWidgetBridge.setItem(i, 1, QTableWidgetItem(hostName)) self.tableWidgetBridge.setItem( i, 2, QTableWidgetItem(configFileName)) self.tableWidgetBridge.setItem( i, 3, QTableWidgetItem( self.getProxyAddressFromJSONFile(configFileName))) self.tableWidgetBridge.resizeColumnsToContents() #self.tableWidgetBridge.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) def onsaveV2rayshellConfigFile(self): self.bridgetreasureChest.clearconfigFiles() rowCount = self.tableWidgetBridge.rowCount() for i in range(rowCount): enable = self.tableWidgetBridge.cellWidget(i, 0) if enable and enable.isChecked(): enable = True else: enable = False hostName = self.tableWidgetBridge.item(i, 1) if hostName: hostName = hostName.text() else: hostName = "" config = self.tableWidgetBridge.item(i, 2) if config: config = config.text() else: config = "" self.bridgetreasureChest.setV2raycoreconfigFiles( enable, hostName, configFileName=config) self.bridgetreasureChest.save.emit() def oncreatenauticalChartPanel(self): v2rayConfigFileName = self.tableWidgetBridge.item( clickedRow.rightClickedRow, 2) if (v2rayConfigFileName): nc = nauticalChartPanel.nauticalChartPanel( v2rayConfigFileName.text()) nc.setAttribute(Qt.WA_DeleteOnClose) nc.createPanel() nc.setWindowTitle( self.translate("bridgePanel", "V2Ray config file edit")) nc.setWindowIcon(self.iconStart) nc.setGeometry(0, 0, 1024, 768) # move widget to center nc.move(QApplication.desktop().screen().rect().center() - nc.rect().center()) nc.show() nc.exec_() def tableWidgetBridgeAddNewV2rayConfigFile(self): configFileNames = self.onopenV2rayConfigJSONFile() if (configFileNames): for configFileName in configFileNames: rowCount = self.tableWidgetBridge.rowCount() radioButtonStopStart = QRadioButton(self) radioButtonStopStart.setIcon(self.iconStop) radioButtonStopStart.setIconSize(self.__iconSize) self.radioButtonGroup.addButton(radioButtonStopStart) self.tableWidgetBridge.setRowCount(rowCount + 1) self.tableWidgetBridge.setCellWidget(rowCount, 0, radioButtonStopStart) self.tableWidgetBridge.setItem(rowCount, 1, QTableWidgetItem("")) self.tableWidgetBridge.setItem( rowCount, 2, QTableWidgetItem(configFileName)) self.tableWidgetBridge.setItem( rowCount, 3, QTableWidgetItem( self.getProxyAddressFromJSONFile(configFileName))) self.tableWidgetBridge.resizeColumnsToContents() else: pass def tableWidgetBridgeDelete(self): self.tableWidgetBridge.removeRow(clickedRow.rightClickedRow) def validateV2rayJSONFile(self, JSONData): """ simply validate a V2Ray json file. """ try: JSONData["inbound"] JSONData["outbound"] except KeyError: return False else: return True def about(self): NineteenEightySeven = QLabel( self.translate( "bridgePanel", """Across the Great Wall, we can reach every corner in the world.""" )) ### Crossing the Great Wall to Join the World Timeless = QLabel( self.translate( "bridgePanel", """You weren't thinking about that when you were creating it.\nBecause if you did? You never would have gone through with it.""" )) DwayneRichardHipp = QLabel( self.translate( "bridgePanel", """May you do good and not evil.\nMay you find forgiveness for yourself and forgive others.\nMay you share freely, never taking more than you give.""" )) vbox = QVBoxLayout() vbox.addWidget(NineteenEightySeven) vbox.addWidget(Timeless) vbox.addWidget(DwayneRichardHipp) dialogAbout = QDialog() dialogAbout.setAttribute(Qt.WA_DeleteOnClose) dialogAbout.setWindowTitle( self.translate("bridgePanel", "About V2Ray-shell")) dialogAbout.setWindowIcon(self.iconStart) dialogAbout.move(QApplication.desktop().screen().rect().center() - dialogAbout.rect().center()) dialogAbout.setLayout(vbox) dialogAbout.open() dialogAbout.exec_() def bugReportPanel(self): self.bugReport = bugReport.bugReport() self.bugReport.setAttribute(Qt.WA_DeleteOnClose) self.bugReport.setWindowTitle( self.translate("bridgePanel", "Bug Report")) self.bugReport.setWindowIcon(self.iconStart) self.bugReport.createPanel() self.bugReport.show() self.bugReport.setGeometry(250, 150, 1024, 768)
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.title = 'Convolutional Neural Network' self.left = 300 self.top = 300 self.width = 960 self.height = 560 self.first_run = True self.current_save = None self.running = False self.iteration_stats = [] self.settings = QSettings("Theo Styles", "Convolutional Neural Network") self.img_size = self.settings.value("img_size", 44) self.init_ui() def update_progress(self, amount=0, status="Running"): self.left_area.progressModule.progress.setText(status + " - " + str(amount) + "%") self.left_area.progressModule.progress.setValue(amount) def testing_finished(self, cls_pred): self.running = False self.main_area_reports.focus() for i, prob_array in enumerate(cls_pred): image = self.dataset.testing_images[i] pred_index = np.argmax(prob_array) prob = prob_array[pred_index] labelForDigit = self.dataset.labels[pred_index] for set in self.main_area_neural.sets: if set.name == labelForDigit: item = set.add_image(image) if prob <= 0.5: item.set_important() self.toolbar.enable_action(0, 0) def run_neural_net(self): self.left_area.progressModule.progress.setDefault() self.obj = RunNeuralNet(self.dataset, self.img_size, len(self.main_area_neural.sets)) # no parent! self.thread = QThread() # no parent! self.obj.moveToThread(self.thread) self.obj.one_iteration.connect(self.update_progress) self.obj.testing_finished.connect(self.testing_finished) self.thread.started.connect(self.obj.long_running) self.thread.start() self.toolbar.disable_action(0, 0) def add_toolbar_clicked(self): folder_name = QFileDialog.getExistingDirectory( self, "Select Directory With Testing Images") if folder_name: self.main_area_neural.top_widget.setVisible(True) self.main_area_neural.initial_image_grid_visible = True if self.main_area_neural.empty_label: self.main_area_neural.empty_label.setText( "Now create sets by selecting images and using the + button to the right of the images!" ) self.main_area_neural.initial_image_grid.populate_from_folder( folder_name, self.update_progress) def export_sets(self): sets = self.main_area_neural.sets if len(sets) == 0: ErrorDialog.dialog(self, "There are no sets to export") return folder_name = QFileDialog.getExistingDirectory( self, "Select a directory to export to") if folder_name: self.left_area.progressModule.progress.setDefault() self.obj = SaveLoad(sets=self.main_area_neural.sets, folder_name=folder_name) # no parent! self.thread = QThread() # no parent! self.obj.moveToThread(self.thread) self.obj.one_iteration.connect(self.update_progress) self.thread.started.connect(self.obj.export_sets) self.thread.start() def run_clicked(self): sets = self.main_area_neural.sets if len(sets) == 0: return ErrorDialog.dialog( self, "Please create at least one set before running the neural network" ) if self.running: return ErrorDialog.dialog(self, "The neural network is already running") itemNames = [] itemData = [] setCount = 0 total_incorrect = 0 self.running = True for set in sets: setCount += 1 itemCount = len(set.all_images) total_incorrect += set.incorrectly_classified_local set.incorrectly_classified_local = 0 for index in range(itemCount): item = set.all_images[index] if item == None: continue itemNames.append(set.name) itemData.append(item.imageData) set.clear() self.iteration_stats.append(total_incorrect) self.dataset.add_sets_to_training_data(setCount, itemNames, itemData) if self.first_run or self.main_area_neural.initial_image_grid_visible: all_image_count = self.main_area_neural.initial_image_grid.count() testing_images = [] for index in range(all_image_count): item = self.main_area_neural.initial_image_grid.item(index) if item == None: continue testing_images.append(item.imageData) self.main_area_neural.initial_image_grid.clear() self.main_area_neural.top_widget.setVisible(False) self.main_area_neural.initial_image_grid_visible = False self.dataset.set_testing_data(testing_images) else: self.dataset.new_testing_data() self.first_run = False self.run_neural_net() def finished_opening_sets(self): self.dataset.new_testing_data() self.main_area_reports.focus() def set_iteration_stats(self, iteration_stats): self.iteration_stats = iteration_stats def open_sets(self): fileName, filter = QFileDialog.getOpenFileName( self, 'Open sets save', PathHelpers.getPath("saves"), "Set Files (*.sets)") if fileName: self.current_save = fileName self.main_area_neural.clear_sets() self.left_area.progressModule.progress.setDefault() self.obj = SaveLoad(self.current_save) # no parent! self.thread = QThread() # no parent! self.obj.moveToThread(self.thread) self.obj.one_iteration.connect(self.update_progress) self.obj.create_set.connect(self.main_area_neural.create_new_set) self.obj.add_to_training_set.connect( self.main_area_neural.add_images_to_set) self.obj.add_to_testing_set.connect( self.dataset.add_to_testing_data) self.obj.set_iteration_stats.connect(self.set_iteration_stats) self.obj.set_classified_info.connect( self.main_area_neural.set_classified_for_set) self.obj.finished.connect(self.finished_opening_sets) self.thread.started.connect(self.obj.load_images) self.thread.start() def save_sets_as(self): self.current_save = None self.save_sets() def save_sets(self): if self.current_save: fileName = self.current_save else: fileName, filter = QFileDialog.getSaveFileName( self, 'Save sets', PathHelpers.getPath("saves"), "Set Files (*.sets)") if fileName: sets = self.main_area_neural.sets[:] if self.main_area_neural.trash_set: sets.append(self.main_area_neural.trash_set) self.current_save = fileName self.left_area.progressModule.progress.setDefault() self.obj = SaveLoad( self.current_save, sets, self.dataset.all_testing_images, iteration_stats=self.iteration_stats) # no parent! self.thread = QThread() # no parent! self.obj.moveToThread(self.thread) self.obj.one_iteration.connect(self.update_progress) self.thread.started.connect(self.obj.save_images) self.thread.start() def deleted_set(self, set_name): self.datapanel.delete_training_row(set_name) def added_to_set(self, set_name): self.datapanel.increment_training_table(set_name) def removed_from_set(self, set_name): self.datapanel.decrement_training_table(set_name) def set_testing_amount(self, amount): self.datapanel.set_testing_amount(amount) def switch_to_neural(self): self.left_area.menu.setCurrentRow(0) def switch_to_reports(self): self.left_area.menu.setCurrentRow(1) def switch_to_settings(self): self.left_area.menu.setCurrentRow(2) def menu_changed(self, index): sets = self.main_area_neural.sets[:] if self.main_area_neural.trash_set: sets.append(self.main_area_neural.trash_set) self.main_area_neural.setVisible(False) self.main_area_settings.setVisible(False) self.main_area_reports.setVisible(False) if index == 0: self.main_area_neural.setVisible(True) elif index == 1: self.main_area_reports.setVisible(True) self.main_area_reports.focus(sets, self.iteration_stats) elif index == 2: self.main_area_settings.setVisible(True) self.main_area_settings.changed() def view_all_training(self): sets = self.main_area_neural.sets[:] if self.main_area_neural.trash_set: sets.append(self.main_area_neural.trash_set) self.training_window = TrainingWindow(self, sets) self.training_window.show() def view_all_testing(self): self.testing_window = TestingWindow(self, self.dataset.all_testing_images) self.testing_window.show() def exit_app(self): sys.exit(0) def about_clicked(self): d = QDialog(self) layout = QVBoxLayout() d.setLayout(layout) layout.addWidget( QLabel("Convolutional Neural Network - Created By Theo Styles")) layout.addWidget(QLabel("Credits:")) layout.addWidget( QLabel("Play icon made by Google from www.flaticon.com")) layout.addWidget( QLabel("Plus icon made by Madebyoliver from www.flaticon.com")) layout.addWidget( QLabel("Export icon made by Popcic from www.flaticon.com")) layout.addWidget( QLabel("Up arrow icon made by Google from www.flaticon.com")) layout.addWidget( QLabel("Down arrow icon made by Google from www.flaticon.com")) layout.addWidget( QLabel("Tick icon made by Eleonor Wang from www.flaticon.com")) d.setWindowTitle("About") d.exec_() def init_ui(self): self.settings = QSettings("Theo Styles", "Convolutional Neural Network") self.settings.setValue("test", 1) self.dataset = DataSet(self.img_size) self.dataset.test_set_changed.connect(self.set_testing_amount) qss_file = open( PathHelpers.getPath("GUI/Stylesheets/default.qss")).read() self.setStyleSheet(qss_file) self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.main_grid = QSplitter() self.main_grid.setObjectName("verticalSplitter") self.main_grid.setContentsMargins(0, 0, 0, 0) self.right_layout = QVBoxLayout() self.right_widget = QWidget() self.right_widget.setLayout(self.right_layout) self.right_grid = QSplitter() self.right_grid.setObjectName("verticalSplitter") self.right_layout.setContentsMargins(0, 0, 0, 0) self.right_layout.setSpacing(0) self.right_grid.setContentsMargins(0, 0, 0, 0) self.right_stacking = QWidget() self.right_stacking_grid = QGridLayout() self.right_stacking.setLayout(self.right_stacking_grid) self.right_grid.addWidget(self.right_stacking) self.right_stacking_grid.setContentsMargins(0, 0, 0, 0) self.right_stacking_grid.setSpacing(0) self.main_area_neural = NeuralNetSection() self.main_area_neural.added_to_set.connect(self.added_to_set) self.main_area_neural.removed_from_set.connect(self.removed_from_set) self.main_area_neural.deleted_set.connect(self.deleted_set) self.right_stacking_grid.addWidget(self.main_area_neural, 0, 0) self.main_area_settings = SettingsSection() self.right_stacking_grid.addWidget(self.main_area_settings, 0, 0) self.main_area_settings.setVisible(False) self.main_area_reports = ReportsSection(self.main_area_neural.sets, self.iteration_stats) self.right_stacking_grid.addWidget(self.main_area_reports, 0, 0) self.main_area_reports.setVisible(False) self.datapanel = DataInfoPanel() self.datapanel.clicked_training_view_all_sig.connect( self.view_all_training) self.datapanel.clicked_testing_view_all_sig.connect( self.view_all_testing) self.right_grid.addWidget(self.datapanel) self.right_grid.setStretchFactor(0, 10) self.right_grid.setStretchFactor(1, 11) self.left_area = MenuPanel() self.left_area.selectedItem.connect(self.menu_changed) self.toolbar = ToolbarPanel() self.toolbar.run_clicked.connect(self.run_clicked) self.toolbar.add_clicked.connect(self.add_toolbar_clicked) self.toolbar.export_clicked.connect(self.export_sets) self.right_layout.addWidget(self.toolbar) self.right_layout.addWidget(self.right_grid) self.main_grid.addWidget(self.left_area) self.main_grid.addWidget(self.right_widget) self.setCentralWidget(self.main_grid) self.main_grid.setStretchFactor(0, 6) self.main_grid.setStretchFactor(1, 10) save_action = QAction("&Save", self) save_action.setShortcut("Ctrl+S") save_action.setStatusTip('Save the current sets') save_action.triggered.connect(self.save_sets) save_action_as = QAction("&Save As", self) save_action_as.setStatusTip('New save for the current sets') save_action_as.triggered.connect(self.save_sets_as) open_action = QAction("&Open", self) open_action.setShortcut("Ctrl+O") open_action.setStatusTip('Open a sets save file') open_action.triggered.connect(self.open_sets) exit_action = QAction("&Exit", self) exit_action.setStatusTip('Exit the application') exit_action.triggered.connect(self.exit_app) menubar = self.menuBar() file_menu = menubar.addMenu('&File') file_menu.addAction(open_action) file_menu.addAction(save_action) file_menu.addAction(save_action_as) file_menu.addAction(exit_action) neural_action = QAction("&Neural Net", self) neural_action.setStatusTip('View the neural network') neural_action.triggered.connect(self.switch_to_neural) reports_action = QAction("&Reports", self) reports_action.setStatusTip('View reports and statistics') reports_action.triggered.connect(self.switch_to_reports) settings_action = QAction("&Settings", self) settings_action.setStatusTip('View settings') settings_action.triggered.connect(self.switch_to_settings) view_menu = menubar.addMenu('&View') view_menu.addAction(neural_action) view_menu.addAction(reports_action) view_menu.addAction(settings_action) import_action = QAction("&Import folder", self) import_action.setStatusTip('Import a folder of images') import_action.triggered.connect(self.add_toolbar_clicked) export_action = QAction("&Export sets", self) export_action.setStatusTip('Export sets to folder') export_action.triggered.connect(self.export_sets) settings_action = QAction("&Settings", self) settings_action.setStatusTip('View settings') settings_action.triggered.connect(self.switch_to_settings) tools_menu = menubar.addMenu('&Tools') tools_menu.addAction(import_action) tools_menu.addAction(export_action) run_action = QAction("&Run Neural Network", self) run_action.setStatusTip('Start running the neural network') run_action.triggered.connect(self.run_clicked) run_menu = menubar.addMenu('&Run') run_menu.addAction(run_action) about_action = QAction("&About", self) about_action.setStatusTip('About the application') about_action.triggered.connect(self.about_clicked) help_menu = menubar.addMenu('&Help') help_menu.addAction(about_action) self.show()
def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) # 在初始化之前设置pg,因为初始化会写死配置,无法在更改 # pg.setConfigOption('foreground', 'd') # 使曲线看起来光滑 pg.setConfigOptions(antialias=True) # 设置文字的字体 font = QFont() font.setFamily("Microsoft Yahei") font.setPointSize(11) self.setMinimumHeight(750) self.setMinimumWidth(1000) # self.setFixedSize(1000, 750) # 统一设置按钮的字体 btn_list = [] # 设置题目和状态栏 self.setWindowTitle("心电平台检测") # 设置状态栏 self.status = self.statusBar() self.status.showMessage("检测~") # 整体布局 pagelayout = QVBoxLayout() # 顶层按钮布局 top = QFrame(self) top.setFrameShape(QFrame.StyledPanel) btn_layout = QHBoxLayout(top) self.data_com = QComboBox() delegate = QStyledItemDelegate() self.data_com.setItemDelegate(delegate) self.data_com.addItem("选择心电数据") self.data_com.setFixedSize(200, 40) self.data_com.setFont(font) set_btn = QPushButton("设置") help_btn = QPushButton("帮助") save_btn = QPushButton("存储") back_btn = QPushButton("回放") fig_btn = QPushButton("截图") patient_table_btn = QPushButton("病例表") self.stop_btn = QPushButton("暂停") btn_list.append(set_btn) btn_list.append(help_btn) btn_list.append(save_btn) btn_list.append(back_btn) btn_list.append(self.stop_btn) btn_list.append(fig_btn) btn_list.append(patient_table_btn) btn_layout.addWidget(self.data_com) btn_layout.addWidget(set_btn) btn_layout.addWidget(help_btn) btn_layout.addWidget(save_btn) btn_layout.addWidget(self.stop_btn) btn_layout.addWidget(back_btn) btn_layout.addWidget(fig_btn) btn_layout.addWidget(patient_table_btn) for btn in btn_list: btn.setFont(font) btn.setFixedSize(100, 40) # 以此统计病人数量 self.patient = 0 for i in range(0, 10): self.patient += 1 self.data_com.addItem(str(100 + i)) # 底层布局 bottom = QFrame(self) bottom.setFrameShape(QFrame.StyledPanel) self.bottom_layout = QStackedLayout(bottom) # 1. 绘图区域 plot_widget = QWidget(bottom) plot_layout = QHBoxLayout() win = pg.GraphicsLayoutWidget() self.p = win.addPlot() self.p.getAxis("bottom").tickFont = font self.p.getAxis("left").tickFont = font # 背景透明 win.setBackground(background=None) plot_layout.addWidget(win) plot_widget.setLayout(plot_layout) self.bottom_layout.addWidget(plot_widget) # 2. 帮助文档 help_widget = QWidget(bottom) help_layout = QHBoxLayout() self.help_text = QTextEdit() self.help_text.setReadOnly(True) help_layout.addWidget(self.help_text) help_widget.setLayout(help_layout) self.bottom_layout.addWidget(help_widget) help_btn.clicked.connect(self.show_help) # 3. 设置 set_widget = QWidget(bottom) set_layout = QVBoxLayout() theme_layout = QHBoxLayout() self.theme_white_radio = QRadioButton("白色主题") self.theme_white_radio.setFixedWidth(120) self.theme_black_radio = QRadioButton("黑色主题") theme_label = QLabel("主题颜色选择") theme_label.setFixedWidth(120) theme_layout.addWidget(theme_label) theme_layout.addWidget(self.theme_white_radio) theme_layout.addWidget(self.theme_black_radio) line_width_layout = QHBoxLayout() line_width = QLabel("设置线宽(范围1-4)") line_width.setFixedWidth(150) line_width_layout.addWidget(line_width) self.line_width_spin = QSpinBox() self.line_width_spin.setMinimum(1) self.line_width_spin.setMaximum(4) line_width_layout.addWidget(self.line_width_spin) set_layout.addLayout(theme_layout) set_layout.addLayout(line_width_layout) set_widget.setLayout(set_layout) self.bottom_layout.addWidget(set_widget) self.theme_white_radio.toggled.connect(self.change_status) self.theme_black_radio.toggled.connect(self.change_status) set_btn.clicked.connect(self.set_) # 暂停与启动的切换 self.stop_btn.clicked.connect(self.stop_) # 截图功能 fig_btn.clicked.connect(self.save_fig) # 回放功能 back_btn.clicked.connect(self.back_show) # 保存数据功能 save_widget = QWidget(bottom) save_layout = QHBoxLayout() save_label = QLabel("请选择保存数据的区间") save_label.setFixedHeight(40) self.left_interval = QLineEdit() self.left_interval.setFixedHeight(40) self.left_interval.setPlaceholderText("起始点,左区间") self.right_interval = QLineEdit() self.right_interval.setFixedHeight(40) self.right_interval.setPlaceholderText("终止点,右区间") save_confirm_btn = QPushButton("确认") save_confirm_btn.setFixedHeight(40) save_layout.addWidget(save_label) save_layout.addWidget(self.left_interval) save_layout.addWidget(self.right_interval) save_layout.addWidget(save_confirm_btn) save_widget.setLayout(save_layout) save_btn.clicked.connect(self.save_widget_) save_confirm_btn.clicked.connect(self.save_data) self.bottom_layout.addWidget(save_widget) # 病例表的填写 table_widget = QWidget(bottom) table_layout = QHBoxLayout() self.patient_table = QTableWidget() self.patient_table.setColumnCount(9) self.patient_table.setRowCount(self.patient) self.patient_table.setHorizontalHeaderLabels([ '标号', '年龄', '性别', '用药', '房性早博', '室性早博', '心室融合心博', '右束支传导阻塞心博', '左束支传导阻塞心博' ]) # self.patient_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.patient_table.resizeColumnsToContents() self.patient_table.verticalHeader().setVisible(False) table_layout.addWidget(self.patient_table) table_widget.setLayout(table_layout) self.bottom_layout.addWidget(table_widget) patient_table_btn.clicked.connect(self.show_table) # 设置最终的窗口布局与控件------------------------------------- splitter = QSplitter(Qt.Vertical) splitter.addWidget(top) splitter.addWidget(bottom) widget = QWidget() pagelayout.addWidget(splitter) widget.setLayout(pagelayout) self.setCentralWidget(widget) # 计时器 当时间到了就出发绘图函数 self.timer = QTimer() self.timer.timeout.connect(self.update) # 记录当前用户 self.people = "" # 当用户改变时出发函数 重新绘图 self.data_com.currentIndexChanged.connect(self.show_ecg1) self.data_com.view().pressed.connect(self.show_ecg) # 读取数据的标志 self.flag = 0 # 帮助文档的标志 self.help = 0 # 暂停的标志 self.stop = 0
class MainWindow(QMainWindow): """Pyspread main window""" gui_update = pyqtSignal(dict) def __init__(self, filepath: str = None, reset_settings: bool = False): """ :param filepath: File path for inital file to be opened :param reset_settings: Ignore stored `QSettings` and use defaults """ super().__init__() self._loading = True self.settings = Settings(self, reset_settings=reset_settings) self.workflows = Workflows(self) self.undo_stack = QUndoStack(self) self.refresh_timer = QTimer() self._init_widgets() self.main_window_actions = MainWindowActions(self) self._init_window() self._init_toolbars() self.settings.restore() if self.settings.signature_key is None: self.settings.signature_key = genkey() # Update recent files in the file menu self.menuBar().file_menu.history_submenu.update() # Update toolbar toggle checkboxes self.update_action_toggles() # Update the GUI so that everything matches the model cell_attributes = self.grid.model.code_array.cell_attributes attributes = cell_attributes[self.grid.current] self.on_gui_update(attributes) self._loading = False self._previous_window_state = self.windowState() # Open initial file if provided by the command line if filepath is not None: if self.workflows.filepath_open(filepath): self.workflows.update_main_window_title() else: msg = "File '{}' could not be opened.".format(filepath) self.statusBar().showMessage(msg) def _init_window(self): """Initialize main window components""" self.setWindowTitle(APP_NAME) self.setWindowIcon(Icon.pyspread) self.safe_mode_widget = QSvgWidget(str(IconPath.warning), self) msg = "%s is in safe mode.\nExpressions are not evaluated." % APP_NAME self.safe_mode_widget.setToolTip(msg) self.statusBar().addPermanentWidget(self.safe_mode_widget) self.safe_mode_widget.hide() # Disable the approve fiel menu button self.main_window_actions.approve.setEnabled(False) self.setMenuBar(MenuBar(self)) def resizeEvent(self, event: QEvent): """Overloaded, aborts on self._loading :param event: Resize event """ if self._loading: return super(MainWindow, self).resizeEvent(event) def closeEvent(self, event: QEvent = None): """Overloaded, allows saving changes or canceling close :param event: Any QEvent """ if event: event.ignore() self.workflows.file_quit() # has @handle_changed_since_save decorator def _init_widgets(self): """Initialize widgets""" self.widgets = Widgets(self) self.entry_line = Entryline(self) self.grid = Grid(self) self.macro_panel = MacroPanel(self, self.grid.model.code_array) self.main_splitter = QSplitter(Qt.Vertical, self) self.setCentralWidget(self.main_splitter) self.main_splitter.addWidget(self.entry_line) self.main_splitter.addWidget(self.grid) self.main_splitter.addWidget(self.grid.table_choice) self.main_splitter.setSizes([self.entry_line.minimumHeight(), 9999, 20]) self.macro_dock = QDockWidget("Macros", self) self.macro_dock.setObjectName("Macro Panel") self.macro_dock.setWidget(self.macro_panel) self.addDockWidget(Qt.RightDockWidgetArea, self.macro_dock) self.macro_dock.installEventFilter(self) self.gui_update.connect(self.on_gui_update) self.refresh_timer.timeout.connect(self.on_refresh_timer) def eventFilter(self, source: QWidget, event: QEvent) -> bool: """Overloaded event filter for handling QDockWidget close events Updates the menu if the macro panel is closed. :param source: Source widget of event :param event: Any QEvent """ if event.type() == QEvent.Close \ and isinstance(source, QDockWidget) \ and source.windowTitle() == "Macros": self.main_window_actions.toggle_macro_panel.setChecked(False) return super().eventFilter(source, event) def _init_toolbars(self): """Initialize the main window toolbars""" self.main_toolbar = MainToolBar(self) self.macro_toolbar = MacroToolbar(self) self.find_toolbar = FindToolbar(self) self.format_toolbar = FormatToolbar(self) self.addToolBar(self.main_toolbar) self.addToolBar(self.macro_toolbar) self.addToolBar(self.find_toolbar) self.addToolBarBreak() self.addToolBar(self.format_toolbar) def update_action_toggles(self): """Updates the toggle menu check states""" self.main_window_actions.toggle_main_toolbar.setChecked( self.main_toolbar.isVisibleTo(self)) self.main_window_actions.toggle_macro_toolbar.setChecked( self.macro_toolbar.isVisibleTo(self)) self.main_window_actions.toggle_format_toolbar.setChecked( self.format_toolbar.isVisibleTo(self)) self.main_window_actions.toggle_find_toolbar.setChecked( self.find_toolbar.isVisibleTo(self)) self.main_window_actions.toggle_entry_line.setChecked( self.entry_line.isVisibleTo(self)) self.main_window_actions.toggle_macro_panel.setChecked( self.macro_dock.isVisibleTo(self)) @property def safe_mode(self) -> bool: """Returns safe_mode state. In safe_mode cells are not evaluated.""" return self.grid.model.code_array.safe_mode @safe_mode.setter def safe_mode(self, value: bool): """Sets safe mode. This triggers the safe_mode icon in the statusbar. If safe_mode changes from True to False then caches are cleared and macros are executed. :param value: Safe mode """ if self.grid.model.code_array.safe_mode == bool(value): return self.grid.model.code_array.safe_mode = bool(value) if value: # Safe mode entered self.safe_mode_widget.show() # Enable approval menu entry self.main_window_actions.approve.setEnabled(True) else: # Safe_mode disabled self.safe_mode_widget.hide() # Disable approval menu entry self.main_window_actions.approve.setEnabled(False) # Clear result cache self.grid.model.code_array.result_cache.clear() # Execute macros self.macro_panel.on_apply() def on_print(self): """Print event handler""" # Create printer printer = QPrinter(mode=QPrinter.HighResolution) # Get print area self.print_area = PrintAreaDialog(self, self.grid).area if self.print_area is None: return # Create print dialog dialog = QPrintDialog(printer, self) if dialog.exec_() == QPrintDialog.Accepted: self.on_paint_request(printer) def on_preview(self): """Print preview event handler""" # Create printer printer = QPrinter(mode=QPrinter.HighResolution) # Get print area self.print_area = PrintAreaDialog(self, self.grid).area if self.print_area is None: return # Create print preview dialog dialog = PrintPreviewDialog(printer) dialog.paintRequested.connect(self.on_paint_request) dialog.exec_() def on_paint_request(self, printer: QPrinter): """Paints to printer :param printer: Target printer """ painter = QPainter(printer) option = QStyleOptionViewItem() painter.setRenderHints(QPainter.SmoothPixmapTransform | QPainter.SmoothPixmapTransform) page_rect = printer.pageRect() rows = list(self.workflows.get_paint_rows(self.print_area)) columns = list(self.workflows.get_paint_columns(self.print_area)) if not rows or not columns: return zeroidx = self.grid.model.index(0, 0) zeroidx_rect = self.grid.visualRect(zeroidx) minidx = self.grid.model.index(min(rows), min(columns)) minidx_rect = self.grid.visualRect(minidx) maxidx = self.grid.model.index(max(rows), max(columns)) maxidx_rect = self.grid.visualRect(maxidx) grid_width = maxidx_rect.x() + maxidx_rect.width() - minidx_rect.x() grid_height = maxidx_rect.y() + maxidx_rect.height() - minidx_rect.y() grid_rect = QRectF(minidx_rect.x() - zeroidx_rect.x(), minidx_rect.y() - zeroidx_rect.y(), grid_width, grid_height) self.settings.print_zoom = min(page_rect.width() / grid_width, page_rect.height() / grid_height) with painter_save(painter): painter.scale(self.settings.print_zoom, self.settings.print_zoom) # Translate so that the grid starts at upper left paper edge painter.translate(zeroidx_rect.x() - minidx_rect.x(), zeroidx_rect.y() - minidx_rect.y()) # Draw grid cells self.workflows.paint(painter, option, grid_rect, rows, columns) self.settings.print_zoom = None def on_fullscreen(self): """Fullscreen toggle event handler""" if self.windowState() == Qt.WindowFullScreen: self.setWindowState(self._previous_window_state) else: self._previous_window_state = self.windowState() self.setWindowState(Qt.WindowFullScreen) def on_approve(self): """Approve event handler""" if ApproveWarningDialog(self).choice: self.safe_mode = False def on_clear_globals(self): """Clear globals event handler""" self.grid.model.code_array.result_cache.clear() # Clear globals self.grid.model.code_array.clear_globals() self.grid.model.code_array.reload_modules() def on_preferences(self): """Preferences event handler (:class:`dialogs.PreferencesDialog`) """ data = PreferencesDialog(self).data if data is not None: max_file_history_changed = \ self.settings.max_file_history != data['max_file_history'] # Dialog has been approved --> Store data to settings for key in data: if key == "signature_key" and not data[key]: data[key] = genkey() self.settings.__setattr__(key, data[key]) # Immediately adjust file history in menu if max_file_history_changed: self.menuBar().file_menu.history_submenu.update() def on_dependencies(self): """Dependancies installer (:class:`installer.InstallerDialog`) """ dial = DependenciesDialog(self) dial.exec_() def on_undo(self): """Undo event handler""" self.undo_stack.undo() def on_redo(self): """Undo event handler""" self.undo_stack.redo() def on_toggle_refresh_timer(self, toggled: bool): """Toggles periodic timer for frozen cells :param toggled: Toggle state """ if toggled: self.refresh_timer.start(self.settings.refresh_timeout) else: self.refresh_timer.stop() def on_refresh_timer(self): """Event handler for self.refresh_timer.timeout Called for periodic updates of frozen cells. Does nothing if either the entry_line or a cell editor is active. """ if not self.entry_line.hasFocus() \ and self.grid.state() != self.grid.EditingState: self.grid.refresh_frozen_cells() def _toggle_widget(self, widget: QWidget, action_name: str, toggled: bool): """Toggles widget visibility and updates toggle actions :param widget: Widget to be toggled shown or hidden :param action_name: Name of action from Action class :param toggled: Toggle state """ if toggled: widget.show() else: widget.hide() self.main_window_actions[action_name].setChecked(widget.isVisible()) def on_toggle_main_toolbar(self, toggled: bool): """Main toolbar toggle event handler :param toggled: Toggle state """ self._toggle_widget(self.main_toolbar, "toggle_main_toolbar", toggled) def on_toggle_macro_toolbar(self, toggled: bool): """Macro toolbar toggle event handler :param toggled: Toggle state """ self._toggle_widget(self.macro_toolbar, "toggle_macro_toolbar", toggled) def on_toggle_format_toolbar(self, toggled: bool): """Format toolbar toggle event handler :param toggled: Toggle state """ self._toggle_widget(self.format_toolbar, "toggle_format_toolbar", toggled) def on_toggle_find_toolbar(self, toggled: bool): """Find toolbar toggle event handler :param toggled: Toggle state """ self._toggle_widget(self.find_toolbar, "toggle_find_toolbar", toggled) def on_toggle_entry_line(self, toggled: bool): """Entryline toggle event handler :param toggled: Toggle state """ self._toggle_widget(self.entry_line, "toggle_entry_line", toggled) def on_toggle_macro_panel(self, toggled: bool): """Macro panel toggle event handler :param toggled: Toggle state """ self._toggle_widget(self.macro_dock, "toggle_macro_panel", toggled) def on_manual(self): """Show manual browser""" dialog = ManualDialog(self) dialog.show() def on_tutorial(self): """Show tutorial browser""" dialog = TutorialDialog(self) dialog.show() def on_about(self): """Show about message box""" about_msg_template = "<p>".join(( "<b>%s</b>" % APP_NAME, "A non-traditional Python spreadsheet application", "Version {version}", "Created by:<br>{devs}", "Documented by:<br>{doc_devs}", "Copyright:<br>Martin Manns", "License:<br>{license}", '<a href="https://pyspread.gitlab.io">pyspread.gitlab.io</a>', )) devs = "Martin Manns, Jason Sexauer<br>Vova Kolobok, mgunyho, " \ "Pete Morgan" doc_devs = "Martin Manns, Bosko Markovic, Pete Morgan" about_msg = about_msg_template.format( version=VERSION, license=LICENSE, devs=devs, doc_devs=doc_devs) QMessageBox.about(self, "About %s" % APP_NAME, about_msg) def on_gui_update(self, attributes: CellAttributes): """GUI update that shall be called on each cell change :param attributes: Attributes of current cell """ widgets = self.widgets menubar = self.menuBar() is_bold = attributes.fontweight == QFont.Bold self.main_window_actions.bold.setChecked(is_bold) is_italic = attributes.fontstyle == QFont.StyleItalic self.main_window_actions.italics.setChecked(is_italic) underline_action = self.main_window_actions.underline underline_action.setChecked(attributes.underline) strikethrough_action = self.main_window_actions.strikethrough strikethrough_action.setChecked(attributes.strikethrough) renderer = attributes.renderer widgets.renderer_button.set_current_action(renderer) widgets.renderer_button.set_menu_checked(renderer) freeze_action = self.main_window_actions.freeze_cell freeze_action.setChecked(attributes.frozen) lock_action = self.main_window_actions.lock_cell lock_action.setChecked(attributes.locked) self.entry_line.setReadOnly(attributes.locked) button_action = self.main_window_actions.button_cell button_action.setChecked(attributes.button_cell is not False) rotation = "rotate_{angle}".format(angle=int(attributes.angle)) widgets.rotate_button.set_current_action(rotation) widgets.rotate_button.set_menu_checked(rotation) widgets.justify_button.set_current_action(attributes.justification) widgets.justify_button.set_menu_checked(attributes.justification) widgets.align_button.set_current_action(attributes.vertical_align) widgets.align_button.set_menu_checked(attributes.vertical_align) border_action = self.main_window_actions.border_group.checkedAction() if border_action is not None: icon = border_action.icon() menubar.format_menu.border_submenu.setIcon(icon) self.format_toolbar.border_menu_button.setIcon(icon) border_width_action = \ self.main_window_actions.border_width_group.checkedAction() if border_width_action is not None: icon = border_width_action.icon() menubar.format_menu.line_width_submenu.setIcon(icon) self.format_toolbar.line_width_button.setIcon(icon) if attributes.textcolor is None: text_color = self.grid.palette().color(QPalette.Text) else: text_color = QColor(*attributes.textcolor) widgets.text_color_button.color = text_color if attributes.bgcolor is None: bgcolor = self.grid.palette().color(QPalette.Base) else: bgcolor = QColor(*attributes.bgcolor) widgets.background_color_button.color = bgcolor if attributes.textfont is None: widgets.font_combo.font = QFont().family() else: widgets.font_combo.font = attributes.textfont widgets.font_size_combo.size = attributes.pointsize merge_cells_action = self.main_window_actions.merge_cells merge_cells_action.setChecked(attributes.merge_area is not None)
class MainWindow(QMainWindow): frame = None jupyter_widget = None browser_widget = None addon_list = [] current_addon = None # currently shown addon def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.setWindowTitle(main_window_title) self.setWindowIcon(QIcon(os.path.join(utils.get_exe_folder(), 'appicon.ico'))) self.init_jupyter_widget() self.init_addon_menu() self.init_splitter() self.init_statusbar() self.init_help_menu() self.setCentralWidget(self.frame) def closeEvent(self, event): # close all the plots # plt.close("all") # nothing to close as # all the plots are in # console pass def init_help_menu(self): menubar = self.menuBar() self.__help_menu = menubar.addMenu('Help') action = QAction('User guide', self) self.__help_menu.addAction(action) action.triggered.connect(self.on_help_user_guide) action = QAction('License', self) self.__help_menu.addAction(action) action.triggered.connect(self.on_help_license) action = QAction('About...', self) self.__help_menu.addAction(action) action.triggered.connect(self.on_help_about) def on_help_license(self, q): self.browser_widget.load_page(license_url) def on_help_user_guide(self, q): self.browser_widget.load_page(user_guide_url) def on_help_about(self, q): # main_window_title, app_name, app_version text = (app_name + ' version ' + app_version + '.\nby ' + author + '.') QMessageBox.about(self, main_window_title, text) def init_statusbar(self): self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) 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) def init_jupyter_widget(self): self.jupyter_widget = make_jupyter_widget_with_kernel() def shutdown_kernel(self): print('Shutting down kernel...') self.jupyter_widget.kernel_client.stop_channels() self.jupyter_widget.kernel_manager.shutdown_kernel() def init_addon_menu(self): self.__menubar = self.menuBar() addon_list = addon_data.addon_list self.__addon_menu = self.__menubar.addMenu('Addons') for addon_group in addon_list: group_menu = self.__addon_menu.addMenu(addon_group.menu_name) for addon in addon_group.addons: action = QAction(addon.menu_name, self) group_menu.addAction(action) self.inputs_widget = InputsWidget(self, addon) action.triggered.connect(self.inputs_widget.show_itself) self.addon_list.append(self.inputs_widget)
def __init__(self, host, port, path, parent=None): super().__init__(parent) self.path = path self.maze_files = sorted( fname.relative_to(self.path) for fname in self.path.glob('**/*.txt') if fname.is_file()) self.setWindowTitle('Micromouse maze simulator') self.resize(800, 600) self.history = [] self.status = QStatusBar() self.setStatusBar(self.status) self.search = QLineEdit() self.search.textChanged.connect(self.filter_mazes) self.files = QListWidget() self.files.currentItemChanged.connect(self.list_value_changed) self.graphics = GraphicsLayoutWidget() viewbox = self.graphics.addViewBox() viewbox.setAspectLocked() self.maze = MazeItem() viewbox.addItem(self.maze) self.slider = QSlider(QtCore.Qt.Horizontal) self.slider.setSingleStep(1) self.slider.setPageStep(10) self.slider.setTickPosition(QSlider.TicksAbove) self.slider.valueChanged.connect(self.slider_value_changed) self.reset() files_layout = QVBoxLayout() files_layout.setContentsMargins(0, 0, 0, 0) files_layout.addWidget(self.search) files_layout.addWidget(self.files) files_widget = QWidget() files_widget.setLayout(files_layout) graphics_layout = QVBoxLayout() graphics_layout.setContentsMargins(0, 0, 0, 0) graphics_layout.addWidget(self.graphics) graphics_layout.addWidget(self.slider) graphics_widget = QWidget() graphics_widget.setLayout(graphics_layout) central_splitter = QSplitter() central_splitter.addWidget(files_widget) central_splitter.addWidget(graphics_widget) main_layout = QVBoxLayout() main_layout.addWidget(central_splitter) main_layout.setContentsMargins(4, 4, 4, 4) main_widget = QWidget() main_widget.setLayout(main_layout) self.setCentralWidget(main_widget) self.filter_mazes('') self.context = zmq.Context() self.reply = self.context.socket(zmq.PUSH) self.reply.connect('inproc://reply') self.thread = QtCore.QThread() self.zeromq_listener = ZMQListener(self.context, host=host, port=port) self.zeromq_listener.moveToThread(self.thread) self.thread.started.connect(self.zeromq_listener.loop) self.zeromq_listener.message.connect(self.signal_received) QtCore.QTimer.singleShot(0, self.thread.start)
def __init__(self, persepolis_setting): super().__init__() # MainWindow self.persepolis_setting = persepolis_setting # add support for other languages locale = str(self.persepolis_setting.value('settings/locale')) QLocale.setDefault(QLocale(locale)) self.translator = QTranslator() if self.translator.load(':/translations/locales/ui_' + locale, 'ts'): QCoreApplication.installTranslator(self.translator) # set ui direction ui_direction = self.persepolis_setting.value('ui_direction') if ui_direction == 'rtl': self.setLayoutDirection(Qt.RightToLeft) elif ui_direction in 'ltr': self.setLayoutDirection(Qt.LeftToRight) icons = ':/' + \ str(self.persepolis_setting.value('settings/icons')) + '/' self.setWindowTitle( QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager")) self.setWindowIcon( QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg'))) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) # enable drag and drop self.setAcceptDrops(True) # frame self.frame = QFrame(self.centralwidget) # download_table_horizontalLayout download_table_horizontalLayout = QHBoxLayout() tabels_splitter = QSplitter(Qt.Horizontal) # category_tree self.category_tree_qwidget = QWidget(self) category_tree_verticalLayout = QVBoxLayout() self.category_tree = CategoryTreeView(self) category_tree_verticalLayout.addWidget(self.category_tree) self.category_tree_model = QStandardItemModel() self.category_tree.setModel(self.category_tree_model) category_table_header = [ QCoreApplication.translate("mainwindow_ui_tr", 'Category') ] self.category_tree_model.setHorizontalHeaderLabels( category_table_header) self.category_tree.header().setStretchLastSection(True) self.category_tree.header().setDefaultAlignment(Qt.AlignCenter) # queue_panel self.queue_panel_widget = QWidget(self) queue_panel_verticalLayout_main = QVBoxLayout(self.queue_panel_widget) # queue_panel_show_button self.queue_panel_show_button = QPushButton(self) queue_panel_verticalLayout_main.addWidget(self.queue_panel_show_button) # queue_panel_widget_frame self.queue_panel_widget_frame = QFrame(self) self.queue_panel_widget_frame.setFrameShape(QFrame.StyledPanel) self.queue_panel_widget_frame.setFrameShadow(QFrame.Raised) queue_panel_verticalLayout_main.addWidget( self.queue_panel_widget_frame) queue_panel_verticalLayout = QVBoxLayout(self.queue_panel_widget_frame) queue_panel_verticalLayout_main.setContentsMargins(50, -1, 50, -1) # start_end_frame self.start_end_frame = QFrame(self) # start time start_verticalLayout = QVBoxLayout(self.start_end_frame) self.start_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.start_checkBox) self.start_frame = QFrame(self) self.start_frame.setFrameShape(QFrame.StyledPanel) self.start_frame.setFrameShadow(QFrame.Raised) start_frame_verticalLayout = QVBoxLayout(self.start_frame) self.start_time_qDataTimeEdit = QDateTimeEdit(self.start_frame) self.start_time_qDataTimeEdit.setDisplayFormat('H:mm') start_frame_verticalLayout.addWidget(self.start_time_qDataTimeEdit) start_verticalLayout.addWidget(self.start_frame) # end time self.end_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.end_checkBox) self.end_frame = QFrame(self) self.end_frame.setFrameShape(QFrame.StyledPanel) self.end_frame.setFrameShadow(QFrame.Raised) end_frame_verticalLayout = QVBoxLayout(self.end_frame) self.end_time_qDateTimeEdit = QDateTimeEdit(self.end_frame) self.end_time_qDateTimeEdit.setDisplayFormat('H:mm') end_frame_verticalLayout.addWidget(self.end_time_qDateTimeEdit) start_verticalLayout.addWidget(self.end_frame) self.reverse_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.reverse_checkBox) queue_panel_verticalLayout.addWidget(self.start_end_frame) # limit_after_frame self.limit_after_frame = QFrame(self) # limit_checkBox limit_verticalLayout = QVBoxLayout(self.limit_after_frame) self.limit_checkBox = QCheckBox(self) limit_verticalLayout.addWidget(self.limit_checkBox) # limit_frame self.limit_frame = QFrame(self) self.limit_frame.setFrameShape(QFrame.StyledPanel) self.limit_frame.setFrameShadow(QFrame.Raised) limit_verticalLayout.addWidget(self.limit_frame) limit_frame_verticalLayout = QVBoxLayout(self.limit_frame) # limit_spinBox limit_frame_horizontalLayout = QHBoxLayout() self.limit_spinBox = QDoubleSpinBox(self) self.limit_spinBox.setMinimum(1) self.limit_spinBox.setMaximum(1023) limit_frame_horizontalLayout.addWidget(self.limit_spinBox) # limit_comboBox self.limit_comboBox = QComboBox(self) self.limit_comboBox.addItem("") self.limit_comboBox.addItem("") limit_frame_horizontalLayout.addWidget(self.limit_comboBox) limit_frame_verticalLayout.addLayout(limit_frame_horizontalLayout) # limit_pushButton self.limit_pushButton = QPushButton(self) limit_frame_verticalLayout.addWidget(self.limit_pushButton) # after_checkBox self.after_checkBox = QtWidgets.QCheckBox(self) limit_verticalLayout.addWidget(self.after_checkBox) # after_frame self.after_frame = QtWidgets.QFrame(self) self.after_frame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.after_frame.setFrameShadow(QtWidgets.QFrame.Raised) limit_verticalLayout.addWidget(self.after_frame) after_frame_verticalLayout = QVBoxLayout(self.after_frame) # after_comboBox self.after_comboBox = QComboBox(self) self.after_comboBox.addItem("") after_frame_verticalLayout.addWidget(self.after_comboBox) # after_pushButton self.after_pushButton = QPushButton(self) after_frame_verticalLayout.addWidget(self.after_pushButton) queue_panel_verticalLayout.addWidget(self.limit_after_frame) category_tree_verticalLayout.addWidget(self.queue_panel_widget) # keep_awake_checkBox self.keep_awake_checkBox = QCheckBox(self) queue_panel_verticalLayout.addWidget(self.keep_awake_checkBox) self.category_tree_qwidget.setLayout(category_tree_verticalLayout) tabels_splitter.addWidget(self.category_tree_qwidget) # download table widget self.download_table_content_widget = QWidget(self) download_table_content_widget_verticalLayout = QVBoxLayout( self.download_table_content_widget) self.download_table = DownloadTableWidget(self) download_table_content_widget_verticalLayout.addWidget( self.download_table) tabels_splitter.addWidget(self.download_table_content_widget) self.download_table.setColumnCount(13) self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.download_table.verticalHeader().hide() # hide gid and download dictioanry section self.download_table.setColumnHidden(8, True) self.download_table.setColumnHidden(9, True) download_table_header = [ QCoreApplication.translate("mainwindow_ui_tr", 'File Name'), QCoreApplication.translate("mainwindow_ui_tr", 'Status'), QCoreApplication.translate("mainwindow_ui_tr", 'Size'), QCoreApplication.translate("mainwindow_ui_tr", 'Downloaded'), QCoreApplication.translate("mainwindow_ui_tr", 'Percentage'), QCoreApplication.translate("mainwindow_ui_tr", 'Connections'), QCoreApplication.translate("mainwindow_ui_tr", 'Transfer rate'), QCoreApplication.translate("mainwindow_ui_tr", 'Estimated time left'), 'Gid', QCoreApplication.translate("mainwindow_ui_tr", 'Link'), QCoreApplication.translate("mainwindow_ui_tr", 'First try date'), QCoreApplication.translate("mainwindow_ui_tr", 'Last try date'), QCoreApplication.translate("mainwindow_ui_tr", 'Category') ] self.download_table.setHorizontalHeaderLabels(download_table_header) # fixing the size of download_table when window is Maximized! self.download_table.horizontalHeader().setSectionResizeMode(0) self.download_table.horizontalHeader().setStretchLastSection(True) tabels_splitter.setStretchFactor(0, 3) # category_tree width tabels_splitter.setStretchFactor(1, 10) # ratio of tables's width download_table_horizontalLayout.addWidget(tabels_splitter) self.frame.setLayout(download_table_horizontalLayout) self.verticalLayout.addWidget(self.frame) self.setCentralWidget(self.centralwidget) # menubar self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 600, 24)) self.setMenuBar(self.menubar) fileMenu = self.menubar.addMenu( QCoreApplication.translate("mainwindow_ui_tr", '&File')) editMenu = self.menubar.addMenu( QCoreApplication.translate("mainwindow_ui_tr", '&Edit')) viewMenu = self.menubar.addMenu( QCoreApplication.translate("mainwindow_ui_tr", '&View')) downloadMenu = self.menubar.addMenu( QCoreApplication.translate("mainwindow_ui_tr", '&Download')) queueMenu = self.menubar.addMenu( QCoreApplication.translate("mainwindow_ui_tr", '&Queue')) videoFinderMenu = self.menubar.addMenu( QCoreApplication.translate("mainwindow_ui_tr", 'V&ideo Finder')) helpMenu = self.menubar.addMenu( QCoreApplication.translate("mainwindow_ui_tr", '&Help')) # viewMenu submenus sortMenu = viewMenu.addMenu( QCoreApplication.translate("mainwindow_ui_tr", 'Sort by')) # statusbar self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.showMessage( QCoreApplication.translate("mainwindow_ui_tr", "Persepolis Download Manager")) # toolBar self.toolBar2 = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar2) self.toolBar2.setWindowTitle( QCoreApplication.translate("mainwindow_ui_tr", 'Menu')) self.toolBar2.setFloatable(False) self.toolBar2.setMovable(False) self.toolBar = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.toolBar.setWindowTitle( QCoreApplication.translate("mainwindow_ui_tr", 'Toolbar')) self.toolBar.setFloatable(False) self.toolBar.setMovable(False) #toolBar and menubar and actions self.videoFinderAddLinkAction = QAction( QIcon(icons + 'video_finder'), QCoreApplication.translate("mainwindow_ui_tr", 'Find Video Links'), self, statusTip=QCoreApplication.translate( "mainwindow_ui_tr", 'Download video or audio from Youtube, Vimeo, etc...'), triggered=self.showVideoFinderAddLinkWindow) QShortcut(QKeySequence('Ctrl+I'), self, self.showVideoFinderAddLinkWindow) videoFinderMenu.addAction(self.videoFinderAddLinkAction) self.stopAllAction = QAction(QIcon(icons + 'stop_all'), QCoreApplication.translate( "mainwindow_ui_tr", 'Stop all active downloads'), self, statusTip='Stop all active downloads', triggered=self.stopAllDownloads) downloadMenu.addAction(self.stopAllAction) self.sort_file_name_Action = QAction(QCoreApplication.translate( "mainwindow_ui_tr", 'File name'), self, triggered=self.sortByName) sortMenu.addAction(self.sort_file_name_Action) self.sort_file_size_Action = QAction(QCoreApplication.translate( "mainwindow_ui_tr", 'File size'), self, triggered=self.sortBySize) sortMenu.addAction(self.sort_file_size_Action) self.sort_first_try_date_Action = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'First try date'), self, triggered=self.sortByFirstTry) sortMenu.addAction(self.sort_first_try_date_Action) self.sort_last_try_date_Action = QAction(QCoreApplication.translate( "mainwindow_ui_tr", 'Last try date'), self, triggered=self.sortByLastTry) sortMenu.addAction(self.sort_last_try_date_Action) self.sort_download_status_Action = QAction(QCoreApplication.translate( "mainwindow_ui_tr", 'Download status'), self, triggered=self.sortByStatus) sortMenu.addAction(self.sort_download_status_Action) self.trayAction = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Show system tray icon'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Show/Hide system tray icon"), triggered=self.showTray) self.trayAction.setCheckable(True) viewMenu.addAction(self.trayAction) self.showMenuBarAction = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Show menubar'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show menubar'), triggered=self.showMenuBar) self.showMenuBarAction.setCheckable(True) viewMenu.addAction(self.showMenuBarAction) self.showSidePanelAction = QAction( QCoreApplication.translate("mainwindow_ui_tr", 'Show side panel'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Show side panel'), triggered=self.showSidePanel) self.showSidePanelAction.setCheckable(True) viewMenu.addAction(self.showSidePanelAction) self.minimizeAction = QAction( QIcon(icons + 'minimize'), QCoreApplication.translate("mainwindow_ui_tr", 'Minimize to system tray'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Minimize to system tray"), triggered=self.minMaxTray) QShortcut(QKeySequence('Ctrl+W'), self, self.minMaxTray) viewMenu.addAction(self.minimizeAction) self.addlinkAction = QAction( QIcon(icons + 'add'), QCoreApplication.translate("mainwindow_ui_tr", 'Add New Download Link'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Add New Download Link"), triggered=self.addLinkButtonPressed) QShortcut(QKeySequence('Ctrl+N'), self, self.addLinkButtonPressed) fileMenu.addAction(self.addlinkAction) self.addtextfileAction = QAction( QIcon(icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Import links from text file'), self, statusTip=QCoreApplication.translate( "mainwindow_ui_tr", 'Create a Text file and put links in it.line by line!'), triggered=self.importText) fileMenu.addAction(self.addtextfileAction) self.resumeAction = QAction( QIcon(icons + 'play'), QCoreApplication.translate("mainwindow_ui_tr", 'Resume Download'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Resume Download"), triggered=self.resumeButtonPressed) QShortcut(QKeySequence('Ctrl+R'), self, self.resumeButtonPressed) downloadMenu.addAction(self.resumeAction) self.pauseAction = QAction( QIcon(icons + 'pause'), QCoreApplication.translate("mainwindow_ui_tr", 'Pause Download'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Pause Download"), triggered=self.pauseButtonPressed) QShortcut(QKeySequence('Ctrl+C'), self, self.pauseButtonPressed) downloadMenu.addAction(self.pauseAction) self.stopAction = QAction( QIcon(icons + 'stop'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop Download'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Stop/Cancel Download"), triggered=self.stopButtonPressed) QShortcut(QKeySequence('Ctrl+S'), self, self.stopButtonPressed) downloadMenu.addAction(self.stopAction) self.propertiesAction = QAction( QIcon(icons + 'setting'), QCoreApplication.translate("mainwindow_ui_tr", 'Properties'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Properties"), triggered=self.propertiesButtonPressed) QShortcut(QKeySequence('Ctrl+P'), self, self.propertiesButtonPressed) downloadMenu.addAction(self.propertiesAction) self.progressAction = QAction( QIcon(icons + 'window'), QCoreApplication.translate("mainwindow_ui_tr", 'Progress'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Progress"), triggered=self.progressButtonPressed) QShortcut(QKeySequence('Ctrl+Z'), self, self.progressButtonPressed) downloadMenu.addAction(self.progressAction) self.openFileAction = QAction( QIcon(icons + 'file'), QCoreApplication.translate("mainwindow_ui_tr", 'Open file'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open file'), triggered=self.openFile) fileMenu.addAction(self.openFileAction) self.openDownloadFolderAction = QAction( QIcon(icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open download folder'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Open download folder'), triggered=self.openDownloadFolder) fileMenu.addAction(self.openDownloadFolderAction) self.openDefaultDownloadFolderAction = QAction( QIcon(icons + 'folder'), QCoreApplication.translate("mainwindow_ui_tr", 'Open default download folder'), self, statusTip=QCoreApplication.translate( "mainwindow_ui_tr", 'Open default download folder'), triggered=self.openDefaultDownloadFolder) fileMenu.addAction(self.openDefaultDownloadFolderAction) self.exitAction = QAction( QIcon(icons + 'exit'), QCoreApplication.translate("mainwindow_ui_tr", 'Exit'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", "Exit"), triggered=self.closeEvent) QShortcut(QKeySequence('Ctrl+Q'), self, self.closeEvent) fileMenu.addAction(self.exitAction) self.clearAction = QAction(QIcon(icons + 'multi_remove'), QCoreApplication.translate( "mainwindow_ui_tr", 'Clear download list'), self, statusTip=QCoreApplication.translate( "mainwindow_ui_tr", 'Clear all items in download list'), triggered=self.clearDownloadList) editMenu.addAction(self.clearAction) self.removeSelectedAction = QAction( QIcon(icons + 'remove'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove selected downloads from list'), self, statusTip=QCoreApplication.translate( "mainwindow_ui_tr", 'Remove selected downloads form list'), triggered=self.removeSelected) editMenu.addAction(self.removeSelectedAction) self.removeSelectedAction.setEnabled(False) self.deleteSelectedAction = QAction( QIcon(icons + 'trash'), QCoreApplication.translate("mainwindow_ui_tr", 'Delete selected download files'), self, statusTip=QCoreApplication.translate( "mainwindow_ui_tr", 'Delete selected download files'), triggered=self.deleteSelected) editMenu.addAction(self.deleteSelectedAction) self.deleteSelectedAction.setEnabled(False) self.createQueueAction = QAction( QIcon(icons + 'add_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Create new queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Create new download queue'), triggered=self.createQueue) queueMenu.addAction(self.createQueueAction) self.removeQueueAction = QAction( QIcon(icons + 'remove_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Remove this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Remove this queue'), triggered=self.removeQueue) queueMenu.addAction(self.removeQueueAction) self.startQueueAction = QAction( QIcon(icons + 'start_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Start this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Start this queue'), triggered=self.startQueue) queueMenu.addAction(self.startQueueAction) self.stopQueueAction = QAction( QIcon(icons + 'stop_queue'), QCoreApplication.translate("mainwindow_ui_tr", 'Stop this queue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Stop this queue'), triggered=self.stopQueue) queueMenu.addAction(self.stopQueueAction) self.moveUpSelectedAction = QAction( QIcon(icons + 'multi_up'), QCoreApplication.translate("mainwindow_ui_tr", 'Move up selected items'), self, statusTip=QCoreApplication.translate( "mainwindow_ui_tr", 'Move currently selected items up by one row'), triggered=self.moveUpSelected) queueMenu.addAction(self.moveUpSelectedAction) self.moveDownSelectedAction = QAction( QIcon(icons + 'multi_down'), QCoreApplication.translate("mainwindow_ui_tr", 'Move down selected items'), self, statusTip=QCoreApplication.translate( "mainwindow_ui_tr", 'Move currently selected items down by one row'), triggered=self.moveDownSelected) queueMenu.addAction(self.moveDownSelectedAction) self.preferencesAction = QAction( QIcon(icons + 'preferences'), QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Preferences'), triggered=self.openPreferences, menuRole=5) editMenu.addAction(self.preferencesAction) self.aboutAction = QAction( QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'About'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'About'), triggered=self.openAbout, menuRole=4) helpMenu.addAction(self.aboutAction) self.issueAction = QAction( QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Report an issue'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Report an issue'), triggered=self.reportIssue) helpMenu.addAction(self.issueAction) self.updateAction = QAction( QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Check for newer version'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Check for newer release'), triggered=self.newUpdate) helpMenu.addAction(self.updateAction) self.logAction = QAction( QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Show log file'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.showLog) helpMenu.addAction(self.logAction) self.helpAction = QAction( QIcon(icons + 'about'), QCoreApplication.translate("mainwindow_ui_tr", 'Help'), self, statusTip=QCoreApplication.translate("mainwindow_ui_tr", 'Help'), triggered=self.persepolisHelp) helpMenu.addAction(self.helpAction) self.qmenu = MenuWidget(self) self.toolBar2.addWidget(self.qmenu) # labels self.queue_panel_show_button.setText( QCoreApplication.translate("mainwindow_ui_tr", "Hide options")) self.start_checkBox.setText( QCoreApplication.translate("mainwindow_ui_tr", "Start Time")) self.end_checkBox.setText( QCoreApplication.translate("mainwindow_ui_tr", "End Time")) self.reverse_checkBox.setText( QCoreApplication.translate("mainwindow_ui_tr", "Download bottom of\n the list first")) self.limit_checkBox.setText( QCoreApplication.translate("mainwindow_ui_tr", "Limit Speed")) self.limit_comboBox.setItemText(0, "KiB/s") self.limit_comboBox.setItemText(1, "MiB/s") self.limit_pushButton.setText( QCoreApplication.translate("mainwindow_ui_tr", "Apply")) self.after_checkBox.setText( QCoreApplication.translate("mainwindow_ui_tr", "After download")) self.after_comboBox.setItemText( 0, QCoreApplication.translate("mainwindow_ui_tr", "Shut Down")) self.keep_awake_checkBox.setText( QCoreApplication.translate("mainwindow_ui_tr", "Keep system awake!")) self.keep_awake_checkBox.setToolTip( QCoreApplication.translate( "mainwindow_ui_tr", "<html><head/><body><p>This option is preventing system from going to sleep.\ This is necessary if your power manager is suspending system automatically. </p></body></html>" )) self.after_pushButton.setText( QCoreApplication.translate("mainwindow_ui_tr", "Apply"))
def __init__(self): super().__init__() self.flag=0 self.chatTextField=QLineEdit(self) self.chatTextField.resize(480,100) self.chatTextField.move(10,350) self.btnSend=QPushButton("Send",self) self.btnSend.resize(480,30) self.btnSendFont=self.btnSend.font() self.btnSendFont.setPointSize(15) self.btnSend.setFont(self.btnSendFont) self.btnSend.move(10,460) self.btnSend.setStyleSheet("background-color: #F7CE16") # self.btnSend.clicked.connect(self.send) self.chatBody=QVBoxLayout(self) splitter=QSplitter(QtCore.Qt.Vertical) self.chat = QTextEdit() self.chat.setReadOnly(True) splitter.addWidget(self.chat) splitter.addWidget(self.chatTextField) splitter.setSizes([400,100]) splitter2=QSplitter(QtCore.Qt.Vertical) splitter2.addWidget(splitter) splitter2.addWidget(self.btnSend) splitter2.setSizes([200,10]) self.chatBody.addWidget(splitter2) self.setWindowTitle("Chat") self.resize(500, 500) # class ClientThread(Thread): # def __init__(self,window): # Thread.__init__(self) # self.window=window # def run(self): # host = socket.gethostname() # port = 80 # BUFFER_SIZE = 2000 # global tcpClientA # tcpClientA = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # tcpClientA.connect((host, port)) # while True: # data = tcpClientA.recv(BUFFER_SIZE) # window.chat.append(data.decode("utf-8")) # tcpClientA.close() # if __name__ == '__main__': # app = QApplication(sys.argv) # window = Window() # clientThread=ClientThread(window) # clientThread.start() # window.exec() # sys.exit(app.exec_())
class FTracePanel(QWidget): def __init__(self, app, flags=None, *args, **kwargs): super().__init__(flags, *args, **kwargs) self.app = app self.kernel = app.get_dwarf().get_kernel() self.ftrace = self.kernel.get_ftrace() self.trace_read_dialog = None layout = QVBoxLayout() central_layout = QVBoxLayout() self.options = QSplitter() self.filter_functions = QTextEdit() self.filter_events = QTextEdit() self.options_list = QListWidget() self.setup_options_view() central_layout.addWidget(self.options) self.buttons = QHBoxLayout() self.btn_pause = QPushButton('pause') self.btn_trace = QPushButton('start') self.btn_read = QPushButton('read') self.btn_pause.setEnabled(False) self.btn_pause.clicked.connect(self.pause_clicked) self.btn_trace.clicked.connect(self.trace_clicked) self.btn_read.clicked.connect(self.read_clicked) self.buttons.addWidget(self.btn_pause) self.buttons.addWidget(self.btn_trace) self.buttons.addWidget(self.btn_read) layout.addLayout(self.buttons) layout.addLayout(central_layout) self.setLayout(layout) def append_data(self, data): if self.trace_read_dialog is not None: self.trace_read_dialog.append(data) def disable_options_view(self): self.btn_pause.setEnabled(True) self.btn_trace.setText('stop') self.btn_read.setEnabled(False) self.options_list.setEnabled(False) self.filter_events.setEnabled(False) self.filter_functions.setEnabled(False) def enable_options_view(self): self.btn_pause.setEnabled(False) self.btn_trace.setText('start') self.btn_read.setEnabled(True) self.options_list.setEnabled(True) self.filter_events.setEnabled(True) self.filter_functions.setEnabled(True) def setup_options_view(self): self.options.setOrientation(Qt.Horizontal) self.options.setHandleWidth(1) filter_functions_layout = QVBoxLayout() filter_functions_layout.addWidget(QLabel("Filter functions")) bar = QScrollBar() bar.setFixedHeight(0) bar.setFixedWidth(0) self.filter_functions.setHorizontalScrollBar(bar) self.filter_functions.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.filter_functions.setPlainText(self.ftrace.get_current_filters()) self.filter_functions.setPlaceholderText("*SyS_open*") filter_functions_layout.addWidget(self.filter_functions) filter_events_layout = QVBoxLayout() filter_events_layout.addWidget(QLabel("Filter events")) bar = QScrollBar() bar.setFixedHeight(0) bar.setFixedWidth(0) self.filter_events.setHorizontalScrollBar(bar) self.filter_events.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.filter_events.setPlainText(self.ftrace.get_current_events()) self.filter_events.setPlaceholderText('raw_syscalls:sys_exit\nraw_syscalls:sys_enter') filter_events_layout.addWidget(self.filter_events) filter_functions_widget = QWidget() filter_functions_widget.setLayout(filter_functions_layout) filter_events_widget = QWidget() filter_events_widget.setLayout(filter_events_layout) options_list_layout = QVBoxLayout() options_list_layout.addWidget(QLabel("Options")) for option in self.ftrace.get_options(): if len(option) < 1: continue q = NotEditableListWidgetItem() q.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) if not option.startswith('no'): q.setCheckState(Qt.Checked) q.setText(option) else: q.setCheckState(Qt.Unchecked) q.setText(option[2:]) self.options_list.addItem(q) options_list_layout.addWidget(self.options_list) options_list_widget = QWidget() options_list_widget.setLayout(options_list_layout) self.options.addWidget(filter_functions_widget) self.options.addWidget(filter_events_widget) self.options.addWidget(options_list_widget) def pause_clicked(self): if self.ftrace.state == FTrace.STATE_TRACING: self.ftrace.pause() self.btn_read.setEnabled(True) self.btn_trace.setText("resume") def read_clicked(self): self.trace_read_dialog = FTraceReadDialog() self.ftrace.read_trace_async() self.trace_read_dialog.show() def trace_clicked(self): if self.ftrace.state == FTrace.STATE_TRACING: self.ftrace.stop() self.enable_options_view() elif self.ftrace.state == FTrace.STATE_NOT_TRACING: self.ftrace.set_current_events(self.filter_events.toPlainText()) self.ftrace.set_current_filters(self.filter_functions.toPlainText()) for i in range(0, self.options_list.count()): item = self.options_list.item(i) option = item.text() enabled = True if item.checkState() == Qt.Unchecked: enabled = False self.ftrace.set_option(option, enabled) self.ftrace.start() self.disable_options_view() else: self.ftrace.start() self.disable_options_view()
class CMWMain(QWidget): def __init__(self, **kwargs): QWidget.__init__(self, parent=None, flags=Qt.WindowStaysOnTopHint) cp.cmwmain = self self.set_input_pars(**kwargs) from psana.graphqt.CMWMainTabs import CMWMainTabs # AFTER set_input_pars !!!!\ self.wlog = cp.wlog = QWLoggerStd(cp, show_buttons=False) repoman = RepoManager(kwargs['logdir'], dettype=None) repoman.save_record_at_start(sys.argv[0].rsplit('/')[-1]) self.wtab = CMWMainTabs() self.vspl = QSplitter(Qt.Vertical) self.vspl.addWidget(self.wtab) self.vspl.addWidget(self.wlog) self.mbox = QHBoxLayout() self.mbox.addWidget(self.vspl) self.setLayout(self.mbox) self.set_style() #self.set_tool_tips() def set_input_pars(self, **kwa): cp.kwargs = kwa self.xywh = cp.main_win_pos_x .value(),\ cp.main_win_pos_y .value(),\ cp.main_win_width .value(),\ cp.main_win_height.value() x, y, w, h = self.xywh self.setGeometry(x, y, w, h) logger.info('set preserved window geometry x,y,w,h: %d,%d,%d,%d' % (x, y, w, h)) #logger.info(log_rec_at_start()) self.main_win_pos_x = cp.main_win_pos_x self.main_win_pos_y = cp.main_win_pos_y self.main_win_width = cp.main_win_width self.main_win_height = cp.main_win_height host = kwa.get('host', None) port = kwa.get('port', None) cp.user = kwa.get('user', None) cp.upwd = kwa.get('upwd', None) exp = kwa.get('experiment', None) det = kwa.get('detector', None) logdir = kwa.get('logdir', None) loglevel = kwa.get('loglevel', 'DEBUG').upper() savecfg = kwa.get('savecfg', False) if isinstance(loglevel, str): loglevel = loglevel.upper() if is_in_command_line(None, '--host'): cp.cdb_host.setValue(host) if is_in_command_line(None, '--port'): cp.cdb_port.setValue(port) if is_in_command_line('-e', '--experiment'): cp.exp_name.setValue(exp) if is_in_command_line('-d', '--detector'): cp.data_source.setValue(det) if is_in_command_line('-l', '--loglevel'): cp.log_level.setValue(loglevel) if is_in_command_line('-L', '--logdir'): cp.log_prefix.setValue(logdir) cp.save_cp_at_exit.setValue(savecfg) if loglevel == 'DEBUG': print(40 * '_') print_kwargs(kwa) def set_tool_tips(self): self.setToolTip('Calibration Management GUI') def set_style(self): self.setMinimumSize(500, 400) self.layout().setContentsMargins(0, 0, 0, 0) spl_pos = cp.main_vsplitter.value() w_height = self.main_win_height.value() self.vspl.setSizes(( spl_pos, w_height - spl_pos, )) def closeEvent(self, e): logger.debug('closeEvent') #try: self.wspe.close() #except: pass self.wtab.close() self.on_save() QWidget.closeEvent(self, e) cp.wlog = None def key_usage(self): return 'Keys:'\ '\n V - view/hide tabs'\ '\n' if __name__ == "__main__": def keyPressEvent(self, e): logger.debug('keyPressEvent, key=%s' % e.key()) if e.key() == Qt.Key_Escape: self.close() elif e.key() == Qt.Key_V: self.wtab.view_hide_tabs() else: logger.info(self.key_usage()) def on_save(self): point, size = self.mapToGlobal(QPoint( -5, -22)), self.size() # Offset (-5,-22) for frame size. x, y, w, h = point.x(), point.y(), size.width(), size.height() msg = 'save window geometry x,y,w,h: %d,%d,%d,%d' % (x, y, w, h) logger.info(msg) print(msg) #Save main window position and size self.main_win_pos_x.setValue(x) self.main_win_pos_y.setValue(y) self.main_win_width.setValue(w) self.main_win_height.setValue(h) spl_pos = self.vspl.sizes()[0] msg = 'Save main v-splitter position %d' % spl_pos logger.debug(msg) cp.main_vsplitter.setValue(spl_pos) if cp.save_cp_at_exit.value(): cp.printParameters() cp.saveParametersInFile() # see ConfigParameters