class Browser(QWidget): def __init__(self): super(Browser, self).__init__() self.setWindowTitle("Navegador PyConAr 2016") vbox = QVBoxLayout(self) # Contenedor principal hbox = QHBoxLayout() # Contenedor horizontal # Widgets btn_atras = QPushButton(QIcon.fromTheme("back"), '') btn_adelante = QPushButton(QIcon.fromTheme("forward"), '') btn_ok = QPushButton(QIcon.fromTheme("find"), '') btn_parar = QPushButton(QIcon.fromTheme("cancel"), '') btn_reload = QPushButton(QIcon.fromTheme("reload"), '') self.url = QLineEdit() self.url.setPlaceholderText("Ingresa una página web o busca en Google") # Agrego los widgets hbox.addWidget(btn_atras) hbox.addWidget(btn_adelante) hbox.addWidget(btn_parar) hbox.addWidget(btn_reload) hbox.addWidget(self.url) hbox.addWidget(btn_ok) # Agrego el contenedor horizontal al vertical vbox.addLayout(hbox) # Componente web self.web = QWebView() vbox.addWidget(self.web) # Creo una barra de estado self.estado = QStatusBar() self.estado.hide() # Creo una barra de progreso y la agrego a la barra de estado self.prog = QProgressBar() self.estado.addWidget(self.prog, 1) self.estado.addWidget(QLabel("Cargando...")) vbox.addWidget(self.estado) # Conexiones btn_atras.clicked.connect(self.web.back) btn_adelante.clicked.connect(self.web.forward) btn_parar.clicked.connect(self.web.stop) btn_reload.clicked.connect(self.web.reload) btn_ok.clicked.connect(self._cargar_pagina) self.web.loadProgress.connect(self.prog.setValue) self.web.loadFinished.connect(self._carga_terminada) self.url.returnPressed.connect(self._cargar_pagina) def _carga_terminada(self): self.estado.hide() self.url.setText(self.web.url().toString()) def _cargar_pagina(self): if not self.estado.isVisible(): self.estado.show() text = self.url.text() if text.find('.') != -1 and not text.startswith('http://'): url = 'http://' + text else: url = 'http://google.com/search?q=' + text.replace(' ', '+') self.web.load(QUrl(url))
class MyTextEditDialog(QMainWindow): def __init__(self, parent): super(MyTextEditDialog, self).__init__(parent) layout = QVBoxLayout() self.editor = TextEdit() # Setup the QTextEdit editor configuration self.editor.setAutoFormatting(QTextEdit.AutoAll) self.editor.selectionChanged.connect(self.update_format) # Initialize default font size. font = QFont('Times', 12) self.editor.setFont(font) # We need to repeat the size to init the current format. self.editor.setFontPointSize(12) # self.path holds the path of the currently open file. # If none, we haven't got a file open yet (or creating new). self.path = None layout.addWidget(self.editor) container = QWidget() container.setLayout(layout) self.setCentralWidget(container) self.status = QStatusBar() self.setStatusBar(self.status) # Uncomment to disable native menubar on Mac # self.menuBar().setNativeMenuBar(False) self.file_toolbar = QToolBar("File") self.file_toolbar.setIconSize(QSize(14, 14)) self.addToolBar(self.file_toolbar) file_menu = self.menuBar().addMenu("&File") open_file_action = QAction( QIcon(os.path.join('images', 'blue-folder-open-document.png')), "Open file...", self) open_file_action.setStatusTip("Open file") open_file_action.triggered.connect(self.file_open) file_menu.addAction(open_file_action) self.file_toolbar.addAction(open_file_action) save_file_action = QAction(QIcon(os.path.join('images', 'disk.png')), "Save", self) save_file_action.setStatusTip("Save current page") save_file_action.triggered.connect(self.file_save) file_menu.addAction(save_file_action) self.file_toolbar.addAction(save_file_action) saveas_file_action = QAction( QIcon(os.path.join('images', 'disk--pencil.png')), "Save As...", self) saveas_file_action.setStatusTip("Save current page to specified file") saveas_file_action.triggered.connect(self.file_saveas) file_menu.addAction(saveas_file_action) self.file_toolbar.addAction(saveas_file_action) print_action = QAction(QIcon(os.path.join('images', 'printer.png')), "Print...", self) print_action.setStatusTip("Print current page") print_action.triggered.connect(self.file_print) file_menu.addAction(print_action) self.file_toolbar.addAction(print_action) self.edit_toolbar = QToolBar("Edit") self.edit_toolbar.setIconSize(QSize(16, 16)) self.addToolBar(self.edit_toolbar) edit_menu = self.menuBar().addMenu("&Edit") undo_action = QAction( QIcon(os.path.join('images', 'arrow-curve-180-left.png')), "Undo", self) undo_action.setStatusTip("Undo last change") undo_action.triggered.connect(self.editor.undo) edit_menu.addAction(undo_action) redo_action = QAction(QIcon(os.path.join('images', 'arrow-curve.png')), "Redo", self) redo_action.setStatusTip("Redo last change") redo_action.triggered.connect(self.editor.redo) self.edit_toolbar.addAction(redo_action) edit_menu.addAction(redo_action) edit_menu.addSeparator() cut_action = QAction(QIcon(os.path.join('images', 'scissors.png')), "Cut", self) cut_action.setStatusTip("Cut selected text") cut_action.setShortcut(QKeySequence.Cut) cut_action.triggered.connect(self.editor.cut) self.edit_toolbar.addAction(cut_action) edit_menu.addAction(cut_action) copy_action = QAction( QIcon(os.path.join('images', 'document-copy.png')), "Copy", self) copy_action.setStatusTip("Copy selected text") cut_action.setShortcut(QKeySequence.Copy) copy_action.triggered.connect(self.editor.copy) self.edit_toolbar.addAction(copy_action) edit_menu.addAction(copy_action) paste_action = QAction( QIcon(os.path.join('images', 'clipboard-paste-document-text.png')), "Paste", self) paste_action.setStatusTip("Paste from clipboard") cut_action.setShortcut(QKeySequence.Paste) paste_action.triggered.connect(self.editor.paste) self.edit_toolbar.addAction(paste_action) edit_menu.addAction(paste_action) select_action = QAction( QIcon(os.path.join('images', 'selection-input.png')), "Select all", self) select_action.setStatusTip("Select all text") cut_action.setShortcut(QKeySequence.SelectAll) select_action.triggered.connect(self.editor.selectAll) edit_menu.addAction(select_action) edit_menu.addSeparator() wrap_action = QAction( QIcon(os.path.join('images', 'arrow-continue.png')), "Wrap text to window", self) wrap_action.setStatusTip("Toggle wrap text to window") wrap_action.setCheckable(True) wrap_action.setChecked(True) wrap_action.triggered.connect(self.edit_toggle_wrap) edit_menu.addAction(wrap_action) self.format_toolbar = QToolBar("Format") self.format_toolbar.setIconSize(QSize(16, 16)) self.addToolBar(self.format_toolbar) self.format_menu = self.menuBar().addMenu("&Format") # We need references to these actions/settings to update as selection changes, so attach to self. # self.bt_ = QPushButton() # self.fonts.currentFontChanged.connect(self.editor.setCurrentFont) # self.format_toolbar.addWidget(self.fonts) self.fonts = QFontComboBox() self.fonts.currentFontChanged.connect(self.editor.setCurrentFont) self.format_toolbar.addWidget(self.fonts) self.fontsize = QComboBox() self.fontsize.addItems([str(s) for s in FONT_SIZES]) # Connect to the signal producing the text of the current selection. Convert the string to float # and set as the pointsize. We could also use the index + retrieve from FONT_SIZES. self.fontsize.currentIndexChanged[str].connect( lambda s: self.editor.setFontPointSize(float(s))) self.format_toolbar.addWidget(self.fontsize) self.bold_action = QAction( QIcon(os.path.join('images', 'edit-bold.png')), "Bold", self) self.bold_action.setStatusTip("Bold") self.bold_action.setShortcut(QKeySequence.Bold) self.bold_action.setCheckable(True) self.bold_action.toggled.connect(lambda x: self.editor.setFontWeight( QFont.Bold if x else QFont.Normal)) self.format_toolbar.addAction(self.bold_action) self.format_menu.addAction(self.bold_action) self.italic_action = QAction( QIcon(os.path.join('images', 'edit-italic.png')), "Italic", self) self.italic_action.setStatusTip("Italic") self.italic_action.setShortcut(QKeySequence.Italic) self.italic_action.setCheckable(True) self.italic_action.toggled.connect(self.editor.setFontItalic) self.format_toolbar.addAction(self.italic_action) self.format_menu.addAction(self.italic_action) self.underline_action = QAction( QIcon(os.path.join('images', 'edit-underline.png')), "Underline", self) self.underline_action.setStatusTip("Underline") self.underline_action.setShortcut(QKeySequence.Underline) self.underline_action.setCheckable(True) self.underline_action.toggled.connect(self.editor.setFontUnderline) self.format_toolbar.addAction(self.underline_action) self.format_menu.addAction(self.underline_action) self.format_menu.addSeparator() self.alignl_action = QAction( QIcon(os.path.join('images', 'edit-alignment.png')), "Align left", self) self.alignl_action.setStatusTip("Align text left") self.alignl_action.setCheckable(True) self.alignl_action.triggered.connect( lambda: self.editor.setAlignment(Qt.AlignLeft)) self.format_toolbar.addAction(self.alignl_action) self.format_menu.addAction(self.alignl_action) self.alignc_action = QAction( QIcon(os.path.join('images', 'edit-alignment-center.png')), "Align center", self) self.alignc_action.setStatusTip("Align text center") self.alignc_action.setCheckable(True) self.alignc_action.triggered.connect( lambda: self.editor.setAlignment(Qt.AlignCenter)) self.format_toolbar.addAction(self.alignc_action) self.format_menu.addAction(self.alignc_action) self.alignr_action = QAction( QIcon(os.path.join('images', 'edit-alignment-right.png')), "Align right", self) self.alignr_action.setStatusTip("Align text right") self.alignr_action.setCheckable(True) self.alignr_action.triggered.connect( lambda: self.editor.setAlignment(Qt.AlignRight)) self.format_toolbar.addAction(self.alignr_action) self.format_menu.addAction(self.alignr_action) self.alignj_action = QAction( QIcon(os.path.join('images', 'edit-alignment-justify.png')), "Justify", self) self.alignj_action.setStatusTip("Justify text") self.alignj_action.setCheckable(True) self.alignj_action.triggered.connect( lambda: self.editor.setAlignment(Qt.AlignJustify)) self.format_toolbar.addAction(self.alignj_action) self.format_menu.addAction(self.alignj_action) format_group = QActionGroup(self) format_group.setExclusive(True) format_group.addAction(self.alignl_action) format_group.addAction(self.alignc_action) format_group.addAction(self.alignr_action) format_group.addAction(self.alignj_action) self.format_menu.addSeparator() # A list of all format-related widgets/actions, so we can disable/enable signals when updating. self._format_actions = [ self.fonts, self.fontsize, self.bold_action, self.italic_action, self.underline_action, # We don't need to disable signals for alignment, as they are paragraph-wide. ] # Initialize. self.update_format() self.update_title() self.hideAllButTextEdit(False) self.show() def block_signals(self, objects, b): for o in objects: o.blockSignals(b) def update_format(self): """ Update the font format toolbar/actions when a new text selection is made. This is neccessary to keep toolbars/etc. in sync with the current edit state. :return: """ # Disable signals for all format widgets, so changing values here does not trigger further formatting. self.block_signals(self._format_actions, True) self.fonts.setCurrentFont(self.editor.currentFont()) # Nasty, but we get the font-size as a float but want it was an int self.fontsize.setCurrentText(str(int(self.editor.fontPointSize()))) self.italic_action.setChecked(self.editor.fontItalic()) self.underline_action.setChecked(self.editor.fontUnderline()) self.bold_action.setChecked(self.editor.fontWeight() == QFont.Bold) self.alignl_action.setChecked(self.editor.alignment() == Qt.AlignLeft) self.alignc_action.setChecked( self.editor.alignment() == Qt.AlignCenter) self.alignr_action.setChecked(self.editor.alignment() == Qt.AlignRight) self.alignj_action.setChecked( self.editor.alignment() == Qt.AlignJustify) self.block_signals(self._format_actions, False) def dialog_critical(self, s): dlg = QMessageBox(self) dlg.setText(s) dlg.setIcon(QMessageBox.Critical) dlg.show() def file_open(self): path, _ = QFileDialog.getOpenFileName( self, "Open file", "", "HTML documents (*.html);Text documents (*.txt);All files (*.*)") try: with open(path, 'rU') as f: text = f.read() except Exception as e: self.dialog_critical(str(e)) else: self.path = path # Qt will automatically try and guess the format as txt/html self.editor.setText(text) self.update_title() def file_save(self): if self.path is None: # If we do not have a path, we need to use Save As. return self.file_saveas() text = self.editor.toHtml() if splitext( self.path) in HTML_EXTENSIONS else self.editor.toPlainText() try: with open(self.path, 'w') as f: f.write(text) except Exception as e: self.dialog_critical(str(e)) def file_saveas(self): path, _ = QFileDialog.getSaveFileName( self, "Save file", "", "HTML documents (*.html);Text documents (*.txt);All files (*.*)") if not path: # If dialog is cancelled, will return '' return text = self.editor.toHtml() if splitext( path) in HTML_EXTENSIONS else self.editor.toPlainText() try: with open(path, 'w') as f: f.write(text) except Exception as e: self.dialog_critical(str(e)) else: self.path = path self.update_title() def file_print(self): dlg = QPrintDialog() if dlg.exec_(): self.editor.print_(dlg.printer()) def update_title(self): self.setWindowTitle( "%s - Megasolid Idiom" % (os.path.basename(self.path) if self.path else "Untitled")) def edit_toggle_wrap(self): self.editor.setLineWrapMode(1 if self.editor.lineWrapMode() == 0 else 0) def hideAllButTextEdit(self, bShow): if (not bShow): # hide all but text self.format_toolbar.hide() self.file_toolbar.hide() self.edit_toolbar.hide() self.menuWidget().hide() self.status.hide() pass else: # show all self.format_toolbar.show() self.file_toolbar.show() self.edit_toolbar.show() self.menuWidget().show() self.status.show() pass
class ErrorStatusBar(QWidget): """ A pop-up status bar for displaying messages about application errors to the user. Messages will be displayed for a given duration or until the message is cleared or updated with a new message. """ CSS = ''' #error_vertical_bar { background-color: #f22b5d; } #error_icon { background-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fff, stop: 0.2 #fff, stop: 1 #fff ); } #error_status_bar { background-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fff, stop: 0.2 #fff, stop: 1 #fff ); font-weight: bold; color: #f22b5d; } ''' def __init__(self): super().__init__() # Set styles self.setStyleSheet(self.CSS) # Set layout layout = QHBoxLayout(self) self.setLayout(layout) # Remove margins and spacing layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) # Error vertical bar self.vertical_bar = QWidget() self.vertical_bar.setObjectName('error_vertical_bar') # Set css id self.vertical_bar.setFixedWidth(10) # Error icon self.label = SvgLabel('error_icon.svg', svg_size=QSize(32, 32)) self.label.setObjectName('error_icon') # Set css id self.label.setFixedWidth(42) # Error status bar self.status_bar = QStatusBar() self.status_bar.setObjectName('error_status_bar') # Set css id self.status_bar.setSizeGripEnabled(False) # Add widgets to layout layout.addWidget(self.vertical_bar) layout.addWidget(self.label) layout.addWidget(self.status_bar) # Hide until a message needs to be displayed self.vertical_bar.hide() self.label.hide() self.status_bar.hide() # Only show errors for a set duration self.status_timer = QTimer() self.status_timer.timeout.connect(self._on_status_timeout) def _hide(self): self.vertical_bar.hide() self.label.hide() self.status_bar.hide() def _show(self): self.vertical_bar.show() self.label.show() self.status_bar.show() def _on_status_timeout(self): self._hide() def update_message(self, message: str, duration: int): """ Display a status message to the user for a given duration. """ self.status_bar.showMessage(message, duration) self.status_timer.start(duration) self._show() def clear_message(self): """ Clear any message currently in the status bar. """ self.status_bar.clearMessage() self._hide()
class GUI(QMainWindow): def __init__(self): super(GUI, self).__init__() self.title = "MudShark v0.1" self.setWindowTitle(self.title) self.defWidth = 800 self.defHeight = 600 # self.setGeometry(100, 100, self.defWidth, self.defHeight) self.resize(self.defWidth, self.defHeight) self.host = "None" self.port = "None" self.log_name = "None" self.log_num = 0 self.mode = "None" self.connected = False self.client = None self.recSize = 0 self.rpw = 0 self.numRecs = 0 self.init_actions() self.modeChangeSignal = ModeChange() self.initUI() def initUI(self): # central widget contains a widget containing a vertical layout, # and that widget contains the stacked widget self.centralWidget = QWidget(self) self.centerVLayoutWidget = QWidget(self.centralWidget) self.centerVLayoutWidget.setGeometry(QRect(0, 0, 800, 550)) self.centralWidLayout = QVBoxLayout(self.centerVLayoutWidget) self.centralWidLayout.setContentsMargins(0, 0, 0, 0) # stacked widget is contained inside centralWidLayout self.stackedWidget = QStackedWidget(self.centerVLayoutWidget) # this is where we instantiate the different views inside stackedWidget self.initialView = InitialView(self) self.stackedWidget.addWidget(self.initialView) self.stackedWidget.setCurrentWidget(self.initialView) self.centralWidLayout.addWidget(self.stackedWidget) self.setCentralWidget(self.centralWidget) self.init_menu() self.init_statusbar() self.init_toolbar() self.show() def updateMode(self, mode): self.mode = mode self.modeChangeSignal.modeChange.connect(self.update_view) self.modeChangeSignal.modeChange.emit() def update_view(self): if self.mode == "None": self.stackedWidget.setCurrentWidget(self.initialView) elif self.mode == "Program log": self.stackedWidget.setCurrentWidget(self.programLogView) elif self.mode == "Retrieve log": self.logDet = client.engage_log(self.client, self.log_num, 0) self.recSize = self.logDet.record_size self.rpw = self.logDet.records_per_window self.numRecs = (self.logDet.max_records / self.logDet.records_per_window) self.records = client.retrieve_records(self.client, self.logDet.records_per_window, self.logDet.max_records, self.logDet.record_size) client.disengage_log(self.client, self.log_num) self.stackedWidget.setCurrentWidget(self.retrieveLogView) def init_actions(self): # exit action self.exitAct = QAction(QIcon('icons/exit.png'), '&Exit', self) self.exitAct.setShortcut('Ctrl+Q') self.exitAct.setStatusTip('Exit application') self.exitAct.setText("Exit") self.exitAct.triggered.connect(qApp.quit) # connect action self.connectAct = QAction(QIcon('icons/connect.png'), 'Connect', self) self.connectAct.setShortcut('Alt+C') self.connectAct.setStatusTip('Connect to a Modbus Meter') self.connectAct.setText("Connect") self.connectAct.triggered.connect(self.connect_popup) # disconnect action self.disconnectAct = QAction(QIcon('icons/disconnect.png'), 'Disconnect', self) self.disconnectAct.setShortcut('Ctrl+D') self.disconnectAct.setText("Disconnect") self.disconnectAct.setStatusTip('Disconnect from current' ' connection') self.disconnectAct.triggered.connect(self.disconnect) # export as action self.exportAsAct = QAction('Export As..', self) self.exportAsAct.setShortcut('Ctrl+e') self.exportAsAct.setText('Export As..') # help action self.helpAct = QAction('Help', self) self.helpAct.setShortcut('Ctrl+h') self.helpAct.setText('Help') # about the author action self.aboutAuthAct = QAction('About the Author', self) self.aboutAuthAct.setText('About the Author') def connect_popup(self): self.ConnectionWindow = cw.ConnectWindow(self) self.ConnectionWindow.show() def disconnect(self): self.host = "None" self.port = "None" self.log_name = "None" self.connected = False self.updateMode("None") self.update_statusbar() if self.client is not None: self.client.close() def init_statusbar(self): self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusMessage = QLabel() statusString = ("Host: " + self.host + " | Port: " + self.port + " | Log: " + self.log_name + " | Mode: " + self.mode + " | Connected: " + str(self.connected)) self.statusMessage.setText(statusString) self.statusBar().addPermanentWidget(self.statusMessage) def update_statusbar(self): self.statusBar().removeWidget(self.statusMessage) statusString = ("Host: " + self.host + " | Port: " + self.port + " | Log: " + self.log_name + " | Mode: " + self.mode + " | Connected: " + str(self.connected)) self.statusMessage = QLabel() self.statusMessage.setText(statusString) self.statusBar().addPermanentWidget(self.statusMessage) def init_toolbar(self): self.toolbar = self.addToolBar("Toolbar") self.toolbar.addAction(self.connectAct) self.toolbar.addAction(self.disconnectAct) self.toolbar.addAction(self.exitAct) def init_menu(self): self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 800, 20)) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle("File") self.menuAbout = QMenu(self.menubar) self.menuAbout.setTitle("About") self.setMenuBar(self.menubar) # File -> Connect self.menuFile.addAction(self.connectAct) # File -> Disconnect self.menuFile.addAction(self.disconnectAct) self.menuFile.addSeparator() # File -> Export As.. self.menuFile.addAction(self.exportAsAct) self.menuFile.addSeparator() # File -> Exit self.menuFile.addAction(self.exitAct) # About -> Help self.menuAbout.addAction(self.helpAct) # About -> About the Author self.menuAbout.addAction(self.aboutAuthAct) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuAbout.menuAction()) ################## # EVENT HANDLING # ################## def toggleMenu(self, state): if state: self.statusbar.show() else: self.statusbar.hide() def contextMenuEvent(self, event): cmenu = QMenu(self) quitAct = cmenu.addAction("Quit") action = cmenu.exec_(self.mapToGlobal(event.pos())) if action == quitAct: qApp.quit()
class GUI(QMainWindow): def __init__(self): super().__init__() self.resize(600, 600) self.setWindowTitle("Untitled-Notepad") self.setWindowIcon( QIcon(r'C:\Users\Yash\PycharmProjects\ppppp\Notepad\icons.png')) #self.timer=QTimer(self) #self.timer.timeout.connect(self.geometrychange) #self.timer.start(10) self.menu = QMenuBar(self) self.file = QMenu("File", self.menu) file = self.file.addAction("New") file.setShortcut("Ctrl+N") file.triggered.connect(self.files) opens = self.file.addAction('Open') opens.setShortcut("Ctrl+O") opens.triggered.connect(self.open) save = self.file.addAction("Save") save.setShortcut("Ctrl+S") save.triggered.connect(self.save) saveas = self.file.addAction("Save as") saveas.triggered.connect(self.saveas) self.file.addSeparator() printsetup = self.file.addAction("Print Preview") printsetup.triggered.connect(self.printsetup) prints = self.file.addAction("Print") prints.setShortcut("Ctrl+P") prints.triggered.connect(self.prints) self.file.addSeparator() exits = self.file.addAction("Exit") exits.setShortcut("Alt+X") exits.triggered.connect(self.exists) self.menu.addMenu(self.file) self.edit = QMenu("Edit", self.menu) undo = self.edit.addAction("Undo") undo.setShortcut("Ctrl+Z") undo.triggered.connect(self.undos) self.edit.addSeparator() self.cuts = self.edit.addAction("Cut") self.cuts.setShortcut("Ctrl+X") self.cuts.triggered.connect(self.cut) self.copys = self.edit.addAction("Copy") self.copys.setShortcut("Ctrl+C") self.copys.triggered.connect(self.copy) self.pastes = self.edit.addAction("Paste") self.pastes.setShortcut("Ctrl+V") self.pastes.triggered.connect(self.paste) self.deletes = self.edit.addAction("Delete") self.deletes.setShortcut("Del") self.deletes.triggered.connect(self.delete) self.edit.addSeparator() self.finding = self.edit.addAction("Find") self.finding.setShortcut("Ctrl+F") self.finding.triggered.connect(self.finds) self.findnexts = self.edit.addAction("Find Next") self.findnexts.setShortcut("F3") self.findnexts.triggered.connect(self.nexts) replace = self.edit.addAction("Replace") replace.setShortcut("Ctrl+H") replace.triggered.connect(self.replace) go = self.edit.addAction("Go To") go.setShortcut("Ctrl+G") go.triggered.connect(self.go) check = QTimer(self) check.timeout.connect(self.check) check.start(100) self.edit.addSeparator() select = self.edit.addAction("Select All") select.setShortcut("Ctrl+A") select.triggered.connect(self.select) time = self.edit.addAction("Time/Date") time.setCheckable(True) time.setShortcut("F5") time.triggered.connect(self.todaytime) self.menu.addMenu(self.edit) self.format = QMenu("Format", self.menu) self.wrap = self.format.addAction("Word Wrap") self.wrap.setCheckable(True) self.wrap.setChecked(True) self.wrap.triggered.connect(self.word) font = self.format.addAction("Font") font.triggered.connect(self.fonts) self.menu.addMenu(self.format) self.view = QMenu("View", self.menu) zoom = QMenu("Zoom", self.view) In = zoom.addAction("Zoom In") In.setShortcut("Ctrl++") In.triggered.connect(self.zoomin) out = zoom.addAction("Zoom Out") out.setShortcut("Ctrl+-") out.triggered.connect(self.zoomout) restore = zoom.addAction("Restore Default Zoom") restore.setShortcut("Ctrl+0") restore.triggered.connect(self.restore) self.view.addMenu(zoom) self.statused = self.view.addAction("Status Bar") self.statused.setCheckable(True) self.statused.setChecked(True) self.statused.triggered.connect(self.status) self.menu.addMenu(self.view) self.help = QMenu("Help", self.menu) help = self.help.addAction("View Help") help.triggered.connect(self.helps) self.help.addSeparator() about = self.help.addAction("About Notepad") about.triggered.connect(self.about) self.menu.addMenu(self.help) self.setMenuBar(self.menu) self.centralwidget = QWidget(self) self.textEdit = QTextEdit(self.centralwidget) self.textEdit.setGeometry(QRect(0, 0, 600, 579)) self.textEdit.setUndoRedoEnabled(True) font = QFont() font.setFamily('Arial') font.setPointSize(16) self.textEdit.setFont(font) self.textEdit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.textEdit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.textEdit.setLineWrapMode(self.textEdit.WidgetWidth) self.textEdit.setLineWidth(2) try: self.path = str(sys.argv[1]) f = open(self.path, 'r', encoding='utf-8') data = f.read() self.textEdit.setText(data) self.setWindowTitle(os.path.basename(self.path) + '-Notepad') except: pass self.setCentralWidget(self.centralwidget) self.show() def closeEvent(self, event): if self.close: reply = QMessageBox.question(self, "You want to quit? ", "Task is in progress !", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore() def resizeEvent(self, event): if self.statused.isChecked() == True: self.status() self.statusbar.setGeometry( QRect(self.geometry().x() - self.geometry().getCoords()[0], self.geometry().width(), self.geometry().width(), 20)) self.textEdit.setGeometry( QRect(self.geometry().x() - self.geometry().getCoords()[0], self.geometry().y() - self.geometry().getCoords()[1], self.geometry().width(), self.geometry().height() - 42)) else: self.textEdit.setGeometry( QRect(self.geometry().x() - self.geometry().getCoords()[0], self.geometry().y() - self.geometry().getCoords()[1], self.geometry().width(), self.geometry().height() - 21)) def check(self): if len(self.textEdit.toPlainText()) == 0: self.copys.setDisabled(True) self.cuts.setDisabled(True) self.pastes.setDisabled(True) self.deletes.setDisabled(True) self.finding.setDisabled(True) self.findnexts.setDisabled(True) else: self.finding.setDisabled(False) self.findnexts.setDisabled(False) self.copys.setDisabled(False) self.cuts.setDisabled(False) self.pastes.setDisabled(False) self.deletes.setDisabled(False) if self.statused.isChecked() == True: time = QTime.currentTime() text = time.toString("hh:mm:ss") self.time.display(text) cursor = self.textEdit.textCursor() row = cursor.blockNumber() + 1 col = cursor.columnNumber() self.label.setText("Row: " + str(row) + "| Col: " + str(col)) def status(self): if self.statused.isChecked() == True: self.statusbar = QStatusBar(self) self.statusbar.setGeometry( QRect(self.geometry().x() - self.geometry().getCoords()[0], self.geometry().width(), self.geometry().width(), 20)) self.textEdit.setGeometry( QRect(self.geometry().x() - self.geometry().getCoords()[0], self.geometry().y() - self.geometry().getCoords()[1], self.geometry().width(), self.geometry().height() - 42)) font = QFont() font.setPointSize(10) self.statusbar.setFont(font) self.label = QLabel("Row: 0 | Col: 0") self.statusbar.addPermanentWidget(self.label) self.time = QLCDNumber() self.time.setDigitCount(8) self.time.setFrameShadow(QFrame.Sunken) self.time.setFrameShape(QFrame.Panel) self.statusbar.addWidget(self.time) self.setStatusBar(self.statusbar) else: self.textEdit.setGeometry( QRect(self.geometry().x() - self.geometry().getCoords()[0], self.geometry().y() - self.geometry().getCoords()[1], self.geometry().width(), self.geometry().height() - 21)) vboxlayout = QVBoxLayout() vboxlayout.setContentsMargins(QtCore.QMargins()) vboxlayout.setSpacing(0) sizegrip = QSizeGrip(self.centralwidget) sizegrip.setVisible(True) vboxlayout.addWidget(sizegrip, 0, Qt.AlignBottom | Qt.AlignRight) self.centralwidget.setLayout(vboxlayout) self.statusbar.hide() def helps(self): QMessageBox.information(self, "Help", "This is your notepad made by PyQt5") def about(self): QMessageBox.information(self, "About", "This is the Notepad made by Yash Rajput") def files(self): self.textEdit.setText('') self.setWindowTitle("Untitled-Notepad") self.filename = ["Untitled-Notepad"] self.new = True def open(self): self.filename = QFileDialog.getOpenFileName( self, 'Open File', '\home', 'Text Files (*.txt);;All Files (*)') if self.filename[0]: f = open(self.filename[0], 'r', encoding='utf-8') try: data = f.read() self.textEdit.setText(data) self.setWindowTitle( os.path.basename(self.filename[0]) + '-Notepad') except: pass def save(self): try: if self.new == False: w = open(self.filename[0], 'w') print(self.filename[0]) w.write(self.textEdit.toPlainText()) w.close() elif self.new == True: self.saveas() except: self.saveas() def saveas(self): self.filename = QFileDialog.getSaveFileName( self, "Save as", '\home', 'Text Files(*.txt);;All Files(*)') try: f = open(self.filename[0], 'w') f.write(self.textEdit.toPlainText()) f.close() self.new = False self.setWindowTitle( os.path.basename(self.filename[0]) + '-Notepad') except: pass def exists(self): box = QMessageBox.question(self, "You want to quit? ", "Task is in progress !", QMessageBox.Yes, QMessageBox.No) if box.exec() == box.Yes: self.destroy() def undos(self): self.textEdit.undo() def cut(self): self.textEdit.cut() def copy(self): self.textEdit.copy() def paste(self): self.textEdit.paste() def select(self): self.textEdit.selectAll() def delete(self): cursor = self.textEdit.textCursor() cursor.removeSelectedText() def todaytime(self): self.textEdit.insertPlainText(str(datetime.today())) def word(self): if self.wrap.isChecked(): self.textEdit.setLineWrapMode(self.textEdit.WidgetWidth) else: self.textEdit.setLineWrapMode(self.textEdit.NoWrap) def fonts(self): font, ok = QFontDialog.getFont() if ok: self.textEdit.setFont(font) def zoomin(self): font = QFont(self.textEdit.font()) size = font.pointSize() font.setPointSize(size + 1) self.textEdit.setFont(font) def zoomout(self): font = QFont(self.textEdit.font()) size = font.pointSize() font.setPointSize(size - 1) self.textEdit.setFont(font) def restore(self): font = QFont() font.setPointSize(8) font.setFamily('Arial') self.textEdit.setFont(font) def finds(self): self.pc = Find(w) self.pc.exec() def replace(self): p = replaces(w) p.exec() def go(self): temp = Go(w) temp.exec() def prints(self): self.printer = QPrinter(QPrinter.HighResolution) dialog = QPrintDialog(self.printer, self) if dialog.exec_() == QPrintDialog.Accepted: w.textEdit.print_(self.printer) def printsetup(self): self.printer = QPrinter(QPrinter.HighResolution) dialog = QPrintPreviewDialog(self.printer, self) dialog.paintRequested.connect(self.handle_paint_request) dialog.exec_() def handle_paint_request(self, printer): self.textEdit.print(printer) def nexts(self): self.pc.click()
class App(QMainWindow): resized = pyqtSignal() def __init__(self, width=1080, height=720): super().__init__() self.connectionStatus = False self.width = width self.height = height self.initUI() # self.initSignalsSlots() self.qsObj = None self.deviceName = "" self.serialPort = None self.currentTabMode = -1 self.sched = None def initUI(self): self.title = 'AutonomousFlight Configurator v1.0' self.left = 0 self.top = 0 # self.width = 1080 # self.height = 720 self.toolbarheight = 65 self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.centerWindow() self.bundle_dir = os.path.dirname(os.path.abspath(__file__)) self.initWidgets() self.setFocus() def centerWindow(self): frameGeo = self.frameGeometry() screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos()) centerPoint = QApplication.desktop().screenGeometry(screen).center() frameGeo.moveCenter(centerPoint) self.move(frameGeo.topLeft()) def initWidgets(self): # HeaderBar self.initHeaderWidget = InitHeaderWidget(self) self.initHeaderWidget.setGeometry(0, 0, self.width, 100) self.initHeaderWidget.show() self.initHeaderWidget.connectionStatusChangedSignal.connect(self.processInitConnection) # Init CoverPage self.coverPageWidget = CoverPageWidget(self) self.coverPageWidget.setGeometry(0, 100, self.width, self.height-100) self.coverPageWidget.show() # Show self.show() def initWorkingWidget(self): # Init StatusHeaderBar self.statusHeaderWidget = StatusHeaderWidget(self, self.qsObj) self.statusHeaderWidget.setGeometry(0, 0, self.width, 100) self.statusHeaderWidget.connectionStatusChangedSignal.connect(self.processStatusConnection) # self.statusHeaderWidget.hide() # Init InfoTabs self.infoTabsWidget = QTabWidget(self) self.infoTabsWidget.setGeometry(0, 100, self.width, self.height-130) # Vertical: 2 self.infoTabsWidget.setTabPosition(2) self.tabNameList = ["CLI", "Overview", "Calibration", "Configure", "ParameterSetting", "Mode", "Sensor", "Motor", "Topology", "Blackbox", "SerialTerminal"] self.tabObjectDict = {"CLI":CLIWidget(self), "Overview":OverviewInfoWidget(self, self.qsObj), "Calibration":CalibrationWidget(self, self.qsObj), "Configure":ConfigureWidget(self, self.qsObj), "ParameterSetting":ParameterSettingWidget(self, self.qsObj), "Mode":FlightModeWidget(self, self.qsObj), "Sensor":SensorWidget(self, self.qsObj), "Motor":MotorInfoWidget(self, self.qsObj), "Topology":TopologyWidget(self, self.qsObj), "Blackbox":BlackboxWidget(self), "SerialTerminal":SerialTerminalWidget(self)} for key,value in self.tabObjectDict.items(): self.infoTabsWidget.addTab(value, key) # self.infoTabsWidget.hide() self.infoTabsWidget.currentChanged.connect(self.setTabMode) # Init StatusBar self.statusBar = QStatusBar() # "Packet error:","I2C error:","Cycle Time:", # "CPU Load:","MSP Version:", "MSP Load:", # "MSP Roundtrip:","HW roundtrip:","Drop ratio:" self.statusBarTopicList = ["Cycle Time:", "I2C error:", "CPU Load:", "MSP Version:"] self.packetInfoLabel = QLabel(" | ".join(self.statusBarTopicList)) self.statusBar.addWidget(self.packetInfoLabel) self.setStatusBar(self.statusBar) # self.statusBar.hide() def initSignalsSlots(self): pass def processInitConnection(self): result = False try: # Start serial port self.startSerialPort() self.qsObj = QuadStates() self.mspHandle = MSPv1(self.serialPort, self.qsObj) result = self.mspHandle.preCheck() # Respond to reboot command from MSPv1 self.mspHandle.rebootSignal.connect(self.reboot) except: print("Fail to open serial port.") if result: self.connectionStatus = True self.debug() self.initWorkingWidget() # Send command to MSP class self.statusHeaderWidget.statusDataRequestSignal.connect(self.mspHandle.processHeaderDataRequest) self.tabObjectDict["CLI"].cliSignal.connect(self.mspHandle.cliCommandSwitch) self.tabObjectDict["Overview"].overviewInfoSignal.connect(self.mspHandle.overviewInfoResponse) self.tabObjectDict["Mode"].flightmodeSaveSignal.connect(self.mspHandle.processModeRangesSave) self.tabObjectDict["Configure"].configureSaveSignal.connect(self.mspHandle.processConfigureSave) self.tabObjectDict["ParameterSetting"].parameterSaveSignal.connect(self.mspHandle.processParameterSettingSave) self.tabObjectDict["Calibration"].accCalibrateSignal.connect(self.mspHandle.processAccCalibrationRequest) self.tabObjectDict["Calibration"].magCalibrateSignal.connect(self.mspHandle.processMagCalibrationRequest) self.tabObjectDict["Calibration"].calibrationSaveSignal.connect(self.mspHandle.processCalibrationSave) self.tabObjectDict["Sensor"].sensorDataRequestSignal.connect(self.mspHandle.processSensorDataRequest) self.tabObjectDict["Motor"].motorDataRequestSignal.connect(self.mspHandle.processMotorDataRequest) self.tabObjectDict["Mode"].modeRCDataRequestSignal.connect(self.mspHandle.processModeRCDataRequest) self.tabObjectDict["Topology"].topologySaveSignal.connect(self.mspHandle.processTopologySave) self.tabObjectDict["SerialTerminal"].serTerSignal.connect(self.mspHandle.processSerialTerminalRequest) # MSP data changed will raise this signal to update labels in UI page self.mspHandle.headerDataUpdateSignal.connect(self.headerPageUpdate) self.mspHandle.cliFeedbackSignal.connect(self.tabObjectDict["CLI"].processFeedback) self.mspHandle.calibrationFeedbackSignal.connect(self.tabObjectDict["Calibration"].processFeedback) self.mspHandle.overviewDataUpdateSignal.connect(self.overviewPageUpdate) self.mspHandle.sensorDataUpdateSignal.connect(self.sensorPageUpdate) self.mspHandle.motorDataUpdateSignal.connect(self.motorPageUpdate) self.mspHandle.modeRCDataUpdateSignal.connect(self.flightmodePageRCUpdate) self.mspHandle.serTerFeedbackSignal.connect(self.tabObjectDict["SerialTerminal"].processFeedback) # Change UI self.initHeaderWidget.hide() self.coverPageWidget.hide() self.statusHeaderWidget.show() self.infoTabsWidget.show() self.infoTabsWidget.setCurrentIndex(0) self.setTabMode(0) self.statusBar.show() # Start StatusHeader Timer self.statusHeaderWidget.start() def processStatusConnection(self): self.connectionStatus = False # # self.checkSchedulerShutdown() self.setTabMode(0) self.statusHeaderWidget.stop() # End serial port self.closeSerialPort() self.qsObj = None # Change UI self.statusHeaderWidget.hide() self.infoTabsWidget.hide() self.statusBar.hide() self.initHeaderWidget.show() self.coverPageWidget.show() def keyPressEvent(self, event): if self.currentTabMode == 0: self.tabObjectDict["CLI"].keyPressed(event) def debug(self): print("---Debug---") # print(self.qsObj.msp_activeboxes) # print(self.qsObj.msp_boxids) # print(len(self.qsObj.msp_boxids)) # print(self.qsObj.msp_boxnames) # print(len(self.qsObj.msp_boxnames)) # print(self.qsObj.msp_mode_ranges) # print(len(self.qsObj.msp_mode_ranges)) print("---Debug---") pass # Process reboot def reboot(self): # Step 1: Close current connection self.processStatusConnection() # Step 2: Wait for 0.3 seconds self.waitTimer = QTimer() self.waitTimer.setInterval(300) self.waitTimer.setSingleShot(True) # Step 3: Reconnect self.waitTimer.timeout.connect(self.processInitConnection) self.waitTimer.start(300) # Page index # Change corresponding index if the tabObjectDict is changed. def setTabMode(self, index): if self.currentTabMode != index: if index == self.tabNameList.index("CLI"): # Stop header widget update self.statusHeaderWidget.stop() elif self.currentTabMode == self.tabNameList.index("CLI"): # Resume header widget update self.statusHeaderWidget.start() if index == self.tabNameList.index("Overview"): # Overview Page self.tabObjectDict["Overview"].start() elif self.currentTabMode == self.tabNameList.index("Overview"): self.tabObjectDict["Overview"].stop() if index == self.tabNameList.index("Calibration"): # Calibration self.calibrationPageUpdate() # Mode if index == self.tabNameList.index("Mode"): self.flightmodePageUpdate() self.tabObjectDict["Mode"].start() elif self.currentTabMode == self.tabNameList.index("Mode"): self.tabObjectDict["Mode"].stop() # Configure if index == self.tabNameList.index("Configure"): # Configure self.configurePageUpdate() if index == self.tabNameList.index("ParameterSetting"): # Parameter Setting self.parameterSettingPageUpdate() if index == self.tabNameList.index("Sensor"): # Sensor self.tabObjectDict["Sensor"].start() elif self.currentTabMode == self.tabNameList.index("Sensor"): self.tabObjectDict["Sensor"].stop() if index == self.tabNameList.index("Motor"): # Motor self.tabObjectDict["Motor"].start() elif self.currentTabMode == self.tabNameList.index("Motor"): self.tabObjectDict["Motor"].stop() # Topology if index == self.tabNameList.index("Topology"): # Topology self.topologyPageUpdate() if index == self.tabNameList.index("Blackbox"): # Blackbox pass if index == self.tabNameList.index("SerialTerminal"): # Serial Terminal # Stop header widget update self.statusHeaderWidget.stop() self.tabObjectDict["SerialTerminal"].start() elif self.currentTabMode == self.tabNameList.index("SerialTerminal"): self.tabObjectDict["SerialTerminal"].stop() # Resume header widget update self.statusHeaderWidget.start() self.currentTabMode = index def startSerialPort(self): self.deviceName = self.initHeaderWidget.connectionMethodComboBox.currentText() self.serialPort = SerialCommunication(self.deviceName) def closeSerialPort(self): self.serialPort.stopDevice() self.serialPort = None def headerPageUpdate(self, ind): if ind == 0: self.statusHeaderWidget.updateMMSV() elif ind == 1: self.statusHeaderWidget.updateSensorStatus() def overviewPageUpdate(self, ind): if ind == 0: self.tabObjectDict["Overview"].updateAttitudeLabels() elif ind == 1: self.tabObjectDict["Overview"].updateArmingFlagLabels() elif ind == 2: self.tabObjectDict["Overview"].updateBatteryLabels() elif ind == 3: self.tabObjectDict["Overview"].updateCommunicationLabels() elif ind == 4: self.tabObjectDict["Overview"].updateGPSLabels() # # Update header sensor lights. # self.statusHeaderWidget.update(self.qsObj.msp_sensor_status) # Update status bar self.statusBarUpdate() def statusBarUpdate(self): self.statusBarTopicList = ["Cycle Time:", "I2C Error:", "CPU Load:", "MSP Version:"] self.statusBarValueDict = {} for field in self.statusBarTopicList: data = None if field == "Cycle Time:": data = self.qsObj.msp_status_ex['cycleTime'] elif field == "I2C Error:": data = self.qsObj.msp_status_ex['i2cError'] elif field == "CPU Load:": data = self.qsObj.msp_status_ex['averageSystemLoadPercent'] elif field == "MSP Version:": data = "1" else: pass self.statusBarValueDict[field] = str(data) labelString = "| " for key,value in self.statusBarValueDict.items(): labelString = labelString + key + value + " | " self.packetInfoLabel.setText(labelString) def sensorPageUpdate(self, ind): if ind == 0: self.tabObjectDict["Sensor"].updateACCPlot() self.tabObjectDict["Sensor"].updateGYROPlot() self.tabObjectDict["Sensor"].updateMAGPlot() elif ind == 1: self.tabObjectDict["Sensor"].updateBAROPlot() elif ind == 2: self.tabObjectDict["Sensor"].updateRangeFinderPlot() def motorPageUpdate(self, ind): if ind == 0: self.tabObjectDict["Motor"].updateMotorValues() def flightmodePageRCUpdate(self, ind): if ind == 0: self.tabObjectDict["Mode"].updateCurrentValueLabels() def flightmodePageUpdate(self): self.tabObjectDict["Mode"].setRanges() def parameterSettingPageUpdate(self): self.mspHandle.processParameterSettingCheck() self.tabObjectDict['ParameterSetting'].setValues() def configurePageUpdate(self): self.mspHandle.processConfigureCheck() self.tabObjectDict['Configure'].setValues() def calibrationPageUpdate(self): self.mspHandle.processCalibrationCheck() self.tabObjectDict['Calibration'].setValues() def topologyPageUpdate(self): self.mspHandle.processTopologyCheck() self.tabObjectDict['Topology'].setValues()
class GestureDraw(QMainWindow): populateGallery = pyqtSignal() closedWindow = pyqtSignal(object) key_pressed = pyqtSignal(object) def __init__(self, parent): super(GestureDraw, self).__init__() self.setWindowTitle('Gesture Draw') self.parent = parent self.configure_gui() self.create_widgets() self.create_menu() self.order[0].actions()[-1].trigger() self.show() def configure_gui(self): self.stack = QStackedWidget(self) self.setCentralWidget(self.stack) resolution = Qapp.desktop().screenGeometry() width, height = resolution.width(), resolution.height() self.setGeometry(0, 0, width // 2, height) def create_widgets(self): self.windows = set() self.mysql = CONNECT(self) self.threadpool = QThreadPool() self.gallery = Gallery(self) self.preview = Preview(self) self.timer = Timer(self.preview, self) self.stack.addWidget(self.gallery) self.stack.addWidget(self.preview) self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.setFixedHeight(30) self.mysql.finishedTransaction.connect(self.select_records) self.mysql.finishedSelect.connect(self.gallery.clearSelection) self.mysql.finishedSelect.connect(self.gallery.update) self.mysql.finishedSelect.connect(self.update_statusbar) self.gallery.selection.connect(self.update_statusbar) self.gallery.find_artist.connect(self.find_by_artist) self.gallery.setContentsMargins(5, 0, 5, 0) for action in self.gallery.menu.actions(): if action.text() in ['Delete', 'Properties']: self.gallery.menu.removeAction(action) self.preview.label.setStyleSheet(f'background: black') def create_menu(self): self.menubar = self.menuBar() self.toolbar = self.addToolBar('Ribbon') self.ribbon = Ribbon(self) self.toolbar.addWidget(self.ribbon) self.menubar.triggered.connect(self.menuPressEvent) self.toolbar.actionTriggered.connect(self.menuPressEvent) self.ribbon.selection_mode.connect(self.setSelectionMode) self.ribbon.multi.click() self.ribbon.tags.setFocus() # File file = self.menubar.addMenu('File') file.addAction('Copy Images to') self.gesture_menu = create_submenu_(self, 'Gesture Draw', GESTURE.keys(), check=False)[0] file.addMenu(self.gesture_menu) file.addSeparator() file.addAction('Exit', self.close, shortcut='CTRL+W') # database database = self.menubar.addMenu('Database') database.addAction('Reconnect') database.addAction('Current statement') database.addAction('Update Autocomplete') database.addAction('Remove Redundancies') # View view = self.menubar.addMenu('View') # Help help = self.menubar.addMenu('Help') @pyqtSlot() def select_records(self): worker = Worker(self.mysql.execute, self.ribbon.update_query(1, 1000)) self.threadpool.start(worker) def start_session(self, gallery, time): if gallery and time: self.menubar.hide() self.toolbar.hide() self.statusbar.hide() if ':' in time: min, sec = time.split(':') time = (int(min) * 60) + int(sec) else: time = int(time) self.stack.setCurrentIndex(1) self.timer.start(gallery, time) else: QMessageBox.information(self, '', 'You are either missing images or a time', QMessageBox.Ok) def update_statusbar(self): total = self.gallery.total() select = len(self.gallery.selectedIndexes()) total = (f'{total} image' if (total == 1) else f'{total} images') if select: select = (f'{select} image selected' if (select == 1) else f'{select} images selected') else: select = '' self.statusbar.showMessage(f' {total} {select}') def find_by_artist(self, index): artist = index.data(Qt.UserRole)[1] if artist: self.ribbon.setText(' OR '.join(artist.split())) else: QMessageBox.information(self, 'Find by artist', 'This image has no artist') def setSelectionMode(self, event): if event: self.gallery.setSelectionMode(QAbstractItemView.MultiSelection) else: self.gallery.setSelectionMode(QAbstractItemView.ExtendedSelection) self.gallery.clearSelection() def menuPressEvent(self, event=None): action = event.text() # Files if action == 'Copy Images to': copy_to(self, self.gallery.selectedIndexes()) elif action in GESTURE.keys(): if action == 'Custom Time': time, ok = QInputDialog.getText(self, "Dialog", "Enter time:") if ok: gallery = self.gallery.selectedIndexes() self.start_session(gallery, time) else: gallery = self.gallery.selectedIndexes() self.start_session(gallery, GESTURE[action]) elif action == 'Exit': self.close() # Database elif action == 'Reconnect': self.mysql = CONNECT(self) self.threadpool = QThreadPool() elif action == 'Current Statement': QMessageBox.information(self, 'Current Statement', self.ribbon.query) elif action == 'Update Autocomplete': worker = Worker(update_autocomplete) self.threadpool.start(worker) self.ribbon.tags.setCompleter( Completer(open(AUTOCOMPLETE).read().split())) elif action == 'Remove Redundancies': worker = Worker(remove_redundancies) self.threadpool.start(worker) def keyPressEvent(self, event): key_press = event.key() if key_press == Qt.Key_Space: self.timer.pause() elif key_press in (Qt.Key_Left, Qt.Key_Right): pass elif key_press == Qt.Key_Escape: if self.stack.currentIndex(): self.timer.pause() self.menubar.show() self.toolbar.show() self.statusbar.show() self.statusbar.showMessage('') self.stack.setCurrentIndex(0) self.select_records() else: self.close() else: self.key_pressed.emit(event) def mousePressEvent(self, event): if event.button() == Qt.MouseButton.LeftButton: self.timer.pause() def closeEvent(self, event): self.threadpool.clear() for window in self.windows: window.close() self.mysql.close() self.closedWindow.emit(self)
class IMonUi(QMainWindow): """Main Window.""" def __init__(self, parent=None): """Initializer.""" super().__init__(parent) self.setWindowTitle('imon: Image Monitor') self.setMinimumSize(1024, 768) self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.setWindowIcon(QIcon('icon.ico')) # create variables self.watchdir = '' self.image_types = ('*.bmp', '*.gif', '*jpg', '*.jpeg', '*.png', '*.pbm', '*.pgm', '*.ppm', '*.xbm', '*.xpm', '*.svg', '*.BMP', '*.GIF', '*JPG', '*.JPEG', '*.PNG', '*.PBM', '*.PGM', '*.PPM', '*.XBM', '*.XPM', '*.SVG') self.wasMaximized = True # create border widgets self._createstatusbar() self._createtoolbar() # create central widget self.display = QLabel() self.display.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.display.pixmap = QPixmap('default.png') self.display.setPixmap(self.display.pixmap) self.display.setAlignment(Qt.AlignCenter) self.setCentralWidget(self.display) self.installEventFilter(self) self.status_message = '{0: <100}'.format(os.path.dirname(os.path.realpath(__file__)) + '/default.png') + ' ' +\ '{0: <50}'.format( str(self.display.pixmap.width()) + 'x' + str(self.display.pixmap.height())) + ' ' +\ '{0: <50}'.format(str(f'{os.path.getsize("default.png") / 1000000:.2f}') + 'MB') self.status.showMessage(self.status_message) self.setStatusBar(self.status) # create timer action to update image self.timer = QTimer() self.timer.timeout.connect(self.updateimage) self.timer.start(100) def updateimage(self): img = get_latest_image(self.watchdir, self.image_types) if img != '': # update display self.display.pixmap = QPixmap(img) self.display.setPixmap(self.display.pixmap) self.display.setPixmap( self.display.pixmap.scaled(self.centralWidget().size(), Qt.KeepAspectRatio)) # update status bar self.status_message = '{0: <100}'.format(img) + ' ' +\ '{0: <50}'.format(str(self.display.pixmap.width()) + 'x' + str(self.display.pixmap.height())) + ' ' +\ '{0: <50}'.format(str(f'{os.path.getsize(img) / 1000000:.2f}') + 'MB') self.status.showMessage(self.status_message) self.setStatusBar(self.status) def _createtoolbar(self): self.tools = QToolBar() self.addToolBar(self.tools) self.tools.addAction('Exit', self.close) self.tools.addAction('Select Watch Directory', self._selectdir) self.tools.addAction('Fullscreen', self._gofullscreen) def _createstatusbar(self): self.status = QStatusBar() self.setStatusBar(self.status) def _selectdir(self): self.watchdir = str( QFileDialog.getExistingDirectory(self, "Select Directory")) def _gofullscreen(self): if self.isMaximized() == True: self.wasMaximized = True else: self.wasMaximized = False self.showFullScreen() self.tools.hide() self.status.hide() def eventFilter(self, source, event): if source is self and event.type() == QEvent.Resize: self.display.setPixmap( self.display.pixmap.scaled(self.centralWidget().size(), Qt.KeepAspectRatio)) return super(IMonUi, self).eventFilter(source, event) def keyPressEvent(self, e): # TODO: when running showMaximized after being fullscreen, it behaves like showNormal if e.key() == Qt.Key_Escape: if self.isFullScreen(): if self.wasMaximized == True: self.showMaximized() self.tools.show() self.status.show() else: self.showNormal() self.tools.show() self.status.show() if e.key() == Qt.Key_F11: if self.isFullScreen(): if self.wasMaximized == True: self.showMaximized() self.tools.show() self.status.show() else: self.showNormal() self.tools.show() self.status.show() else: self._gofullscreen()
class WidgetDemo(QWidget): def __init__(self, model, rows, columns): super(WidgetDemo, self).__init__() self.init_rows = rows self.init_columns = columns self.model = model self.initUI(model) def initUI(self, model): self.resize(800, 800) self.res_pos = [] self.focus_pos = None self.var_list = None self.signal = MySignal() #菜单栏 self.menu = QMenuBar() self.file = self.menu.addMenu('文件') self.edit = self.menu.addMenu('编辑') self.view = self.menu.addMenu('视图') self.help = self.menu.addMenu('帮助') #各菜单下的子菜单 #文件菜单下的子菜单 # self.new = self.file.addAction('新建') self.open = self.file.addAction('打开') self.save = self.file.addAction('保存') # self.save_as = self.file.addAction('另存为') #编辑菜单下的子菜单 self.cut = self.edit.addAction('剪切') self.copy = self.edit.addAction('复制') self.paste = self.edit.addAction('粘贴') self.delete = self.edit.addAction('删除') self.find = self.edit.addAction('查找') self.replace = self.edit.addAction('替换') # 快捷键 self.open.setShortcut('Ctrl+O') self.save.setShortcut('Ctrl+S') # self.new.setShortcut('Ctrl+N') self.find.setShortcut('Ctrl+F') #视图菜单下的子菜单 self.tool_view = QAction('工具栏', checkable=True) self.tool_view.setChecked(True) self.view.addAction(self.tool_view) self.statu_view = QAction('状态栏', checkable=True) self.statu_view.setChecked(True) self.view.addAction(self.statu_view) #帮助菜单下的子菜单 self.about = self.help.addAction('关于') #工具栏 self.tool_bar = QToolBar() # self.tool_bar.addAction(self.new) self.tool_bar.addAction(self.open) self.tool_bar.addAction(self.save) self.tool_bar.addAction(self.cut) self.tool_bar.addAction(self.copy) self.tool_bar.addAction(self.paste) self.tool_bar.addAction(self.find) # self.setting = QAction('变量设置') # self.setting.setEnabled(False) # self.tool_bar.addAction(self.setting) # self.tool_bar.addAction(self.replace) # #tool文本显示在下方 # self.tool_bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) #findWidge self.find_widget = FindWidget() self.find_widget.hide() #表格 self.table_view = QTableView() self.table_view.setModel(self.model) #状态栏 self.status_bar = QStatusBar() self.status_bar.showMessage('状态栏') # 右键菜单栏 self.setContextMenuPolicy(Qt.CustomContextMenu) self.context_menu = QMenu() self.addRow_action = self.context_menu.addAction('增加一行') self.addRow_action.triggered.connect(self.addRow) self.delRow_action = self.context_menu.addAction('删除一行') self.delRow_action.triggered.connect( lambda: self.model.removeRow(self.table_view.currentIndex().row())) self.addColumn_action = self.context_menu.addAction('增加一列') self.addColumn_action.triggered.connect(self.addColumn) self.delColumn_action = self.context_menu.addAction('删除一列') self.delColumn_action.triggered.connect( lambda: self.model.removeColumn(self.table_view.currentIndex(). column())) self.customContextMenuRequested.connect(self.rightMenuShow) #创建布局 layout = QVBoxLayout() layout.addWidget(self.menu) layout.addWidget(self.tool_bar) layout.addWidget(self.find_widget) layout.addWidget(self.table_view) layout.addWidget(self.status_bar) self.setLayout(layout) #关联信号 self.open.triggered.connect(self.triggeredOpen) self.save.triggered.connect(self.triggeredSave) self.tool_view.triggered.connect(self.triggeredView) self.statu_view.triggered.connect(self.triggeredView) # self.new.triggered.connect(self.triggeredNew) self.find.triggered.connect(self.triggeredFind) self.find_widget.search.triggered.connect(self.dataLocation) self.find_widget.down_aciton.triggered.connect(self.downAcitonLocation) self.find_widget.up_aciton.triggered.connect(self.upAcitonLocation) self.find_widget.close_aciton.triggered.connect(self.triggeredHideFind) self.find_widget.repalce_button.clicked.connect(self.onClickReplace) self.find_widget.repalceAll_button.clicked.connect( self.onClickReplaceAll) # self.setting.triggered.connect(self.triggeredSetting) #美化 icon = QIcon() icon.addPixmap(QPixmap('./image/打开.png'), QIcon.Normal, QIcon.Off) self.open.setIcon(icon) icon.addPixmap(QPixmap('./image/保存.png'), QIcon.Normal, QIcon.Off) self.save.setIcon(icon) # icon.addPixmap(QPixmap('./image/新建.png'), QIcon.Normal, QIcon.Off) # self.new.setIcon(icon) icon.addPixmap(QPixmap('./image/剪切.png'), QIcon.Normal, QIcon.Off) self.cut.setIcon(icon) icon.addPixmap(QPixmap('./image/复制.png'), QIcon.Normal, QIcon.Off) self.copy.setIcon(icon) icon.addPixmap(QPixmap('./image/粘贴.png'), QIcon.Normal, QIcon.Off) self.paste.setIcon(icon) icon.addPixmap(QPixmap('./image/查找1.png'), QIcon.Normal, QIcon.Off) self.find.setIcon(icon) # icon.addPixmap(QPixmap('./image/设置.png'), QIcon.Normal, QIcon.Off) # self.setting.setIcon(icon) # icon.addPixmap(QPixmap('./image/替换.png'), QIcon.Normal, QIcon.Off) # self.replace.setIcon(icon) def showProgress(self, msg): self.status_bar.showMessage(msg) def loadData(self, model): print('load...') self.model = model self.table_view.setModel(self.model) qApp.processEvents() def triggeredOpen(self): self.status_bar.showMessage('打开文件', 5000) self.dialog = QFileDialog() self.dialog.setFileMode(QFileDialog.AnyFile) dir = r'D:/Learn-python-notes/projects/demo/Work/TCM_DSAS/data' self.dialog.setDirectory(dir) self.dialog.setFilter(QDir.Files) if self.dialog.exec_(): try: file_name = self.dialog.selectedFiles()[0] #这里线程实例化一定要实例化成员变量,否则线程容易销毁 self.thread = ReaderExcelThread(file_name) self.thread.standarModel_signal.connect(self.loadData) self.thread.progressRate_signal.connect(self.showProgress) self.thread.finished_signal.connect(self.thread.quit) self.thread.start() # self.setting.setEnabled(True) except Exception as e: print(e) pass def triggeredSave(self): self.status_bar.showMessage('保存文件', 5000) file_path, _ = QFileDialog.getSaveFileName( self, '保存文件', './data', 'ALL Files(*);;xlsx(*.xlsx);;xls(*.xls);;csv(*.csv)') if file_path == '': return # 文件中写入数据 try: self.write_thread = WriteExcelThread(file_path, self.model) self.write_thread.start_signal.connect(self.showProgress) self.write_thread.end_signal.connect(self.write_thread.quit) self.write_thread.start() self.status_bar.showMessage('保存完毕!') except Exception as e: print(e) #状态栏与工具栏的显示和隐藏 def triggeredView(self, state): sender = self.sender().text() if sender == '工具栏': if state: self.tool_bar.show() else: self.tool_bar.hide() else: if state: self.status_bar.show() else: self.status_bar.hide() # def triggeredNew(self): # print('New') # pass def triggeredFind(self): self.find_widget.show() #重载信号,实现ESC隐藏查找窗口 def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: self.find_widget.hide() #聚焦到某个cell def positionFocus(self, x, y): self.table_view.verticalScrollBar().setSliderPosition(x) self.table_view.horizontalScrollBar().setSliderPosition(y) self.table_view.openPersistentEditor(self.model.index(x, y)) self.table_view.setFocus() #得到所以匹配项的位置 def dataLocation(self): self.changeCellColor() text = self.find_widget.line_edit1.text() self.res_pos = [] flag = 0 rows = self.model.rowCount() columns = self.model.columnCount() try: for row in range(rows): for column in range(columns): if text == self.model.index(row, column).data(): self.res_pos.append((row, column)) item = self.model.item(row, column) item.setBackground(QColor(255, 255, 0)) item.setForeground(QColor(255, 0, 0)) #转到到第一个匹配值的位置,并处于可编辑状态 if not flag: flag = 1 self.positionFocus(row, column) self.focus_pos = 0 except Exception as e: print(e) #向下跳转 def downAcitonLocation(self): cnt = len(self.res_pos) if cnt == 0 or self.focus_pos == cnt - 1: return try: self.table_view.closePersistentEditor( self.model.index(self.res_pos[self.focus_pos][0], self.res_pos[self.focus_pos][1])) x, y = self.res_pos[self.focus_pos + 1] self.positionFocus(x, y) self.focus_pos += 1 except Exception as e: print(e) # 向上跳转 def upAcitonLocation(self): cnt = len(self.res_pos) if cnt == 0 or self.focus_pos == 0: return try: self.table_view.closePersistentEditor( self.model.index(self.res_pos[self.focus_pos][0], self.res_pos[self.focus_pos][1])) x, y = self.res_pos[self.focus_pos - 1] self.positionFocus(x, y) self.focus_pos -= 1 except Exception as e: print(e) def triggeredHideFind(self): self.changeCellColor() self.find_widget.hide() def changeCellColor(self): if self.res_pos is not None and len(self.res_pos): self.table_view.closePersistentEditor( self.model.index(self.res_pos[self.focus_pos][0], self.res_pos[self.focus_pos][1])) for item in self.res_pos: x, y = item item = self.model.item(x, y) item.setBackground(QColor(255, 255, 255)) item.setForeground(QColor(0, 0, 0)) def onClickReplace(self): cnt = len(self.res_pos) text = self.find_widget.line_edit2.text() if self.res_pos is None or cnt == 0: return try: x, y = self.res_pos[self.focus_pos] self.model.setItem(x, y, QStandardItem(text)) except Exception as e: print(e) def onClickReplaceAll(self): cnt = len(self.res_pos) if self.res_pos is None or cnt == 0: return try: text = self.find_widget.line_edit2.text() for x, y in self.res_pos: self.model.setItem(x, y, QStandardItem(text)) except Exception as e: print(e) # #设置变量 # def triggeredSetting(self): # self.getVar_thread = GetVarThread(self.model) # self.getVar_thread.send_signal.connect(self.initVarList) # self.getVar_thread.end_signal.connect(self.getVar_thread.quit) # self.getVar_thread.start() # # # # def initVarList(self,var_list): # dialog = VariableSettingWindow.VariableSettingWindowDemo(var_list) # dialog.signal.sender.connect(self.getVarList) # dialog.show() # # def getVarList(self,lst): # self.var_list = lst # print(lst) def addRow(self): # 当前行的下方添加一行 try: self.model.insertRows(self.table_view.currentIndex().row() + 1, 1) except Exception as e: print(e) def addColumn(self): self.model.insertColumns(self.table_view.currentIndex().column() + 1, 1) def rightMenuShow(self): try: #菜单显示的位置 self.context_menu.popup(QCursor.pos()) self.context_menu.show() except Exception as e: print(e)
class CodeEditorTabWidget(QWidget): """ Widget which representing code editor with tabs. """ def __init__(self, parent=None): QWidget.__init__(self, parent) vertical_layout = QVBoxLayout() self.tab_widget = QTabWidget() self.tab_widget.setTabBar(TabBar()) self.tab_widget.setTabsClosable(True) self.tab_widget.setUsesScrollButtons(True) self.tab_widget.setMovable(True) self.tab_widget.tabCloseRequested.connect(self.close_tab) self.tab_widget.currentChanged.connect(self.tab_changed) self.editor_status_bar = QStatusBar(self) self.editor_status_bar.setStyleSheet("QStatusBar{border-bottom: 1px outset grey; border-left: 1px outset grey; border-right: 1px outset grey;}") self.editor_status_bar.hide() vertical_layout.setSpacing(0) vertical_layout.setContentsMargins(5, 22, 0, 0) vertical_layout.addWidget(self.tab_widget) vertical_layout.addWidget(self.editor_status_bar) self.setLayout(vertical_layout) self.opened_tabs = 0 def open_file(self, file_path: str) -> None: """ Open file in new tab. Args: file_path(str): file path """ with open(file_path, 'r') as f: code_editor = CodeEditorWidget(self) code_editor.load_file(f) code_editor.file_saved = True code_editor.opened_file = f.name self.add_tab(code_editor, os.path.basename(f.name)) def new_file(self) -> None: """ Create new tab / file """ code_editor = CodeEditorWidget(self) code_editor.file_saved = False self.add_tab(code_editor, "NoName") def save_file(self, file_path: str = None) -> None: """ Save current file(as). Args: file_path(str): if file path is not None. Save as method called """ file = file_path or self.get_current_file() current_widget = self.get_current_widget() with open(file, 'w') as f: f.write(current_widget.get_plain_text()) current_widget.opened_file = file current_widget.file_saved = True self.tab_changed() self.set_tab_text(os.path.basename(file)) def add_tab(self, code_editor: CodeEditorWidget, file_name: str) -> None: """ Add new tab to the widget. Args: code_editor(CodeEditorWidget): code editor widget in new tab file_name(str): name of new tab - file name """ new_index = self.tab_widget.count() self.tab_widget.addTab(code_editor, file_name) self.tab_widget.setCurrentIndex(new_index) self.opened_tabs += 1 def tab_changed(self) -> None: """ Change hide/show information in editor status bar. Update line and column in main status bar. This method is called when currentChanged signal is emitted. """ current_widget = self.get_current_widget() if not current_widget: self.editor_status_bar.hide() return else: self.editor_status_bar.showMessage(self.get_current_file() or "File not saved") self.editor_status_bar.show() current_widget.main_window.set_new_cursor_position(current_widget.get_cursor()) def set_tab_text(self, text: str, index: int = None) -> None: """ Set new text of current tab Args: text(str): new text index(int): index of tab. If None -> use current """ current_index = index or self.tab_widget.currentIndex() self.tab_widget.setTabText(current_index, text) def close_tab(self, index: int) -> None: """ Close tab at index. Args: index(int): index of tab """ self.tab_widget.removeTab(index) self.opened_tabs -= 1 def is_file_saved(self) -> bool: """ Return if file in current widget is saved. Returns: bool: True if file is save else False """ current_tab = self.get_current_widget() return current_tab.file_saved def get_current_widget(self) -> CodeEditorWidget: """ Return widget in current active tab Returns: CodeEditorWidget: Code editor in current tab """ return self.tab_widget.currentWidget() def get_current_file(self) -> str: """ Return file path of file in current active tab Returns: str: file path of file in active tab """ return self.get_current_widget().opened_file
class WidgetDemo(QWidget): def __init__(self,mode): super(WidgetDemo,self).__init__() self.mode = mode self.initUI(mode) def initUI(self,mode): self.resize(800,800) #这里初始化,便于直接输入数据 self.data = [['']*100 for i in range(15000)] self.res_pos = [] self.focus_pos = None self.var_list = None #菜单栏 self.menu = QMenuBar() self.file = self.menu.addMenu('文件') self.edit = self.menu.addMenu('编辑') self.view = self.menu.addMenu('视图') self.help = self.menu.addMenu('帮助') #各菜单下的子菜单 #文件菜单下的子菜单 self.new = self.file.addAction('新建') self.open = self.file.addAction('打开') self.save = self.file.addAction('保存') # self.save_as = self.file.addAction('另存为') #编辑菜单下的子菜单 self.cut = self.edit.addAction('剪切') self.copy = self.edit.addAction('复制') self.paste = self.edit.addAction('粘贴') self.delete = self.edit.addAction('删除') self.find = self.edit.addAction('查找') self.replace = self.edit.addAction('替换') # 快捷键 self.open.setShortcut('Ctrl+O') self.save.setShortcut('Ctrl+S') self.new.setShortcut('Ctrl+N') self.find.setShortcut('Ctrl+F') #视图菜单下的子菜单 self.tool_view = QAction('工具栏',checkable=True) self.tool_view.setChecked(True) self.view.addAction(self.tool_view) self.statu_view = QAction('状态栏',checkable=True) self.statu_view.setChecked(True) self.view.addAction(self.statu_view) #帮助菜单下的子菜单 self.about = self.help.addAction('关于') #工具栏 self.tool_bar = QToolBar() self.tool_bar.addAction(self.new) self.tool_bar.addAction(self.open) self.tool_bar.addAction(self.save) self.tool_bar.addAction(self.cut) self.tool_bar.addAction(self.copy) self.tool_bar.addAction(self.paste) self.tool_bar.addAction(self.find) self.setting = QAction('变量设置') self.setting.setEnabled(False) self.tool_bar.addAction(self.setting) # self.tool_bar.addAction(self.replace) # #tool文本显示在下方 # self.tool_bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) #findWidge self.find_widget = FindWidget() self.find_widget.hide() #表格 self.table_view = QTableView() self.table_view.setModel(self.mode) #状态栏 self.status_bar = QStatusBar() self.status_bar.showMessage('这是一个状态栏') #创建布局 layout = QVBoxLayout() layout.addWidget(self.menu) layout.addWidget(self.tool_bar) layout.addWidget(self.find_widget) layout.addWidget(self.table_view) layout.addWidget(self.status_bar) self.setLayout(layout) #关联信号 self.open.triggered.connect(self.triggeredOpen) self.save.triggered.connect(self.triggeredSave) self.mode.itemChanged.connect(self.dealItemChanged) self.tool_view.triggered.connect(self.triggeredView) self.statu_view.triggered.connect(self.triggeredView) self.new.triggered.connect(self.triggeredNew) self.find.triggered.connect(self.triggeredFind) self.find_widget.search.triggered.connect(self.dataLocation) self.find_widget.down.triggered.connect(self.downLocation) self.find_widget.up.triggered.connect(self.upLocation) self.find_widget.close.triggered.connect(self.triggeredHideFind) self.find_widget.repalce_button.clicked.connect(self.onClickReplace) self.find_widget.repalceAll_button.clicked.connect(self.onClickReplaceAll) self.setting.triggered.connect(self.triggeredSetting) #美化 icon = QIcon() icon.addPixmap(QPixmap('../image/打开.png'), QIcon.Normal, QIcon.Off) self.open.setIcon(icon) icon.addPixmap(QPixmap('../image/保存.png'), QIcon.Normal, QIcon.Off) self.save.setIcon(icon) icon.addPixmap(QPixmap('../image/新建.png'), QIcon.Normal, QIcon.Off) self.new.setIcon(icon) icon.addPixmap(QPixmap('../image/剪切.png'), QIcon.Normal, QIcon.Off) self.cut.setIcon(icon) icon.addPixmap(QPixmap('../image/复制.png'), QIcon.Normal, QIcon.Off) self.copy.setIcon(icon) icon.addPixmap(QPixmap('../image/粘贴.png'), QIcon.Normal, QIcon.Off) self.paste.setIcon(icon) icon.addPixmap(QPixmap('../image/查找1.png'), QIcon.Normal, QIcon.Off) self.find.setIcon(icon) icon.addPixmap(QPixmap('../image/设置.png'), QIcon.Normal, QIcon.Off) self.setting.setIcon(icon) # icon.addPixmap(QPixmap('../image/替换.png'), QIcon.Normal, QIcon.Off) # self.replace.setIcon(icon) def triggeredOpen(self): self.status_bar.showMessage('打开文件',5000) self.dialog = QFileDialog() self.dialog.setFileMode(QFileDialog.AnyFile) dir = r'../data' self.dialog.setDirectory(dir) self.dialog.setFilter(QDir.Files) if self.dialog.exec_(): try: start = time.time() file_name = self.dialog.selectedFiles()[0] #这里读取数据返回列表便于表格中数据的更新 data_list = read_xlsx(file_name) self.data = data_list self.mode = QStandardItemModel() for rows in data_list: row = [QStandardItem(str(cell)) for cell in rows] self.mode.appendRow(row) self.mode.itemChanged.connect(self.dealItemChanged) self.table_view.setModel(self.mode) # self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.table_view.resizeColumnsToContents() self.table_view.resizeRowsToContents() end = time.time() self.status_bar.showMessage('数据加载完毕,耗时{}秒'.format(end-start)) self.setting.setEnabled(True) except Exception as e: print(e) pass def triggeredSave(self): self.status_bar.showMessage('保存文件', 5000) file_path, _ = QFileDialog.getSaveFileName(self, '保存文件', '../data', 'ALL Files(*);;xlsx(*.xlsx);;xls(*.xls);;csv(*.csv)') if file_path == '': return # 文件中写入数据 try: wb = workbook.Workbook() wb.encoding = 'utf-8' wa = wb.active for item in self.data: # 过滤无效数据 try: if ''.join(item) == '': continue except: pass wa.append(item) wb.save(file_path) self.status_bar.showMessage('保存完毕!') except Exception as e: print(e) #数据变化信号处理 def dealItemChanged(self,item): try: row,column = item.row(),item.column() self.data[row][column] = item.text() except Exception as e: print(e) pass #状态栏与工具栏的显示和隐藏 def triggeredView(self,state): sender = self.sender().text() if sender == '工具栏': if state: self.tool_bar.show() else: self.tool_bar.hide() else: if state: self.status_bar.show() else: self.status_bar.hide() def triggeredNew(self): print('New') pass def triggeredFind(self): self.find_widget.show() #重载信号,实现ESC隐藏查找窗口 def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: self.find_widget.hide() #聚焦到某个cell def positionFocus(self,x,y): self.table_view.verticalScrollBar().setSliderPosition(x) self.table_view.horizontalScrollBar().setSliderPosition(y) self.table_view.openPersistentEditor(self.mode.index(x, y)) self.table_view.setFocus() #得到所以匹配项的位置 def dataLocation(self): text = self.find_widget.line_edit1.text() self.res_pos = [] flag = 0 for i,row in enumerate(self.data): try: if ''.join(row) == '': continue except: pass for j,cell in enumerate(row): if text == str(cell): # print(i,j) self.res_pos.append((i,j)) item = self.mode.item(i,j) item.setBackground(QColor(255, 255, 0)) item.setForeground(QColor(255, 0, 0)) #转到到第一个匹配值的位置,并处于可编辑状态 if not flag: flag = 1 self.positionFocus(i,j) self.focus_pos = 0 #向下跳转 def downLocation(self): cnt = len(self.res_pos) if cnt == 0 or self.focus_pos == cnt-1: return try: self.table_view.closePersistentEditor( self.mode.index(self.res_pos[self.focus_pos][0],self.res_pos[self.focus_pos][1])) x, y = self.res_pos[self.focus_pos + 1] self.positionFocus(x,y) self.focus_pos += 1 except Exception as e: print(e) # 向上跳转 def upLocation(self): cnt = len(self.res_pos) if cnt == 0 or self.focus_pos == 0: return try: self.table_view.closePersistentEditor( self.mode.index(self.res_pos[self.focus_pos][0], self.res_pos[self.focus_pos][1])) x, y = self.res_pos[self.focus_pos - 1] self.positionFocus(x, y) self.focus_pos -= 1 except Exception as e: print(e) def triggeredHideFind(self): if self.res_pos is not None and len(self.res_pos): self.table_view.closePersistentEditor( self.mode.index(self.res_pos[self.focus_pos][0], self.res_pos[self.focus_pos][1])) for item in self.res_pos: x,y = item item = self.mode.item(x,y) item.setBackground(QColor(255, 255, 255)) item.setForeground(QColor(0, 0, 0)) self.find_widget.hide() #不清楚如何修改cell值,替换功能暂时无法上线 def onClickReplace(self): print('-'*50) cnt = len(self.res_pos) if self.res_pos is None or cnt == 0: return try: x, y = self.res_pos[self.focus_pos] text = self.find_widget.line_edit2.text() self.data[x][y] = text print(self.data[x][y]) except Exception as e: print(e) def onClickReplaceAll(self): pass #设置变量 def triggeredSetting(self): # 设置变量窗口 var_list = self.data[0] if self.data[0][0]!='' else self.data[0][1:] self.dialog = VariableSettingWindow.VariableSettingWindowDemo(var_list) self.dialog.signal.sender.connect(self.getVarList) self.dialog.show() def getVarList(self,lst): self.var_list = lst
class PopUpWindow(QWidget): def __init__(self, pop_height, pop_width, pop_bombs): super().__init__() self.pop_height = pop_height self.pop_width = pop_width self.pop_bombs = pop_bombs self.valid_int = True self.pref_status = QStatusBar() self.pref_status_label = QLabel() self.pref_status.addWidget(self.pref_status_label) self.pref_status.hide() self.getVals() def getVals(self): self.height_label = QLabel("Height:") self.width_label = QLabel("Width:") self.bombs_label = QLabel("Bombs:") self.height_edit = QLineEdit(str(self.pop_height)) self.width_edit = QLineEdit(str(self.pop_width)) self.bombs_edit = QLineEdit(str(self.pop_bombs)) #grid for getting user input self.pref_grid = QGridLayout() self.pref_grid.setSpacing(10) self.pref_grid.addWidget(self.height_label, 1, 0) self.pref_grid.addWidget(self.height_edit, 1, 1) self.pref_grid.addWidget(self.width_label, 2, 0) self.pref_grid.addWidget(self.width_edit, 2, 1) self.pref_grid.addWidget(self.bombs_label, 3, 0) self.pref_grid.addWidget(self.bombs_edit, 3, 1) #Difficulty display buttons difficulty_box = QHBoxLayout() beg_button = QPushButton("Beginner") beg_button.clicked.connect(self.beg_push) int_button = QPushButton("Intermediate") int_button.clicked.connect(self.int_push) adv_button = QPushButton("Advanced") adv_button.clicked.connect(self.adv_push) difficulty_box.addWidget(beg_button) difficulty_box.addWidget(int_button) difficulty_box.addWidget(adv_button) #Ok and cancel buttons button_box = QHBoxLayout() ok_button = QPushButton("Ok") ok_button.clicked.connect(self.ok_push) cancel_button = QPushButton("Cancel") cancel_button.clicked.connect(self.cancel_push) button_box.addWidget(ok_button) button_box.addWidget(cancel_button) self.final_display = QVBoxLayout() self.final_display.addLayout(difficulty_box) self.final_display.addLayout(self.pref_grid) self.final_display.addLayout(button_box) self.final_display.addWidget(self.pref_status) #self.setLayout(self.pref_grid) self.setLayout(self.final_display) def ok_push(self): #print("Ok was clicked") #reset flag to true, then recheck all values before submitting self.valid_int = True self.check_int(self.height_edit.text()) self.check_int(self.width_edit.text()) self.check_int(self.bombs_edit.text()) if self.valid_int: #Make sure there are less bombs than number of squares if int(self.bombs_edit.text()) < (int(self.width_edit.text()) * int(self.height_edit.text())): #Make sure width and length are a positive numbr less than 50 if (int(self.width_edit.text()) in range(1, 51)) and (int( self.height_edit.text()) in range(1, 51)): self.pop_height = int(self.height_edit.text()) self.pop_width = int(self.width_edit.text()) self.pop_bombs = int(self.bombs_edit.text()) self.pref_status_label.setText("") self.pref_status.hide() #print("\n\n=================\npop_height:{}\npop_width:{}\npop_bombs:{}\n=================\n\n".format(self.pop_height, self.pop_width, self.pop_bombs)) self.close() else: self.pref_status.show() self.pref_status_label.setText( "Error: Board must have dimensions less than 50x50") else: self.pref_status.show() self.pref_status_label.setText("Error: Too many bombs") def cancel_push(self): #print("Cancel was clicked") self.pref_status.hide() self.close() ''' Beginner: H:9 W:9 B:10 Intermediate: H:16 W:16 B:40 Advanced: H:16 W:30 B:99 ''' def beg_push(self): #print("Beginner") self.pref_status.hide() self.height_edit.setText("9") self.width_edit.setText("9") self.bombs_edit.setText("10") def int_push(self): #print("Intermediate") self.pref_status.hide() self.height_edit.setText("16") self.width_edit.setText("16") self.bombs_edit.setText("40") def adv_push(self): #print("Advanced") self.pref_status.hide() self.height_edit.setText("16") self.width_edit.setText("30") self.bombs_edit.setText("99") def check_int(self, check_val): try: int(check_val) except ValueError: #print('{} is not able to become an int'.format(check_val)) self.valid_int = False #self.statusBar.showMessage("{} is not a valid entry.".format()) self.pref_status_label.setText( "{} is not a valid entry.".format(check_val)) self.pref_status.show() else: pass
class mainWindow(QMainWindow): def __init__(self,obj): super().__init__() self.setObjectName('Window1') self.obj=obj self.set=0 self.initUI() def initUI(self): self.resize(850,500) self.setWindowTitle('Moodly 1.0 Beta - Configure') self.setWindowIcon(QIcon(':/Assets/moodly.gif')) self.setFixedSize(830,500) self.center() self.sysTray=QWidget() self.tray = SystemTrayIcon(QIcon(':/Assets/moodly.gif'),self.sysTray) self.tray.show() self.tray.trigger.connect(self.showApp) self.tray.qtrigger.connect(self.closeApp) self.tray.uptrigger.connect(self.updateNow) self.setWidget() self.show() def setWidget(self): if self.obj.configured==0: self.setCentralWidget(configureWidget(self)) elif self.obj.configured==1: self.setCentralWidget(setupWidget(self)) elif self.obj.configured==2: self.setStyleSheet('''#Window1{background-color: light gray;}''') self.setWindowTitle('Moodly 1.0 Beta') self.setMenuBar() self.tabWidget = tabWidget(self) self.setCentralWidget(self.tabWidget) self.tray.updateAction.setEnabled(True) self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.statusBar.hide() self.statusLbl1 = QLabel() self.statusLbl2 = QLabel() self.statusLbl2.setAlignment(QtCore.Qt.AlignRight) self.statusBar.addWidget(self.statusLbl1) self.statusBar.addWidget(self.statusLbl2,QtCore.Qt.AlignRight) self.updateTimer() self.notifTimer() self.i_thread = {} self.nt=0 def showApp(self): if self.isMinimized(): self.showNormal() self.show() self.activateWindow() def closeApp(self): self.tray.hide() qApp.quit() def showStatus(self,msg,id_): if id_ == 0: self.statusLbl1.setText(msg) else: self.statusLbl2.setText(msg) self.statusBar.show() def hideStatus(self,id_): if id_==0: self.statusLbl1.setText('') else: self.statusLbl2.setText('') if self.statusLbl1.text() == '' and self.statusLbl2.text()=='': self.statusBar.hide() def updateTimer(self): self.current_timer = QTimer() delay = int(re.findall(r'\d+', self.obj.upIntval)[0]) delay = delay*60*60*1000 self.current_timer.timeout.connect(self.updater) self.current_timer.setSingleShot(True) if self.set==0: self.updater() else: self.current_timer.start(delay) def notifTimer(self): if self.obj.nIntval=="Turn Off": self.notifier = False else: delay = int(re.findall(r'\d+', self.obj.nIntval)[0])*60*60 self.timer1 = QTimer() self.timer1.timeout.connect(partial(self.quickNotify)) self.timer1.setSingleShot(True) self.timer1.start(10*60*1000) self.notifier= True def quickNotify(self): if self.obj.n !=0 and self.obj.updating==False: str_ = str(self.obj.n) self.tray.display_notify("Moodly","You have %s unread notifications"%str_,1) self.notifTimer() def quickStatus(self,i): if self.obj.updating==False: if i==0: self.showStatus('Next Update Scheduled at %s'%str(self.obj.scheduled)) self.timer2 = QTimer() self.timer2.timeout.connect(partial(self.quickStatus,1)) self.timer2.setSingleShot(True) self.timer2.start(6000) elif i==1: delay = int(re.findall(r'\d+', self.obj.upIntval)[0])*60*60 self.showStatus('Last Update Scheduled at %s'%str(self.obj.scheduled-datetime.timedelta(0,delay))+'Failed') self.timer2 = QTimer() self.timer2.timeout.connect(partial(self.quickStatus,2)) self.timer2.setSingleShot(True) self.timer2.start(6000) else: self.showStatus('Last Successful Update ') self.timer2 = QTimer() self.timer2.timeout.connect(self.hideStatus) self.timer2.setSingleShot(True) self.timer2.start(6000) self.statusTimer() def updater(self): self.obj.updating = True self.showStatus('Updating Moodly.....',0) self.thread=updateThread(self.obj) self.thread.finished.connect(self.downloader) self.thread.start() def downloader(self): if int(self.obj.dwnld)==1: self.showStatus('Downloading Files.....',0) self.dthread=downloadThread(self.obj) self.dthread.finished.connect(self.tabUpdater) self.dthread.start() else: self.tabUpdater() def closeEvent(self, event): self.hide() event.ignore() self.tray.display_notify('Moodly','Moodly running in notification tray.',1) def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def setMenuBar(self): exitAction = QAction(QIcon(':/Assets/close.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.triggered.connect(self.closeApp) self.alreadyOpen = 0 configAction = QAction(QIcon(':/Assets/setting.png'), '&Configure', self) configAction.triggered.connect(self.changeConfig) configAction.setShortcut('Ctrl+Shift+C') updateAction = QAction(QIcon(':/Assets/sync.png'), '&Update Now', self) updateAction.triggered.connect(self.updateNow) updateAction.setShortcut('Ctrl+U') menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(configAction) fileMenu.addAction(updateAction) fileMenu.addAction(exitAction) def updateNow(self): if self.obj.updating==False: self.current_timer.stop() self.current_timer.deleteLater() self.updater() else: reply = QMessageBox.information(self,'Moodly',"An update is already in progress. ", QMessageBox.Ok) if reply == QMessageBox.Ok: pass def changeConfig(self): if self.alreadyOpen is 0: self.tab = reConfigureWidget(self.tabWidget) self.tabWidget.addTab(self.tab,QIcon(':/Assets/setting.png'),'Configure') self.tabWidget.setTabToolTip(self.tabWidget.indexOf(self.tab),'Configure') self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(self.tab)) self.alreadyOpen=1 else: self.tabWidget.setCurrentIndex(self.tabWidget.indexOf(self.tab)) def verify(self): self.obj.saveConfig(1) self.thread=WorkThread(self.obj) self.thread.finished.connect(self.notify) self.thread.start() self.set=1 self.setWidget() def notify(self): self.setWidget() self.tray.display_notify("Moodly",self.obj.status_msg[0],self.obj.status_msg[1]) def tabUpdater(self): self.set=1 self.tabWidget.tab1.updater() self.tabWidget.tab2.updater() for tab in self.tabWidget.tab: tab.updater() self.obj.updating = False self.c_timer = QTimer() self.c_timer.timeout.connect(partial(self.hideStatus,0)) self.c_timer.setSingleShot(True) self.showStatus('Update Completed',0) self.c_timer.start(5000) self.tray.display_notify("Moodly",self.obj.status_msg[0],self.obj.status_msg[1]) self.updateTimer() def itemsWriter(self,fileName,id1,id2): nt=self.getIndex() self.i_thread[nt] = itemsWriterThread(fileName,id1,id2,nt,self.obj) self.i_thread[nt].finished.connect(partial(self.del_i_thread,self.i_thread[nt].id3)) self.i_thread[nt].start() def del_i_thread(self,id3): self.i_thread[id3]=0 def getIndex(self): if self.nt==0: return self.nt else: for i in range(0,self.nt): if self.i_thread[i]==0: return i self.nt+=1 return self.nt def configWriter(self,text1,text2,combo1,combo2,text3,path_): self.sid3=self.showStatus('Configuring...',1) self.c_thread = configWriterThread(self.obj,text1,text2,combo1,combo2,text3,path_) self.c_thread.finished.connect(self.reConfigModify) self.c_thread.start() def reConfigModify(self): if self.alreadyOpen==1: self.tab.status_label.setText(self.obj.config_status) self.tray.display_notify("Moodly",self.obj.status_msg[0],self.obj.status_msg[1]) self.re_timer = QTimer() self.re_timer.timeout.connect(partial(self.hideStatus,1)) self.re_timer.setSingleShot(True) self.showStatus(self.obj.config_status,1) self.re_timer.start(5000) self.tabWidget.updating = False if self.obj.intValChanged ==0: self.current_timer.stop() self.current_timer.deleteLater() self.updateTimer() self.obj.intValChanged = -1 elif self.obj.intValChanged ==1: if self.notifier == True: self.timer1.stop() self.timer1.deleteLater() self.notifTimer() self.obj.intValChanged = -1 elif self.obj.intValChanged ==2: self.current_timer.stop() self.current_timer.deleteLater() self.updateTimer() if self.notifier == True: self.timer1.stop() self.timer1.deleteLater() self.notifTimer() self.obj.intValChanged = -1