def contextMenuEvent(self, evt): """ Protected method handling context menu events. @param evt reference to the context menu event (QContextMenuEvent) """ point = evt.globalPos() if self.__browser: point = self.__browser.mapFromGlobal(point) if not self.__browser.rect().contains(point, True): return link = QUrl(self.__browser.anchorAt(point)) else: point = self.__result.mapFromGlobal(point) link = self.__result.linkAt(point) if link.isEmpty() or not link.isValid(): return menu = QMenu() curTab = menu.addAction(self.tr("Open Link")) newTab = menu.addAction(self.tr("Open Link in New Tab")) menu.move(evt.globalPos()) act = menu.exec_() if act == curTab: self.linkActivated.emit(link) elif act == newTab: self.__mw.newTab(link)
def showContextMenu(self, pos): self._cachedPos = pos menu = QMenu(self.parent()) menu.addAction("Add Anchor…", self._createAnchor) menu.addAction("Add Component…", self._createComponent) menu.exec_(self._cachedPos) self._cachedPos = None
def contextMenuEvent(self, event): menu = QMenu(self) local_filename = self.currentItem().text() # Get the file extension ext = os.path.splitext(local_filename)[1].lower() open_internal_action = None # Mu micro:bit mode only handles .py & .hex if ext == '.py' or ext == '.hex': open_internal_action = menu.addAction(_("Open in Mu")) # Open outside Mu (things get meta if Mu is the default application) open_action = menu.addAction(_("Open")) action = menu.exec_(self.mapToGlobal(event.pos())) if action == open_action: # Get the file's path path = os.path.join(self.home, local_filename) logger.info("Opening {}".format(path)) msg = _("Opening '{}'").format(local_filename) logger.info(msg) self.set_message.emit(msg) # Let Qt work out how to open it QDesktopServices.openUrl(QUrl.fromLocalFile(path)) elif action == open_internal_action: logger.info("Open {} internally".format(local_filename)) # Get the file's path path = os.path.join(self.home, local_filename) # Send the signal bubbling up the tree self.open_file.emit(path)
def slot_transportViewMenu(self): menu = QMenu(self) actHMS = menu.addAction("Hours:Minutes:Seconds") actBBT = menu.addAction("Beat:Bar:Tick") actFrames = menu.addAction("Frames") actHMS.setCheckable(True) actBBT.setCheckable(True) actFrames.setCheckable(True) if self.fCurTransportView == TRANSPORT_VIEW_HMS: actHMS.setChecked(True) elif self.fCurTransportView == TRANSPORT_VIEW_BBT: actBBT.setChecked(True) elif self.fCurTransportView == TRANSPORT_VIEW_FRAMES: actFrames.setChecked(True) actSelected = menu.exec_(QCursor().pos()) if actSelected == actHMS: self.setTransportView(TRANSPORT_VIEW_HMS) elif actSelected == actBBT: self.setTransportView(TRANSPORT_VIEW_BBT) elif actSelected == actFrames: self.setTransportView(TRANSPORT_VIEW_FRAMES)
class CurrentPlaylistTable(MusicTable): remove_signal = pyqtSignal([int]) # song id def __init__(self, app): super().__init__(app) self._app = app self._row = 0 self.menu = QMenu() self.remove = QAction('从当前列表中移除', self) self.menu.addAction(self.remove) self.remove.triggered.connect(self.remove_song) def contextMenuEvent(self, event): point = event.pos() item = self.itemAt(point) if item is not None: row = self.row(item) self._row = row self.menu.exec(event.globalPos()) def remove_song(self): song = self.songs[self._row] self.songs.pop(self._row) self.removeRow(self._row) self.remove_signal.emit(song.mid)
def __init__(self, project, settings): QWidget.__init__(self) self.ui = Ui_ProjectWidget() self.ui.setupUi(self) self.project = project self.project.filesChanged.connect(self.refresh) self.toolbar = QToolBar() import_image = lambda: ImportImage.pick(lambda f: self.import_image.emit(f[0]), settings) self.toolbar.addAction(ImportImage.icon(), ImportImage.ACTION_TEXT, import_image) self.ui.import_image.clicked.connect(import_image) self.raw_spectra_model = QStandardItemModel() self.calibrated_spectra_model = QStandardItemModel() self.finished_spectra_model = QStandardItemModel() def button_action(button, signal, widget, model): button.clicked.connect(lambda: signal.emit(model.item(widget.selectionModel().selectedRows()[0].row()).data() ) ) widget.selectionModel().selectionChanged.connect(lambda sel, unsel: button.setEnabled(len(sel.indexes())>0)) for model, widget in [(self.raw_spectra_model, self.ui.raw_spectra), (self.calibrated_spectra_model, self.ui.calibrated_spectra), (self.finished_spectra_model, self.ui.finished_spectra)]: widget.setModel(model) widget.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) button_action(self.ui.calibrate, self.calibrate, self.ui.raw_spectra, self.raw_spectra_model) button_action(self.ui.math, self.math, self.ui.calibrated_spectra, self.calibrated_spectra_model) button_action(self.ui.finish, self.finish, self.ui.calibrated_spectra, self.calibrated_spectra_model) button_action(self.ui.open_finished, self.finish, self.ui.finished_spectra, self.finished_spectra_model) open_finished_menu = QMenu() self.ui.open_finished_dirs.setMenu(open_finished_menu) open_finished_menu.addAction(QIcon(':/image_20'), 'Exported Images folder', lambda: QDesktopServices.openUrl(QUrl.fromLocalFile(project.directory_path(Project.EXPORTED_IMAGES)))) open_finished_menu.addAction(QIcon(':/done_20'), 'Finished Spectra folder', lambda: QDesktopServices.openUrl(QUrl.fromLocalFile(project.directory_path(Project.FINISHED_PROFILES)))) self.refresh()
def contextMenuEvent(self, event): # Update selection self.updateSelection() # Set context menu mode app = get_app() app.context_menu_object = "files" menu = QMenu(self) menu.addAction(self.win.actionImportFiles) menu.addAction(self.win.actionDetailsView) if self.selected: # If file selected, show file related options menu.addSeparator() menu.addAction(self.win.actionPreview_File) menu.addAction(self.win.actionSplitClip) menu.addAction(self.win.actionAdd_to_Timeline) menu.addAction(self.win.actionFile_Properties) menu.addSeparator() menu.addAction(self.win.actionRemove_from_Project) menu.addSeparator() # Show menu menu.exec_(QCursor.pos())
def __init__(self): super(MainWindow, self).__init__() fileMenu = QMenu("&File", self) openAction = fileMenu.addAction("&Open...") openAction.setShortcut("Ctrl+O") saveAction = fileMenu.addAction("&Save As...") saveAction.setShortcut("Ctrl+S") quitAction = fileMenu.addAction("E&xit") quitAction.setShortcut("Ctrl+Q") self.setupModel() self.setupViews() openAction.triggered.connect(self.openFile) saveAction.triggered.connect(self.saveFile) quitAction.triggered.connect(QApplication.instance().quit) self.menuBar().addMenu(fileMenu) self.statusBar() self.openFile(':/Charts/qtdata.cht') self.setWindowTitle("Chart") self.resize(870, 550)
def create_context_menu(self) -> QMenu: menu = QMenu(self) index = self.model().mapToSource(self.currentIndex()) # type: QModelIndex if index.isValid(): current_index_info = self.model().sourceModel().fileInfo(index) # type: QFileInfo if current_index_info.isDir(): if os.path.isfile(os.path.join(current_index_info.filePath(), constants.PROJECT_FILE)): open_action = menu.addAction("Open project") open_action.setIcon(QIcon(":/icons/data/icons/appicon.png")) else: open_action = menu.addAction("Open folder") open_action.setIcon(QIcon.fromTheme("folder-open")) open_action.triggered.connect(self.on_open_action_triggered) new_dir_action = menu.addAction("New folder") new_dir_action.setIcon(QIcon.fromTheme("folder")) new_dir_action.triggered.connect(self.create_directory) del_action = menu.addAction("Delete") del_action.setIcon(QIcon.fromTheme("edit-delete")) del_action.triggered.connect(self.remove) menu.addSeparator() open_in_explorer_action = menu.addAction("Open in file manager...") open_in_explorer_action.triggered.connect(self.on_open_explorer_action_triggered) return menu
class Add_to_playlist_btn(QPushButton): def __init__(self): super().__init__('+') self.setToolTip('添加到歌单') self.menu = QMenu() self.playlists = [] def mousePressEvent(self, event): self.set_playlists_options() self.menu.exec(event.globalPos()) def set_playlists_options(self): playlists = ControllerApi.api.get_user_playlist() if not ControllerApi.api.is_response_ok(playlists): return self.playlists = playlists self.menu.clear() for playlist in playlists: if ControllerApi.api.is_playlist_mine(playlist): name = playlist['name'] pid = playlist['id'] action = QAction(name, self) action.triggered.connect(partial(self.add_to_playlist, pid)) self.menu.addAction(action) def add_to_playlist(self, pid): if not ControllerApi.state['current_mid']: return False flag = ControllerApi.api.add_song_to_playlist(ControllerApi.state['current_mid'], pid) if flag: ControllerApi.notify_widget.show_message('◕◡◔', '加入歌单成功') else: ControllerApi.notify_widget.show_message('◕◠◔', '加入歌单失败, 可能早已在列表了哦')
def cb_backends(self): self.cb_backends = QComboBox() self.cb_backends.addItem('Auto') menuLyricSource = QMenu(self.ui.menuEdit) menuLyricSource.setTitle('Lyric source') self.lyricGroup = QActionGroup(self) def addAction(name, checked=False): action = QAction(name, self) action.setText(name) action.setCheckable(True) action.setChecked(checked) action.setActionGroup(self.lyricGroup) return action menuLyricSource.addAction(addAction('Auto', True)) menuLyricSource.addSeparator() menuLyricSource.triggered.connect(self._menu_backend_change) for backend in Pyrics.get_backends(): menuLyricSource.addAction(addAction(backend.__name__)) self.cb_backends.addItem(backend.__name__) self.ui.menuEdit.addMenu(menuLyricSource) self.ui.toolBar.addWidget(self.cb_backends) self.cb_backends.currentIndexChanged.connect(self._cb_backend_change)
def _treeContextMenu(self, point): """ Context menu on the tree. This allows for quick access to adding and cloning nodes. Input: point[QPoint]: Point where the context menu was requested """ item = self.itemAt(point) if not item: return block = self._item_block_map.get(item) if not block: return if not block.star and not block.user_added: return menu = QMenu() menu.addAction(self.add_action) if block.star: self.add_action.setText("Add") else: self.add_action.setText("Clone") menu.addAction(self.remove_action) result = menu.exec_(self.mapToGlobal(point)) if result == self.add_action: self.copyBlock(block) elif result == self.remove_action: text = "Are you sure you want to delete %s" % block.path button = QMessageBox.question(self, "Confirm remove", text, QMessageBox.Yes, QMessageBox.No) if button == QMessageBox.Yes: self.removeBlock(block)
def contextMenuEvent(self, event): from_index = self._table.indexAt(event.pos()) if not (0 <= from_index.row() < self.model.rowCount()): return # The context menu event is the same regardless of the selected column # Therefore ColumnID is set such that the label name is retrieved from_index_to_name = self.model.index(from_index.row(), LabelListModel.ColumnID.Name) from_name = self.model.data(from_index_to_name, Qt.DisplayRole) menu = QMenu(parent=self) menu.addAction( "Clear {}".format(from_name), partial(self.clearRequested.emit, from_index_to_name.row(), str(from_name)) ) if self.support_merges and self.allowDelete: for to_row in range(self.model.rowCount()): to_index = self.model.index(to_row, LabelListModel.ColumnID.Name) to_name = self.model.data(to_index, Qt.DisplayRole) action = menu.addAction( "Merge {} into {}".format( from_name, to_name ), partial( self.mergeRequested.emit, from_index_to_name.row(), str(from_name), to_row, str(to_name)) ) if to_row == from_index_to_name.row(): action.setEnabled(False) menu.exec_( self.mapToGlobal(event.pos()) )
def __init__(self, parent=None): super(ZMQPublisherInfoWidget, self).__init__(parent) ui_class, widget_class = uic.loadUiType(os.path.split(__file__)[0] + "/zmqPubSubInfoWidget.ui") self.ui = ui_class() self.ui.setupUi(self) self.status = { "pub": { "address": None, "running": False }, "sub": { "address": None, "running": False } } self.ui.toggleSubStatus.clicked.connect(partial(self.ui.toggleSubStatus.setEnabled, False)) self.ui.togglePubStatus.clicked.connect(partial(self.ui.togglePubStatus.setEnabled, False)) self.ui.toggleSubStatus.clicked.connect(self.subStatusToggled.emit) self.ui.togglePubStatus.clicked.connect(self.pubStatusToggled.emit) menu = QMenu("options") self.change_pub_addr_action = menu.addAction("Change Address", self.changePubAddress.emit) self.ui.togglePubStatus.setMenu(menu) menu = QMenu("options") self.change_sub_addr_action = menu.addAction("Change Address", self.changeSubAddress.emit) self.ui.toggleSubStatus.setMenu(menu) self.status_style = "background-color: %s; border: 3px inset gray; padding: 5px"
def contextMenuEvent(self, event): menu = QMenu() removeAction = menu.addAction(QA.translate('QOcrWidget', "Remove")) #Action = menu.addAction(self.scene().tr("Remove")) menu.addSeparator() textAction = menu.addAction(QA.translate('QOcrWidget', "Text")) graphicsAction = menu.addAction(QA.translate('QOcrWidget', "Graphics")) ## verification of the type of the selection and ## setting a check box near the type that is in use textAction.setCheckable(True) graphicsAction.setCheckable(True) if self.kind == 1: textAction.setChecked(True) elif self.kind == 2: graphicsAction.setChecked(True) selectedAction = menu.exec_(event.screenPos()) if selectedAction == removeAction: self.scene().removeArea(self) elif selectedAction == textAction: self.kind = 1 elif selectedAction == graphicsAction: self.kind = 2
def createSubMenu(self, menu, view, hitTestResult): """ Public method to create the personal information sub-menu. @param menu reference to the main menu (QMenu) @param view reference to the view (HelpBrowser) @param hitTestResult reference to the hit test result (QWebHitTestResult) """ self.__view = view self.__element = hitTestResult.element() if not hitTestResult.isContentEditable(): return if not self.__loaded: self.__loadSettings() submenu = QMenu(self.tr("Insert Personal Information"), menu) submenu.setIcon(UI.PixmapCache.getIcon("pim.png")) for key, info in sorted(self.__allInfo.items()): if info: act = submenu.addAction( self.__translations[key], self.__insertData) act.setData(info) submenu.addSeparator() submenu.addAction(self.tr("Edit Personal Information"), self.showConfigurationDialog) menu.addMenu(submenu) menu.addSeparator()
def create_context_menu_window(self, tabWidget, window): ctrlMenu = QMenu("") title_action = QAction('Window menu', tabWidget) title_action.setDisabled(True) sep_action = QAction('',tabWidget) sep_action.setSeparator(True) sep_action2 = QAction('',tabWidget) sep_action2.setSeparator(True) dock_action = QAction('Dock Window',tabWidget) dock_action.triggered.connect(lambda ignore, area=tabWidget, window = window : self.cmenu_dock_window(area,window)) rename_win_action = QAction('Rename Window',self.tabWidget) rename_win_action.triggered.connect(lambda ignore, window = window : self.cmenu_rename_wind(window)) bg_action = QAction('Set background',tabWidget) bg_action.triggered.connect(lambda ignore, wind = window : self.cmenu_set_bg_window(wind)) ctrlMenu.addAction(title_action) ctrlMenu.addAction(sep_action) ctrlMenu.addAction(dock_action) ctrlMenu.addAction(sep_action2) ctrlMenu.addAction(rename_win_action) ctrlMenu.addAction(bg_action) return ctrlMenu
def addShowActions(self): """Adds a submenu giving access to the (other) opened viewer documents""" mds = self._actionCollection.viewer_document_select docs = mds.viewdocs() document_actions = {} multi_docs = len(docs) > 1 if self._panel.widget().currentViewdoc(): current_doc_filename = self._panel.widget().currentViewdoc().filename() m = self._menu sm = QMenu(m) sm.setTitle(_("Show...")) sm.setEnabled(multi_docs) ag = QActionGroup(m) ag.triggered.connect(self._panel.slotShowViewdoc) for d in docs: action = QAction(sm) action.setText(d.name()) action._document_filename = d.filename() # TODO: Tooltips aren't shown by Qt (it seems) action.setToolTip(d.filename()) action.setCheckable(True) action.setChecked(d.filename() == current_doc_filename) ag.addAction(action) sm.addAction(action) m.addSeparator() m.addMenu(sm)
def __init__(self): super(MainWindow, self).__init__() fileMenu = QMenu("&File", self) newAction = fileMenu.addAction("&New...") newAction.setShortcut("Ctrl+N") self.printAction = fileMenu.addAction("&Print...", self.printFile) self.printAction.setShortcut("Ctrl+P") self.printAction.setEnabled(False) quitAction = fileMenu.addAction("&Exit") quitAction.setShortcut("Ctrl+Q") helpMenu = QMenu("&Help", self) aboutAction = helpMenu.addAction("&About") self.menuBar().addMenu(fileMenu) self.menuBar().addMenu(helpMenu) self.solvers = QTabWidget() self.solvers.setTabsClosable(True) self.solvers.tabCloseRequested.connect(self.closeTab) newAction.triggered.connect(self.openDialog) quitAction.triggered.connect(self.close) aboutAction.triggered.connect(self.openAbout) self.setCentralWidget(self.solvers) self.setWindowTitle("Pulppy Software")
def init_stat_bar(self): self.status_bar = self.statusBar() self.status_bar.setMaximumHeight(20) self.status_bar.setSizeGripEnabled(False) self.stat_info = QLabel() self.stat_info.setIndent(5) self.sort_main = QAction("Asc", self) sort_menu = QMenu() self.sort_main.setMenu(sort_menu) s_by_title = QAction("Title", sort_menu) s_by_artist = QAction("Artist", sort_menu) sort_menu.addAction(s_by_title) sort_menu.addAction(s_by_artist) self.status_bar.addPermanentWidget(self.stat_info) #self.status_bar.addAction(self.sort_main) self.temp_msg = QLabel() self.temp_timer = QTimer() self.manga_list_view.gallery_model.ROWCOUNT_CHANGE.connect(self.stat_row_info) self.manga_list_view.gallery_model.db_emitter.COUNT_CHANGE.connect(self.stat_row_info) self.manga_list_view.gallery_model.STATUSBAR_MSG.connect(self.stat_temp_msg) self.manga_list_view.STATUS_BAR_MSG.connect(self.stat_temp_msg) self.manga_table_view.STATUS_BAR_MSG.connect(self.stat_temp_msg) self.stat_row_info() app_constants.STAT_MSG_METHOD = self.stat_temp_msg
def __init__(self, **kwargs): super(SearchOptionsButton, self).__init__(**kwargs) self.setText(self.tr('Options')) menu = QMenu() self.actionCi = menu.addAction(self.tr('Case insensitive')) menu.addSeparator() self.actionFormat = QActionGroup(self) self.actionPlain = menu.addAction(self.tr('Plain text')) self.actionPlain.setEnabled(False) self.actionRe = menu.addAction(self.tr('Regular expression')) self.actionGlob = menu.addAction(self.tr('Glob pattern')) self.actionGlob.setEnabled(False) self.actionFormat.addAction(self.actionPlain) self.actionFormat.addAction(self.actionRe) self.actionFormat.addAction(self.actionGlob) self.actionRoot = menu.addAction(self.tr('Search in best root dir')) for act in [self.actionCi, self.actionRe, self.actionPlain, self.actionGlob, self.actionRoot]: act.setCheckable(True) self.actionRe.setChecked(True) self.setMenu(menu)
def create_context_menu(self) -> QMenu: menu = QMenu() if self.context_menu_pos is None: return menu selected_label_index = self.model().get_selected_label_index(row=self.rowAt(self.context_menu_pos.y()), column=self.columnAt(self.context_menu_pos.x())) if self.model().row_count > 0: if selected_label_index == -1: label_action = menu.addAction("Create label...") label_action.setIcon(QIcon.fromTheme("list-add")) else: label_action = menu.addAction("Edit label...") label_action.setIcon(QIcon.fromTheme("configure")) label_action.triggered.connect(self.on_create_or_edit_label_action_triggered) menu.addSeparator() zoom_menu = menu.addMenu("Zoom font size") zoom_menu.addAction(self.zoom_in_action) zoom_menu.addAction(self.zoom_out_action) zoom_menu.addAction(self.zoom_original_action) menu.addSeparator() return menu
class ValueDomainNodeInfo(PredicateNodeInfo): """ This class implements the information box for the Value Domain node. """ def __init__(self, mainwindow, parent=None): """ Initialize the Value Domain node information box. """ super().__init__(mainwindow, parent) self.datatypeKey = Key('Datatype', self) self.datatypeMenu = QMenu(self) for action in self.mainwindow.actionsChangeValueDomainDatatype: self.datatypeMenu.addAction(action) self.datatypeButton = Button() self.datatypeButton.setMenu(self.datatypeMenu) self.datatypeButton.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.nodePropLayout.addRow(self.datatypeKey, self.datatypeButton) def updateData(self, node): """ Fetch new information and fill the widget with data. :type node: AbstractNode """ super().updateData(node) datatype = node.datatype for action in self.mainwindow.actionsChangeValueDomainDatatype: action.setChecked(action.data() is datatype) self.datatypeButton.setText(datatype.value)
class ApplicationWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setWindowTitle("application main window") self.file_menu = QMenu('&File', self) self.file_menu.addAction('&Quit', self.fileQuit, QtCore.Qt.CTRL + QtCore.Qt.Key_Q) self.menuBar().addMenu(self.file_menu) self.help_menu = QMenu('&Help', self) self.menuBar().addSeparator() self.menuBar().addMenu(self.help_menu) self.main_widget = QWidget(self) l = QVBoxLayout(self.main_widget) sc = MyStaticMplCanvas(self.main_widget, width=5, height=4, dpi=100) dc = MyDynamicMplCanvas(self.main_widget, width=5, height=4, dpi=100) l.addWidget(sc) l.addWidget(dc) self.main_widget.setFocus() self.setCentralWidget(self.main_widget) self.statusBar().showMessage("All hail matplotlib!", 2000) def fileQuit(self): self.close() def closeEvent(self, ce): self.fileQuit()
def show_id_context_menu(self, position): current_id = -1 try: current_id = int(self.__ui.lbl_uav_id.text()) except Exception: #print("Don't show the menu") return menu = QMenu() menu.addAction("Show Mission for " + str(current_id)) menu.addAction("Show Fence for " + str(current_id)) global_position = self.__ui.lbl_uav_id.mapToGlobal(position) selectedItem = menu.exec(global_position) if selectedItem.text()[0:12] == "Show Mission": if self.fetching_mission_for == -1: #prevent concurrent fetches self.fetching_mission_for = current_id self.wpFetchThread = WaypointFetchThread(self, self.__hm_state, current_id) self.wpFetchThread.start() elif self.fetching_mission_for != current_id: QMessageBox.error(self, "Still fetching waypoints for " + str(current_id), "Still fetching waypoints for " + str(current_id) + "\n\nCan't fetch multiple waypoints concurrently. Wait a few more seconds for the previous fetch operation to finish.") return elif selectedItem.text()[0:10] == "Show Fence": self.fenFetchThread = FenceFetchThread(self, self.__hm_state, current_id) self.fenFetchThread.start()
def buildWidget(self): layout = QHBoxLayout(self) layout.setContentsMargins(0,0,0,0) SettingMenu = QMenu() exitButton = QAction(QIcon('exit24.png'), 'Set As High', self) exitButton.triggered.connect(self.setHigh) SettingMenu.addAction(exitButton) setlowButton = QAction(QIcon('exit24.png'), 'Set As Low', self) setlowButton.triggered.connect(self.setLow) SettingMenu.addAction(setlowButton) self.tb_down = QToolButton() self.tb_down.pressed.connect(self.on_click_down) self.tb_down.released.connect(self.on_released) self.tb_down.setArrowType(Qt.LeftArrow) self.tb_up = QToolButton() self.tb_up.pressed.connect(self.on_click_up) self.tb_up.released.connect(self.on_released) self.tb_up.setArrowType(Qt.RightArrow) if self.showToggleButton: tb_set = QToolButton() tb_set.clicked.connect(self.on_click_set_value) tb_set.setText('<>') if self.showSettingMenu: tb_set.setMenu(SettingMenu) tb_set.setPopupMode(QToolButton.DelayedPopup) layout.addWidget(self.tb_down) layout.addWidget(self.bar) layout.addWidget(self.tb_up) if self.showToggleButton: layout.addWidget(tb_set) layout.setSpacing(0)
def create_context_menu(self): menu = QMenu() menu.setToolTipsVisible(True) self._add_zoom_actions_to_menu(menu) if self.something_is_selected: filter_bw = Filter.read_configured_filter_bw() text = self.tr("Apply bandpass filter (filter bw={0:n})".format(filter_bw)) create_from_frequency_selection = menu.addAction(text) create_from_frequency_selection.triggered.connect(self.on_create_from_frequency_selection_triggered) create_from_frequency_selection.setIcon(QIcon.fromTheme("view-filter")) try: cancel_button = " or ".join(k.toString() for k in QKeySequence.keyBindings(QKeySequence.Cancel)) except Exception as e: logger.debug("Error reading cancel button: " + str(e)) cancel_button = "Esc" create_from_frequency_selection.setToolTip("You can abort filtering with <b>{}</b>.".format(cancel_button)) configure_filter_bw = menu.addAction(self.tr("Configure filter bandwidth...")) configure_filter_bw.triggered.connect(self.on_configure_filter_bw_triggered) configure_filter_bw.setIcon(QIcon.fromTheme("configure")) menu.addSeparator() export_fta_action = menu.addAction("Export spectrogram...") export_fta_action.triggered.connect(self.on_export_fta_action_triggered) return menu
def open_pl_menu(self, position): menu = QMenu() # if len(self.combo_pl_names) > 0: play_now = menu.addAction("Play this playlist now") pl_now_icon = QIcon() pl_now_icon.addPixmap(QPixmap(":icons/play.png"), QIcon.Normal, QIcon.Off) play_now.setIcon(pl_now_icon) add_to_current = menu.addAction("Add this playlist to Now Playing") add_curr_icon = QIcon() add_curr_icon.addPixmap(QPixmap(":icons/add.png"), QIcon.Normal, QIcon.Off) add_to_current.setIcon(add_curr_icon) new_playlist = menu.addAction("Add New Playlist") new_pl_icon = QIcon() new_pl_icon.addPixmap(QPixmap(":icons/playlist_add.png"), QIcon.Normal, QIcon.Off) new_playlist.setIcon(new_pl_icon) create_from_albums = menu.addAction("Create play lists from Album names") create_icon = QIcon() create_icon.addPixmap(QPixmap(":icons/book_cd.png"), QIcon.Normal, QIcon.Off) create_from_albums.setIcon(create_icon) if len(self.combo_pl_names) <= 0: play_now.setEnabled(False) add_to_current.setEnabled(False) action = menu.exec_(self.combo_pl_names.mapToGlobal(position)) if action == play_now: # print("Play this one now :- " + self.combo_pl_names.currentText()) my_func.play_list_now(self) if action == add_to_current: # print("Add this one to Now Playing :- " + self.combo_pl_names.currentText()) my_func.add_play_list_to_now(self) if action == new_playlist: # print("I want to add a new playlist") my_func.add_new_playlist(self) if action == create_from_albums: # print("Create play lists from Album names") my_func.make_playlists_from_albums(self)
class PredicateNodeInfo(NodeInfo): """ This class implements the information box for predicate nodes. """ def __init__(self, mainwindow, parent=None): """ Initialize the predicate node information box. """ super().__init__(mainwindow, parent) self.brushKey = Key('Color', self) self.brushMenu = QMenu(self) for action in self.mainwindow.actionsChangeNodeBrush: self.brushMenu.addAction(action) self.brushButton = Button() self.brushButton.setMenu(self.brushMenu) self.brushButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.nodePropLayout.addRow(self.brushKey, self.brushButton) def updateData(self, node): """ Fetch new information and fill the widget with data. :type node: AbstractNode """ super().updateData(node) for action in self.mainwindow.actionsChangeNodeBrush: color = action.data() brush = QBrush(QColor(color.value)) if node.brush == brush: self.brushButton.setIcon(ColoredIcon(12, 12, color.value, '#000000')) self.brushButton.setText(color.value) break
class Systray(QObject): trayIconMenu = None def __init__(self, parent): super().__init__(parent) self.trayIconMenu = QMenu(None) icon = QIcon(":/image/thunder.ico") self.trayIcon = CompatSystemTrayIcon(self) self.trayIcon.setIcon(icon) self.trayIcon.setContextMenu(self.trayIconMenu) self.trayIcon.setVisible(True) self.trayIcon.activated.connect(self.slotSystrayActivated) self.trayIconMenu.addAction(app.mainWin.action_exit) @pyqtSlot(QSystemTrayIcon.ActivationReason) def slotSystrayActivated(self, reason): if reason == QSystemTrayIcon.Context: # right pass elif reason == QSystemTrayIcon.MiddleClick: # middle pass elif reason == QSystemTrayIcon.DoubleClick: # double click pass elif reason == QSystemTrayIcon.Trigger: # left if app.mainWin.isHidden() or app.mainWin.isMinimized(): app.mainWin.restore() else: app.mainWin.minimize()
def _addVCSMenu(self, mainMenu): """ Protected method used to add the VCS menu to all project browsers. @param mainMenu reference to the menu to be amended """ self.vcsMenuActions = [] self.vcsAddMenuActions = [] menu = QMenu(self.tr("Version Control")) act = menu.addAction( UI.PixmapCache.getIcon( os.path.join("VcsPlugins", "vcsPySvn", "icons", "pysvn.png")), self.vcs.vcsName(), self._VCSInfoDisplay) font = act.font() font.setBold(True) act.setFont(font) menu.addSeparator() act = menu.addAction(UI.PixmapCache.getIcon("vcsUpdate.png"), self.tr('Update from repository'), self._VCSUpdate) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsCommit.png"), self.tr('Commit changes to repository...'), self._VCSCommit) self.vcsMenuActions.append(act) menu.addSeparator() act = menu.addAction(UI.PixmapCache.getIcon("vcsAdd.png"), self.tr('Add to repository'), self._VCSAdd) self.vcsAddMenuActions.append(act) if 1 in self.browser.specialMenuEntries: self.vcsMenuAddTree = menu.addAction( UI.PixmapCache.getIcon("vcsAdd.png"), self.tr('Add tree to repository'), self._VCSAddTree) self.vcsAddMenuActions.append(self.vcsMenuAddTree) act = menu.addAction(UI.PixmapCache.getIcon("vcsRemove.png"), self.tr('Remove from repository (and disk)'), self._VCSRemove) self.vcsMenuActions.append(act) menu.addSeparator() act = menu.addAction(self.tr('Copy'), self.__SVNCopy) self.vcsMenuActions.append(act) act = menu.addAction(self.tr('Move'), self.__SVNMove) self.vcsMenuActions.append(act) if pysvn.svn_version >= (1, 5, 0) and pysvn.version >= (1, 6, 0): menu.addSeparator() act = menu.addAction(self.tr("Add to Changelist"), self.__SVNAddToChangelist) self.vcsMenuActions.append(act) act = menu.addAction(self.tr("Remove from Changelist"), self.__SVNRemoveFromChangelist) self.vcsMenuActions.append(act) menu.addSeparator() act = menu.addAction(UI.PixmapCache.getIcon("vcsLog.png"), self.tr('Show log'), self._VCSLog) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsLog.png"), self.tr('Show log browser'), self._VCSLogBrowser) self.vcsMenuActions.append(act) menu.addSeparator() act = menu.addAction(UI.PixmapCache.getIcon("vcsStatus.png"), self.tr('Show status'), self._VCSStatus) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsRepo.png"), self.tr('Show repository info'), self.__SVNInfo) self.vcsMenuActions.append(act) menu.addSeparator() act = menu.addAction(UI.PixmapCache.getIcon("vcsDiff.png"), self.tr('Show differences'), self._VCSDiff) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsSbsDiff.png"), self.tr('Show differences side-by-side'), self.__SVNSbsDiff) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsDiff.png"), self.tr('Show differences (extended)'), self.__SVNExtendedDiff) self.vcsMenuActions.append(act) act = menu.addAction( UI.PixmapCache.getIcon("vcsSbsDiff.png"), self.tr('Show differences side-by-side (extended)'), self.__SVNSbsExtendedDiff) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsDiff.png"), self.tr('Show differences (URLs)'), self.__SVNUrlDiff) self.vcsMenuActions.append(act) self.blameAct = menu.addAction(self.tr('Show annotated file'), self.__SVNBlame) self.vcsMenuActions.append(self.blameAct) menu.addSeparator() act = menu.addAction(UI.PixmapCache.getIcon("vcsRevert.png"), self.tr('Revert changes'), self._VCSRevert) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsMerge.png"), self.tr('Merge changes'), self._VCSMerge) self.vcsMenuActions.append(act) act = menu.addAction(self.tr('Conflicts resolved'), self.__SVNResolve) self.vcsMenuActions.append(act) menu.addSeparator() act = menu.addAction(UI.PixmapCache.getIcon("vcsLock.png"), self.tr('Lock'), self.__SVNLock) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsUnlock.png"), self.tr('Unlock'), self.__SVNUnlock) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsUnlock.png"), self.tr('Break Lock'), self.__SVNBreakLock) self.vcsMenuActions.append(act) act = menu.addAction(UI.PixmapCache.getIcon("vcsUnlock.png"), self.tr('Steal Lock'), self.__SVNStealLock) self.vcsMenuActions.append(act) menu.addSeparator() act = menu.addAction(self.tr('Set Property'), self.__SVNSetProp) self.vcsMenuActions.append(act) act = menu.addAction(self.tr('List Properties'), self.__SVNListProps) self.vcsMenuActions.append(act) act = menu.addAction(self.tr('Delete Property'), self.__SVNDelProp) self.vcsMenuActions.append(act) menu.addSeparator() menu.addAction(self.tr('Select all local file entries'), self.browser.selectLocalEntries) menu.addAction(self.tr('Select all versioned file entries'), self.browser.selectVCSEntries) menu.addAction(self.tr('Select all local directory entries'), self.browser.selectLocalDirEntries) menu.addAction(self.tr('Select all versioned directory entries'), self.browser.selectVCSDirEntries) menu.addSeparator() menu.addAction(self.tr("Configure..."), self.__SVNConfigure) mainMenu.addSeparator() mainMenu.addMenu(menu) self.menu = menu
class GitStashBrowserDialog(QWidget, Ui_GitStashBrowserDialog): """ Class implementing a dialog to show the stashes. """ NameColumn = 0 DateColumn = 1 MessageColumn = 2 Separator = "@@||@@" TotalStatisticsRole = Qt.UserRole FileStatisticsRole = Qt.UserRole + 1 def __init__(self, vcs, parent=None): """ Constructor @param vcs reference to the vcs object @param parent reference to the parent widget (QWidget) """ super(GitStashBrowserDialog, self).__init__(parent) self.setupUi(self) self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self.__position = QPoint() self.__fileStatisticsRole = Qt.UserRole self.__totalStatisticsRole = Qt.UserRole + 1 self.stashList.header().setSortIndicator(0, Qt.AscendingOrder) self.refreshButton = self.buttonBox.addButton( self.tr("&Refresh"), QDialogButtonBox.ActionRole) self.refreshButton.setToolTip( self.tr("Press to refresh the list of stashes")) self.refreshButton.setEnabled(False) self.vcs = vcs self.__resetUI() self.__ioEncoding = Preferences.getSystem("IOEncoding") self.process = QProcess() self.process.finished.connect(self.__procFinished) self.process.readyReadStandardOutput.connect(self.__readStdout) self.process.readyReadStandardError.connect(self.__readStderr) self.__contextMenu = QMenu() self.__differencesAct = self.__contextMenu.addAction( self.tr("Show"), self.__showPatch) self.__contextMenu.addSeparator() self.__applyAct = self.__contextMenu.addAction( self.tr("Restore && Keep"), self.__apply) self.__popAct = self.__contextMenu.addAction( self.tr("Restore && Delete"), self.__pop) self.__contextMenu.addSeparator() self.__branchAct = self.__contextMenu.addAction( self.tr("Create Branch"), self.__branch) self.__contextMenu.addSeparator() self.__dropAct = self.__contextMenu.addAction(self.tr("Delete"), self.__drop) self.__clearAct = self.__contextMenu.addAction(self.tr("Delete All"), self.__clear) def closeEvent(self, e): """ Protected slot implementing a close event handler. @param e close event (QCloseEvent) """ if self.process is not None and \ self.process.state() != QProcess.NotRunning: self.process.terminate() QTimer.singleShot(2000, self.process.kill) self.process.waitForFinished(3000) self.__position = self.pos() e.accept() def show(self): """ Public slot to show the dialog. """ if not self.__position.isNull(): self.move(self.__position) self.__resetUI() super(GitStashBrowserDialog, self).show() def __resetUI(self): """ Private method to reset the user interface. """ self.stashList.clear() def __resizeColumnsStashes(self): """ Private method to resize the shelve list columns. """ self.stashList.header().resizeSections(QHeaderView.ResizeToContents) self.stashList.header().setStretchLastSection(True) def __generateStashEntry(self, name, date, message): """ Private method to generate the stash items. @param name name of the stash (string) @param date date the stash was created (string) @param message stash message (string) """ QTreeWidgetItem(self.stashList, [name, date, message]) def __getStashEntries(self): """ Private method to retrieve the list of stashes. """ self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self.inputGroup.setEnabled(True) self.inputGroup.show() self.refreshButton.setEnabled(False) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.buf = [] self.errors.clear() self.intercept = False args = self.vcs.initCommand("stash") args.append("list") args.append("--format=format:%gd{0}%ai{0}%gs%n".format(self.Separator)) self.process.kill() self.process.setWorkingDirectory(self.repodir) self.inputGroup.setEnabled(True) self.inputGroup.show() self.process.start('git', args) procStarted = self.process.waitForStarted(5000) if not procStarted: self.inputGroup.setEnabled(False) self.inputGroup.hide() E5MessageBox.critical( self, self.tr('Process Generation Error'), self.tr( 'The process {0} could not be started. ' 'Ensure, that it is in the search path.').format('git')) def start(self, projectDir): """ Public slot to start the git stash command. @param projectDir name of the project directory (string) """ self.errorGroup.hide() QApplication.processEvents() self.__projectDir = projectDir # find the root of the repo self.repodir = self.__projectDir while not os.path.isdir(os.path.join(self.repodir, self.vcs.adminDir)): self.repodir = os.path.dirname(self.repodir) if os.path.splitdrive(self.repodir)[1] == os.sep: return self.activateWindow() self.raise_() self.stashList.clear() self.__started = True self.__getStashEntries() def __procFinished(self, exitCode, exitStatus): """ Private slot connected to the finished signal. @param exitCode exit code of the process (integer) @param exitStatus exit status of the process (QProcess.ExitStatus) """ self.__processBuffer() self.__finish() def __finish(self): """ Private slot called when the process finished or the user pressed the button. """ if self.process is not None and \ self.process.state() != QProcess.NotRunning: self.process.terminate() QTimer.singleShot(2000, self.process.kill) self.process.waitForFinished(3000) QApplication.restoreOverrideCursor() self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) self.inputGroup.setEnabled(False) self.inputGroup.hide() self.refreshButton.setEnabled(True) def __processBuffer(self): """ Private method to process the buffered output of the git stash command. """ for line in self.buf: name, date, message = line.split(self.Separator) date = date.strip().rsplit(":", 1)[0] self.__generateStashEntry(name, date, message.strip()) self.__resizeColumnsStashes() if self.__started: self.stashList.setCurrentItem(self.stashList.topLevelItem(0)) self.__started = False def __readStdout(self): """ Private slot to handle the readyReadStandardOutput signal. It reads the output of the process and inserts it into a buffer. """ self.process.setReadChannel(QProcess.StandardOutput) while self.process.canReadLine(): line = str(self.process.readLine(), self.__ioEncoding, 'replace').strip() if line: self.buf.append(line) def __readStderr(self): """ Private slot to handle the readyReadStandardError signal. It reads the error output of the process and inserts it into the error pane. """ if self.process is not None: s = str(self.process.readAllStandardError(), self.__ioEncoding, 'replace') self.errorGroup.show() self.errors.insertPlainText(s) self.errors.ensureCursorVisible() @pyqtSlot(QAbstractButton) def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. @param button button that was clicked (QAbstractButton) """ if button == self.buttonBox.button(QDialogButtonBox.Close): self.close() elif button == self.buttonBox.button(QDialogButtonBox.Cancel): self.cancelled = True self.__finish() elif button == self.refreshButton: self.on_refreshButton_clicked() @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) def on_stashList_currentItemChanged(self, current, previous): """ Private slot called, when the current item of the stash list changes. @param current reference to the new current item (QTreeWidgetItem) @param previous reference to the old current item (QTreeWidgetItem) """ self.statisticsList.clear() self.filesLabel.setText("") self.insertionsLabel.setText("") self.deletionsLabel.setText("") if current: if current.data(0, self.TotalStatisticsRole) is None: args = self.vcs.initCommand("stash") args.append("show") args.append('--numstat') args.append(current.text(self.NameColumn)) output = "" process = QProcess() process.setWorkingDirectory(self.repodir) process.start('git', args) procStarted = process.waitForStarted(5000) if procStarted: finished = process.waitForFinished(30000) if finished and process.exitCode() == 0: output = str(process.readAllStandardOutput(), Preferences.getSystem("IOEncoding"), 'replace') if output: totals = {"files": 0, "additions": 0, "deletions": 0} fileData = [] for line in output.splitlines(): additions, deletions, name = \ line.strip().split(None, 2) totals["files"] += 1 if additions != "-": totals["additions"] += int(additions) if deletions != "-": totals["deletions"] += int(deletions) fileData.append({ "file": name, "total": ("-" if additions == "-" else str(int(additions) + int(deletions))), "added": additions, "deleted": deletions }) current.setData(0, self.TotalStatisticsRole, totals) current.setData(0, self.FileStatisticsRole, fileData) else: return for dataDict in current.data(0, self.FileStatisticsRole): QTreeWidgetItem(self.statisticsList, [ dataDict["file"], dataDict["total"], dataDict["added"], dataDict["deleted"] ]) self.statisticsList.header().resizeSections( QHeaderView.ResizeToContents) self.statisticsList.header().setStretchLastSection(True) totals = current.data(0, self.TotalStatisticsRole) self.filesLabel.setText( self.tr("%n file(s) changed", None, totals["files"])) self.insertionsLabel.setText( self.tr("%n line(s) inserted", None, int(totals["additions"]))) self.deletionsLabel.setText( self.tr("%n line(s) deleted", None, int(totals["deletions"]))) @pyqtSlot(QPoint) def on_stashList_customContextMenuRequested(self, pos): """ Private slot to show the context menu of the stash list. @param pos position of the mouse pointer (QPoint) """ enable = len(self.stashList.selectedItems()) == 1 self.__differencesAct.setEnabled(enable) self.__applyAct.setEnabled(enable) self.__popAct.setEnabled(enable) self.__branchAct.setEnabled(enable) self.__dropAct.setEnabled(enable) self.__clearAct.setEnabled(self.stashList.topLevelItemCount() > 0) self.__contextMenu.popup(self.mapToGlobal(pos)) @pyqtSlot() def on_refreshButton_clicked(self): """ Private slot to refresh the list of shelves. """ self.start(self.__projectDir) @pyqtSlot() def on_sendButton_clicked(self): """ Private slot to send the input to the git process. """ inputTxt = self.input.text() inputTxt += os.linesep if self.passwordCheckBox.isChecked(): self.errors.insertPlainText(os.linesep) self.errors.ensureCursorVisible() else: self.errors.insertPlainText(inputTxt) self.errors.ensureCursorVisible() self.errorGroup.show() self.process.write(inputTxt) self.passwordCheckBox.setChecked(False) self.input.clear() @pyqtSlot() def on_input_returnPressed(self): """ Private slot to handle the press of the return key in the input field. """ self.intercept = True self.on_sendButton_clicked() @pyqtSlot(bool) def on_passwordCheckBox_toggled(self, checked): """ Private slot to handle the password checkbox toggled. @param checked flag indicating the status of the check box (boolean) """ if checked: self.input.setEchoMode(QLineEdit.Password) else: self.input.setEchoMode(QLineEdit.Normal) def keyPressEvent(self, evt): """ Protected slot to handle a key press event. @param evt the key press event (QKeyEvent) """ if self.intercept: self.intercept = False evt.accept() return super(GitStashBrowserDialog, self).keyPressEvent(evt) def __showPatch(self): """ Private slot to show the contents of the selected stash. """ stashName = self.stashList.selectedItems()[0].text(self.NameColumn) self.vcs.gitStashShowPatch(self.__projectDir, stashName) def __apply(self): """ Private slot to apply the selected stash but keep it. """ stashName = self.stashList.selectedItems()[0].text(self.NameColumn) self.vcs.gitStashApply(self.__projectDir, stashName) def __pop(self): """ Private slot to apply the selected stash and delete it. """ stashName = self.stashList.selectedItems()[0].text(self.NameColumn) self.vcs.gitStashPop(self.__projectDir, stashName) self.on_refreshButton_clicked() def __branch(self): """ Private slot to create a branch from the selected stash. """ stashName = self.stashList.selectedItems()[0].text(self.NameColumn) self.vcs.gitStashBranch(self.__projectDir, stashName) self.on_refreshButton_clicked() def __drop(self): """ Private slot to delete the selected stash. """ stashName = self.stashList.selectedItems()[0].text(self.NameColumn) res = self.vcs.gitStashDrop(self.__projectDir, stashName) if res: self.on_refreshButton_clicked() def __clear(self): """ Private slot to delete all stashes. """ res = self.vcs.gitStashClear(self.__projectDir) if res: self.on_refreshButton_clicked()
class Dialog(QDialog): NumGridRows = 3 NumButtons = 4 def __init__(self, extra, synth, decoders, set_decoder): super(Dialog, self).__init__() self.synth = synth self.decoders = decoders self.set_decoder = set_decoder self.createMenu() self.createAudioControls() self.createDatasetControls() self.createGridGroupBox() mainLayout = QVBoxLayout() mainLayout.setMenuBar(self.menuBar) vLayout = QVBoxLayout() vLayout.addWidget(self.audioControls) # vLayout.addWidget(self.datasetControls) vLayout.addWidget(self.gridGroupBox) hLayout = QHBoxLayout() vGroupBox = QGroupBox() vGroupBox.setLayout(vLayout) hLayout.addWidget(vGroupBox) hLayout.addWidget(extra) hGroupBox = QGroupBox() hGroupBox.setLayout(hLayout) hGroupBox.setFlat(True) title = QLabel("Sounderfeit") title.setStyleSheet("font-size: 20pt; font-weight: bold;") mainLayout.addWidget(title) mainLayout.addWidget(hGroupBox) self.setLayout(mainLayout) self.setWindowTitle("Sounderfeit") def createMenu(self): self.menuBar = QMenuBar() self.fileMenu = QMenu("&File", self) self.exitAction = self.fileMenu.addAction("E&xit") self.menuBar.addMenu(self.fileMenu) self.exitAction.triggered.connect(self.accept) def createAudioControls(self): self.audioControls = QGroupBox("Audio") vlayout = QVBoxLayout() layout = QHBoxLayout() button = QPushButton("Play") button.clicked.connect(lambda: self.synth.start()) layout.addWidget(button) button = QPushButton("Stop") button.clicked.connect(lambda: self.synth.stop()) layout.addWidget(button) layout2 = QVBoxLayout() for n, d in enumerate(self.decoders): button = QRadioButton(d) button.setChecked(n == 0) def make_clicked(d, button): def clicked(): if button.isChecked(): self.set_decoder(d) print('Decoder set to', d) self.synth.setMode(0) return clicked button.clicked.connect(make_clicked(d, button)) layout2.addWidget(button) button = QRadioButton("STK Bowed") button.clicked.connect(lambda: self.synth.setMode(1)) layout2.addWidget(button) vlayout.addLayout(layout) vlayout.addLayout(layout2) self.audioControls.setLayout(vlayout) def createDatasetControls(self): self.datasetControls = QGroupBox("Dataset") layout = QHBoxLayout() button = QPushButton("Load") layout.addWidget(button) button = QPushButton("Train") layout.addWidget(button) self.datasetControls.setLayout(layout) def createGridGroupBox(self): self.gridGroupBox = QGroupBox("Parameters") layout = QGridLayout() volume_slider = QSlider() volume_slider.setRange(0, 128) volume_slider.setValue(64) position_slider = QSlider() position_slider.setRange(0, 64) position_slider.setValue(32) pressure_slider = QSlider() pressure_slider.setRange(0, 128) pressure_slider.setValue(64) latent1_slider = QSlider() latent1_slider.setRange(0, 128) latent1_slider.setValue(64) layout.addWidget(volume_slider, 0, 0, alignment=Qt.AlignHCenter) layout.addWidget(QLabel('volume'), 1, 0, alignment=Qt.AlignHCenter) layout.addWidget(position_slider, 0, 1, alignment=Qt.AlignHCenter) layout.addWidget(QLabel('position'), 1, 1, alignment=Qt.AlignHCenter) layout.addWidget(pressure_slider, 0, 2, alignment=Qt.AlignHCenter) layout.addWidget(QLabel('pressure'), 1, 2, alignment=Qt.AlignHCenter) layout.addWidget(latent1_slider, 0, 3, alignment=Qt.AlignHCenter) layout.addWidget(QLabel('latent1'), 1, 3, alignment=Qt.AlignHCenter) self.gridGroupBox.setLayout(layout) position_slider.valueChanged.connect( lambda: self.synth.setParam(0, position_slider.value())) pressure_slider.valueChanged.connect( lambda: self.synth.setParam(1, pressure_slider.value())) volume_slider.valueChanged.connect( lambda: self.synth.setParam(2, volume_slider.value() / 128.0)) latent1_slider.valueChanged.connect( lambda: self.synth.setParam(3, latent1_slider.value() / 128.0))
class Tray(QSystemTrayIcon): def __init__(self, app): """ type app: feeluown.app.App """ super().__init__() self._app = app self._app_old_state = None #: app window state before minimized # setup context menu self._menu = QMenu() self._status_action = QAction('...') self._toggle_player_action = QAction(QIcon.fromTheme('media-play'), TOGGLE_PLAYER_TEXT[0]) self._next_action = QAction(QIcon.fromTheme('media-skip-forward'), '下一首') self._prev_action = QAction(QIcon.fromTheme('media-skip-backward'), '上一首') self._quit_action = QAction(QIcon.fromTheme('exit'), '退出') # add toggle_app action for macOS, on other platforms, user # can click the tray icon to toggle_app if IS_MACOS: self._toggle_app_action = QAction(QIcon.fromTheme('window'), TOGGLE_APP_TEXT[1]) else: self._toggle_app_action = None self.activated.connect(self._toggle_app_state) # noqa # bind signals self._quit_action.triggered.connect(self._app.exit) self._toggle_player_action.triggered.connect(self._app.player.toggle) self._prev_action.triggered.connect(self._app.playlist.previous) self._next_action.triggered.connect(self._app.playlist.next) if self._toggle_app_action is not None: self._toggle_app_action.triggered.connect(self._toggle_app_state) self._app.player.state_changed.connect(self.on_player_state_changed) self._app.playlist.song_changed.connect(self.on_player_song_changed) self._app.theme_mgr.theme_changed.connect(self.on_theme_changed) q_app = QApplication.instance() q_app.applicationStateChanged.connect(self.on_app_state_changed) self._app.installEventFilter(self) self.setContextMenu(self._menu) self.setup_ui() def initialize(self): self._set_icon() self._status_action.setIcon(self.icon()) self.show() def setup_ui(self): self._menu.addAction(self._status_action) self._menu.addAction(self._toggle_player_action) self._menu.addAction(self._prev_action) self._menu.addAction(self._next_action) self._menu.addSeparator() if self._toggle_app_action is not None: self._menu.addAction(self._toggle_app_action) self._menu.addAction(self._quit_action) self._status_action.setEnabled(False) def _toggle_app_state(self): """activate/deactivate app""" if self._app.isHidden(): self._app.show() self._app.activateWindow() elif self._app.isMinimized(): self._app.setWindowState(self._app_old_state) else: self._app.hide() def _set_icon(self): # respect system icon icon = QIcon.fromTheme('feeluown-tray', QIcon(self._app.theme_mgr.get_icon('tray'))) self.setIcon(icon) def on_theme_changed(self, _): self._set_icon() def on_player_song_changed(self, song): if song is not None: status = f'{song.title_display} - {song.artists_name_display}' if self._app.config.NOTIFY_ON_TRACK_CHANGED: # TODO: show song cover if possible self.showMessage(song.title_display, song.artists_name_display, msecs=self._app.config.NOTIFY_DURATION) self._status_action.setText(elided_text(status, 120)) self._status_action.setToolTip(status) self.setToolTip(status) def on_player_state_changed(self, state): if state == State.playing: self._toggle_player_action.setText(TOGGLE_PLAYER_TEXT[1]) self._toggle_player_action.setIcon(QIcon.fromTheme('media-pause')) self._toggle_player_action.setEnabled(True) else: self._toggle_player_action.setText(TOGGLE_PLAYER_TEXT[0]) self._toggle_player_action.setIcon(QIcon.fromTheme('media-play')) if state == State.stopped: self._toggle_player_action.setEnabled(False) else: self._toggle_player_action.setEnabled(True) def on_app_state_changed(self, state): if state == Qt.ApplicationActive: # On macOS, when the app is hidden, there will be an icon on the # macOS dock, if user click the dock, we should activate the app window. # For other platforms(Win32/Linux), the dock icon is not visible if # the window is hidden/closed. # # When the state will be changed to QApplicationActive? # * the dock icon is clicked (on macOS) # * the Qt.Tool widget got focus (on macOS and Linux) # * the Qt.Window widget got focus (on Linux) if IS_MACOS: self._app.show() self._app.activateWindow() elif state == Qt.ApplicationInactive: # when app window is not the top window, it changes to inactive if self._toggle_app_action is not None: self._toggle_app_action.setText(TOGGLE_APP_TEXT[0]) def eventFilter(self, obj, event): """event filter for app""" app_text_idx = None if event.type() == QEvent.WindowStateChange: # when window is maximized before minimized, the window state will # be Qt.WindowMinimized | Qt.WindowMaximized if obj.windowState() & Qt.WindowMinimized: self._app_old_state = event.oldState() app_text_idx = 0 else: app_text_idx = 1 elif event.type() == QEvent.Hide: app_text_idx = 0 elif event.type() == QEvent.Show: app_text_idx = 1 if app_text_idx is not None and self._toggle_app_action is not None: self._toggle_app_action.setText(TOGGLE_APP_TEXT[app_text_idx]) return False
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 MainWindowUI(object): def setup_ui(self, MainWin): # Main Window MainWin.setObjectName("MainWindow") MainWin.setWindowTitle(MainWin.tr("BDBag")) MainWin.resize(680, 600) 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") # Actions # Create/Update self.actionCreateOrUpdate = QAction(MainWin) self.actionCreateOrUpdate.setObjectName("actionCreateOrUpdate") # Revert self.actionRevert = QAction(MainWin) self.actionRevert.setObjectName("actionRevert") self.actionRevert.setText(MainWin.tr("Revert")) self.actionRevert.setToolTip( MainWin.tr("Revert a bag directory back to a normal directory.")) self.actionRevert.setShortcut(MainWin.tr("Ctrl+R")) # Validate Fast self.actionValidateFast = QAction(MainWin) self.actionValidateFast.setObjectName("actionValidateFast") self.actionValidateFast.setText(MainWin.tr("Validate: Fast")) self.actionValidateFast.setToolTip( MainWin. tr("Perform fast validation by checking the payload file counts and sizes against the Payload-0xum " "value from the bag manifest")) self.actionValidateFast.setShortcut(MainWin.tr("Ctrl+F")) # Validate Full self.actionValidateFull = QAction(MainWin) self.actionValidateFull.setObjectName("actionValidateFull") self.actionValidateFull.setText(MainWin.tr("Validate: Full")) self.actionValidateFull.setToolTip( MainWin. tr("Perform full validation by calculating checksums for all files and comparing them against " "entries in the bag manifest(s)")) self.actionValidateFull.setShortcut(MainWin.tr("Ctrl+V")) # Fetch Missing self.actionFetchMissing = QAction(MainWin) self.actionFetchMissing.setObjectName("actionFetchMissing") self.actionFetchMissing.setText(MainWin.tr("Fetch: Missing")) self.actionFetchMissing.setToolTip( MainWin. tr("Fetch only those remote files that are not already present in the bag" )) self.actionFetchMissing.setShortcut(MainWin.tr("Ctrl+M")) # Fetch All self.actionFetchAll = QAction(MainWin) self.actionFetchAll.setObjectName("actionFetchAll") self.actionFetchAll.setText(MainWin.tr("Fetch: All")) self.actionFetchAll.setToolTip( MainWin. tr("Fetch all remote files, even if they are already present in the bag" )) self.actionFetchAll.setShortcut(MainWin.tr("Ctrl+A")) # Archive ZIP self.actionArchiveZIP = QAction(MainWin) self.actionArchiveZIP.setObjectName("actionArchiveZIP") self.actionArchiveZIP.setText(MainWin.tr("Archive: ZIP")) self.actionArchiveZIP.setToolTip( MainWin.tr("Create a ZIP format archive of the bag.")) self.actionArchiveZIP.setShortcut(MainWin.tr("Ctrl+Z")) # Archive TGZ self.actionArchiveTGZ = QAction(MainWin) self.actionArchiveTGZ.setObjectName("actionArchiveTGZ") self.actionArchiveTGZ.setText(MainWin.tr("Archive: TGZ")) self.actionArchiveTGZ.setToolTip( MainWin.tr("Create a TAR/GZIP format archive of the bag.")) self.actionArchiveTGZ.setShortcut(MainWin.tr("Ctrl+T")) # 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+O")) # Cancel self.actionCancel = QAction(MainWin) self.actionCancel.setObjectName("actionCancel") self.actionCancel.setText(MainWin.tr("Cancel")) self.actionCancel.setToolTip( MainWin.tr("Cancel the current background task.")) self.actionCancel.setShortcut(MainWin.tr("Ctrl+C")) # About self.actionAbout = QAction(MainWin) self.actionAbout.setObjectName("actionAbout") self.actionAbout.setText(MainWin.tr("About")) self.actionAbout.setToolTip(MainWin.tr("Show version information.")) self.actionAbout.setShortcut(MainWin.tr("Ctrl+B")) # Tree View self.treeView = QTreeView(self.centralWidget) self.treeView.setObjectName("treeView") self.treeView.setStyleSheet(""" QTreeView { border: 2px solid grey; border-radius: 5px; } """) self.verticalLayout.addWidget(self.treeView) # Log Widget self.logTextBrowser = log_widget.QPlainTextEditLogger( self.centralWidget) self.logTextBrowser.widget.setObjectName("logTextBrowser") self.logTextBrowser.widget.setStyleSheet(""" QPlainTextEdit { border: 2px solid grey; border-radius: 5px; background-color: lightgray; } """) self.verticalLayout.addWidget(self.logTextBrowser.widget) # Menu Bar self.menuBar = QMenuBar(MainWin) self.menuBar.setObjectName("menuBar") MainWin.setMenuBar(self.menuBar) # Bag Menu self.menuBag = QMenu(self.menuBar) self.menuBag.setObjectName("menuBag") self.menuBag.setTitle(MainWin.tr("Bag")) self.menuBar.addAction(self.menuBag.menuAction()) self.menuBag.addAction(self.actionCreateOrUpdate) self.menuBag.addAction(self.actionRevert) self.menuBag.addAction(self.actionCancel) self.menuBag.addAction(self.actionOptions) # Fetch Menu self.menuFetch = QMenu(self.menuBag) self.menuFetch.setObjectName("menuFetch") self.menuFetch.setTitle(MainWin.tr("Fetch")) self.menuFetch.addAction(self.actionFetchMissing) self.menuFetch.addAction(self.actionFetchAll) self.menuBag.addAction(self.menuFetch.menuAction()) # Validate Menu self.menuValidate = QMenu(self.menuBag) self.menuValidate.setObjectName("menuValidate") self.menuValidate.setTitle(MainWin.tr("Validate")) self.menuValidate.addAction(self.actionValidateFast) self.menuValidate.addAction(self.actionValidateFull) self.menuBag.addAction(self.menuValidate.menuAction()) # Archive Menu self.menuArchive = QMenu(self.menuBag) self.menuArchive.setObjectName("menuArchive") self.menuArchive.setTitle(MainWin.tr("Archive")) self.menuArchive.addAction(self.actionArchiveZIP) self.menuArchive.addAction(self.actionArchiveTGZ) self.menuBag.addAction(self.menuArchive.menuAction()) # Help Menu self.menuHelp = QMenu(self.menuBar) self.menuHelp.setObjectName("menuHelp") self.menuHelp.setTitle(MainWin.tr("Help")) self.menuHelp.addAction(self.actionAbout) self.menuBar.addAction(self.menuHelp.menuAction()) # Tool Bar self.mainToolBar = QToolBar(MainWin) self.mainToolBar.setObjectName("mainToolBar") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) MainWin.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # Create/Update self.mainToolBar.addAction(self.actionCreateOrUpdate) self.actionCreateOrUpdate.setIcon( self.actionCreateOrUpdate.parentWidget().style().standardIcon( getattr(QStyle, "SP_FileDialogNewFolder"))) # Revert self.mainToolBar.addAction(self.actionRevert) self.actionRevert.setIcon( self.actionRevert.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogOkButton"))) # Fetch self.mainToolBar.addAction(self.actionFetchMissing) self.actionFetchMissing.setIcon( self.actionFetchMissing.parentWidget().style().standardIcon( getattr(QStyle, "SP_ArrowDown"))) self.mainToolBar.addAction(self.actionFetchAll) self.actionFetchAll.setIcon( self.actionFetchAll.parentWidget().style().standardIcon( getattr(QStyle, "SP_ArrowDown"))) # Validate self.mainToolBar.addAction(self.actionValidateFast) self.actionValidateFast.setIcon( self.actionValidateFast.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogApplyButton"))) self.mainToolBar.addAction(self.actionValidateFull) self.actionValidateFull.setIcon( self.actionValidateFull.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogApplyButton"))) # Archive self.mainToolBar.addAction(self.actionArchiveZIP) self.actionArchiveZIP.setIcon( self.actionArchiveZIP.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogSaveButton"))) self.mainToolBar.addAction(self.actionArchiveTGZ) self.actionArchiveTGZ.setIcon( self.actionArchiveTGZ.parentWidget().style().standardIcon( getattr(QStyle, "SP_DialogSaveButton"))) # Options self.mainToolBar.addAction(self.actionOptions) self.actionOptions.setIcon( self.actionOptions.parentWidget().style().standardIcon( getattr(QStyle, "SP_FileDialogDetailedView"))) # Cancel self.mainToolBar.addAction(self.actionCancel) self.actionCancel.setIcon( self.actionCancel.parentWidget().style().standardIcon( getattr(QStyle, "SP_BrowserStop"))) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # Progress Bar self.progressBar = QProgressBar(self.centralWidget) self.progressBar.setValue(0) self.progressBar.setTextVisible(False) self.progressBar.setObjectName("progressBar") self.progressBar.setStyleSheet(""" QProgressBar { border: 2px solid grey; border-radius: 5px; text-align: center; } QProgressBar::chunk { background-color: darkblue; width: 10px; margin: 0.5px; } """) self.verticalLayout.addWidget(self.progressBar) # finalize UI setup self.toggleCreateOrUpdate(MainWin) QMetaObject.connectSlotsByName(MainWin) def toggleCreateOrUpdate(self, MainWin): if MainWin.isBag: self.actionCreateOrUpdate.setText(MainWin.tr("Update")) self.actionCreateOrUpdate.setToolTip( MainWin.tr("Update a bag in an existing directory")) self.actionCreateOrUpdate.setShortcut(MainWin.tr("Ctrl+U")) else: self.actionCreateOrUpdate.setText(MainWin.tr("Create")) self.actionCreateOrUpdate.setToolTip( MainWin.tr("Create a new bag from an existing directory")) self.actionCreateOrUpdate.setShortcut(MainWin.tr("Ctrl+N"))
def create_menu(self, position): menu = QMenu() selected = self.selectedItems() if not selected: menu.addAction(_("New contact"), lambda: self.parent.new_contact_dialog()) menu.addAction(_("Import file"), lambda: self.import_contacts()) menu.addAction(_("Export file"), lambda: self.export_contacts()) else: names = [item.text(0) for item in selected] keys = [item.text(1) for item in selected] column = self.currentColumn() column_title = self.headerItem().text(column) column_data = '\n'.join([item.text(column) for item in selected]) menu.addAction( _("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data)) if column in self.editable_columns: item = self.currentItem() menu.addAction( _("Edit {}").format(column_title), lambda: self.editItem(item, column)) menu.addAction(_("Pay to"), lambda: self.parent.payto_contacts(keys)) menu.addAction(_("Delete"), lambda: self.parent.delete_contacts(keys)) URLs = [ block_explorer_URL(self.config, 'addr', key) for key in filter(is_address, keys) ] if URLs: menu.addAction(_("View on block explorer"), lambda: map(webbrowser.open, URLs)) run_hook('create_contact_menu', menu, selected) menu.exec_(self.viewport().mapToGlobal(position))
class ApplicationWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setWindowTitle("application main window") self.file_menu = QMenu('&File', self) self.file_menu.addAction('&Quit', self.fileQuit, QtCore.Qt.CTRL + QtCore.Qt.Key_Q) self.menuBar().addMenu(self.file_menu) self.help_menu = QMenu('&Help', self) self.menuBar().addSeparator() self.menuBar().addMenu(self.help_menu) self.help_menu.addAction('&About', self.about) self.main_widget = QWidget(self) l = QVBoxLayout(self.main_widget) sc = MyStaticMplCanvas(self.main_widget, width=5, height=4, dpi=100, title='Title 1') dc = MyDynamicMplCanvas(self.main_widget, width=5, height=4, dpi=100, title='Title 2') scntb = NavigationToolbar(sc, self.main_widget) # full toolbar dcntb = NavToolbar(dc, self.main_widget) # only save button l.addWidget(sc) l.addWidget(scntb) #l.addWidget(dc) #l.addWidget(dcntb) self.main_widget.setFocus() self.setCentralWidget(self.main_widget) self.statusBar().showMessage("All hail matplotlib!", 2000) def fileQuit(self): self.close() def closeEvent(self, ce): self.fileQuit() def about(self): QMessageBox.about( self, "About", """embedding_in_qt5.py example Copyright 2015 BoxControL This program is a simple example of a Qt5 application embedding matplotlib canvases. It is base on example from matplolib documentation, and initially was developed from Florent Rougon and Darren Dale. http://matplotlib.org/examples/user_interfaces/embedding_in_qt4.html It may be used and modified with no restriction; raw copies as well as modified versions may be distributed without limitation.""")
class CalcDlg(QWidget): """Main dialog for calculator program. """ def __init__(self, parent=None): QWidget.__init__(self, parent) self.calc = CalcCore() self.setWindowTitle('rpCalc') modPath = os.path.abspath(sys.path[0]) if modPath.endswith('.zip') or modPath.endswith('.exe'): modPath = os.path.dirname(modPath) # for py2exe/cx_freeze iconPathList = [iconPath, os.path.join(modPath, 'icons/'), os.path.join(modPath, '../icons')] self.icons = icondict.IconDict() self.icons.addIconPath(filter(None, iconPathList)) self.icons.addIconPath([path for path in iconPathList if path]) try: QApplication.setWindowIcon(self.icons['calc_lg']) except KeyError: pass self.setFocusPolicy(Qt.StrongFocus) self.helpView = None self.extraView = None self.regView = None self.histView = None self.memView = None self.altBaseView = None self.optDlg = None self.popupMenu = QMenu(self) self.popupMenu.addAction('Registers on &LCD', self.toggleReg) self.popupMenu.addSeparator() self.popupMenu.addAction('Show &Register List', self.viewReg) self.popupMenu.addAction('Show &History List', self.viewHist) self.popupMenu.addAction('Show &Memory List', self.viewMem) self.popupMenu.addSeparator() self.popupMenu.addAction('Show Other &Bases', self.viewAltBases) self.popupMenu.addSeparator() self.popupMenu.addAction('Show Help &File', self.help) self.popupMenu.addAction('&About rpCalc', self.about) self.popupMenu.addSeparator() self.popupMenu.addAction('&Quit', self.close) topLay = QVBoxLayout(self) self.setLayout(topLay) topLay.setSpacing(4) topLay.setContentsMargins(6, 6, 6, 6) lcdBox = LcdBox() topLay.addWidget(lcdBox) lcdLay = QGridLayout(lcdBox) lcdLay.setColumnStretch(1, 1) lcdLay.setRowStretch(3, 1) self.extraLabels = [QLabel(' T:',), QLabel(' Z:',), QLabel(' Y:',)] for i in range(3): lcdLay.addWidget(self.extraLabels[i], i, 0, Qt.AlignLeft) self.extraLcds = [Lcd(1.5, 13), Lcd(1.5, 13), Lcd(1.5, 13)] lcdLay.addWidget(self.extraLcds[2], 0, 1, Qt.AlignRight) lcdLay.addWidget(self.extraLcds[1], 1, 1, Qt.AlignRight) lcdLay.addWidget(self.extraLcds[0], 2, 1, Qt.AlignRight) if not self.calc.option.boolData('ViewRegisters'): for w in self.extraLabels + self.extraLcds: w.hide() self.lcd = Lcd(2.0, 13) lcdLay.addWidget(self.lcd, 3, 0, 1, 2, Qt.AlignRight) self.setLcdHighlight() self.updateLcd() self.updateColors() self.cmdLay = QGridLayout() topLay.addLayout(self.cmdLay) self.cmdDict = {} self.addCmdButton('x^2', 0, 0) self.addCmdButton('sqRT', 0, 1) self.addCmdButton('y^X', 0, 2) self.addCmdButton('xRT', 0, 3) self.addCmdButton('RCIP', 0, 4) self.addCmdButton('SIN', 1, 0) self.addCmdButton('COS', 1, 1) self.addCmdButton('TAN', 1, 2) self.addCmdButton('LN', 1, 3) self.addCmdButton('e^X', 1, 4) self.addCmdButton('ASIN', 2, 0) self.addCmdButton('ACOS', 2, 1) self.addCmdButton('ATAN', 2, 2) self.addCmdButton('LOG', 2, 3) self.addCmdButton('tn^X', 2, 4) self.addCmdButton('STO', 3, 0) self.addCmdButton('RCL', 3, 1) self.addCmdButton('R<', 3, 2) self.addCmdButton('R>', 3, 3) self.addCmdButton('x<>y', 3, 4) self.addCmdButton('SHOW', 4, 0) self.addCmdButton('CLR', 4, 1) self.addCmdButton('PLCS', 4, 2) self.addCmdButton('SCI', 4, 3) self.addCmdButton('DEG', 4, 4) self.addCmdButton('EXIT', 5, 0) self.addCmdButton('Pi', 5, 1) self.addCmdButton('EXP', 5, 2) self.addCmdButton('CHS', 5, 3) self.addCmdButton('<-', 5, 4) self.mainLay = QGridLayout() topLay.addLayout(self.mainLay) self.mainDict = {} self.addMainButton(0, 'OPT', 0, 0) self.addMainButton(Qt.Key_Slash, '/', 0, 1) self.addMainButton(Qt.Key_Asterisk, '*', 0, 2) self.addMainButton(Qt.Key_Minus, '-', 0, 3) self.addMainButton(Qt.Key_7, '7', 1, 0) self.addMainButton(Qt.Key_8, '8', 1, 1) self.addMainButton(Qt.Key_9, '9', 1, 2) self.addMainButton(Qt.Key_Plus, '+', 1, 3, 1, 0) self.addMainButton(Qt.Key_4, '4', 2, 0) self.addMainButton(Qt.Key_5, '5', 2, 1) self.addMainButton(Qt.Key_6, '6', 2, 2) self.addMainButton(Qt.Key_1, '1', 3, 0) self.addMainButton(Qt.Key_2, '2', 3, 1) self.addMainButton(Qt.Key_3, '3', 3, 2) self.addMainButton(Qt.Key_Enter, 'ENT', 3, 3, 1, 0) self.addMainButton(Qt.Key_0, '0', 4, 0, 0, 1) self.addMainButton(Qt.Key_Period, '.', 4, 2) self.mainDict[Qt.Key_Return] = \ self.mainDict[Qt.Key_Enter] # added for european keyboards: self.mainDict[Qt.Key_Comma] = \ self.mainDict[Qt.Key_Period] self.cmdDict['ENT'] = self.mainDict[Qt.Key_Enter] self.cmdDict['OPT'] = self.mainDict[0] self.entryStr = '' self.showMode = False statusBox = QFrame() statusBox.setFrameStyle(QFrame.Panel | QFrame.Sunken) statusBox.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)) topLay.addWidget(statusBox) statusLay = QHBoxLayout(statusBox) self.entryLabel = QLabel(statusBox) statusLay.addWidget(self.entryLabel) statusLay.setContentsMargins(1, 1, 1, 1) self.statusLabel = QLabel(statusBox) self.statusLabel.setAlignment(Qt.AlignRight) statusLay.addWidget(self.statusLabel) if self.calc.option.boolData('ExtraViewStartup'): self.viewReg() if self.calc.option.boolData('AltBaseStartup'): self.viewAltBases() xSize = self.calc.option.intData('MainDlgXSize', 0, 10000) ySize = self.calc.option.intData('MainDlgYSize', 0, 10000) if xSize and ySize: self.resize(xSize, ySize) self.move(self.calc.option.intData('MainDlgXPos', 0, 10000), self.calc.option.intData('MainDlgYPos', 0, 10000)) self.updateEntryLabel('rpCalc Version {0}'.format(__version__)) QTimer.singleShot(5000, self.updateEntryLabel) def updateEntryLabel(self, subsText=''): """Set entry & status label text, use entryStr or subsText, options. """ numFormat = self.calc.option.boolData('ForceSciNotation') and 'sci' \ or 'fix' decPlcs = self.calc.option.intData('NumDecimalPlaces', 0, 9) angle = self.calc.option.strData('AngleUnit') self.statusLabel.setText('{0} {1} {2}'.format(numFormat, decPlcs, angle)) self.entryLabel.setText(subsText or '> {0}'.format(self.entryStr)) def setOptions(self): """Starts option dialog, called by option key. """ oldViewReg = self.calc.option.boolData('ViewRegisters') self.optDlg = optiondlg.OptionDlg(self.calc.option, self) self.optDlg.startGroupBox('Startup', 8) optiondlg.OptionDlgBool(self.optDlg, 'SaveStacks', 'Save previous entries') optiondlg.OptionDlgBool(self.optDlg, 'ExtraViewStartup', 'Auto open extra data view') optiondlg.OptionDlgBool(self.optDlg, 'AltBaseStartup', 'Auto open alternate base view') self.optDlg.startGroupBox('Display', 8) optiondlg.OptionDlgInt(self.optDlg, 'NumDecimalPlaces', 'Number of decimal places', 0, 9) optiondlg.OptionDlgBool(self.optDlg, 'ThousandsSeparator', 'Separate thousands with spaces') optiondlg.OptionDlgBool(self.optDlg, 'ForceSciNotation', 'Always show exponent') optiondlg.OptionDlgBool(self.optDlg, 'UseEngNotation', 'Use engineering notation') optiondlg.OptionDlgBool(self.optDlg, 'TrimExponents', 'Hide exponent leading zeros') optiondlg.OptionDlgBool(self.optDlg, 'ViewRegisters', 'View Registers on LCD') optiondlg.OptionDlgBool(self.optDlg, 'HideLcdHighlight', 'Hide LCD highlight') self.optDlg.startNewColumn() optiondlg.OptionDlgRadio(self.optDlg, 'AngleUnit', 'Angular Units', [('deg', 'Degrees'), ('rad', 'Radians')]) self.optDlg.startGroupBox('Alternate Bases') optiondlg.OptionDlgInt(self.optDlg, 'AltBaseBits', 'Size limit', CalcCore.minNumBits, CalcCore.maxNumBits, True, 4, False, ' bits') optiondlg.OptionDlgBool(self.optDlg, 'UseTwosComplement', 'Use two\'s complement\nnegative numbers') self.optDlg.startGroupBox('Extra Views',) optiondlg.OptionDlgPush(self.optDlg, 'View Extra Data', self.viewExtra) optiondlg.OptionDlgPush(self.optDlg, 'View Other Bases', self.viewAltBases) optiondlg.OptionDlgPush(self.optDlg, 'View Help file', self.help) optiondlg.OptionDlgInt(self.optDlg, 'MaxHistLength', 'Saved history steps', CalcCore.minMaxHist, CalcCore.maxMaxHist, True, 10) if self.optDlg.exec_() == QDialog.Accepted: self.calc.option.writeChanges() newViewReg = self.calc.option.boolData('ViewRegisters') if newViewReg != oldViewReg: if newViewReg: for w in self.extraLabels + self.extraLcds: w.show() else: for w in self.extraLabels + self.extraLcds: w.hide() qApp.processEvents() self.adjustSize() if self.altBaseView: self.altBaseView.updateOptions() self.setLcdHighlight() self.calc.updateXStr() self.optDlg = None def setLcdHighlight(self): """Set lcd highlight based on option. """ opt = self.calc.option.boolData('HideLcdHighlight') and \ QLCDNumber.Flat or QLCDNumber.Filled self.lcd.setSegmentStyle(opt) for lcd in self.extraLcds: lcd.setSegmentStyle(opt) def updateColors(self): """Adjust the colors to the current option settings. """ if self.calc.option.boolData('UseDefaultColors'): return pal = QApplication.palette() background = QColor(self.calc.option.intData('BackgroundR', 0, 255), self.calc.option.intData('BackgroundG', 0, 255), self.calc.option.intData('BackgroundB', 0, 255)) foreground = QColor(self.calc.option.intData('ForegroundR', 0, 255), self.calc.option.intData('ForegroundG', 0, 255), self.calc.option.intData('ForegroundB', 0, 255)) pal.setColor(QPalette.Base, background) pal.setColor(QPalette.Text, foreground) QApplication.setPalette(pal) def viewExtra(self, defaultTab=0): """Show extra data view. """ if self.optDlg: self.optDlg.reject() # unfortunately necessary? if not self.extraView: self.extraView = extradisplay.ExtraDisplay(self) self.extraView.tabUpdate(defaultTab) self.extraView.tab.setCurrentIndex(defaultTab) self.extraView.show() def viewReg(self): """Show extra data view with register tab open. """ self.viewExtra(0) def viewHist(self): """Show extra data view with history tab open. """ self.viewExtra(1) def viewMem(self): """Show extra data view with memory tab open. """ self.viewExtra(2) def updateExtra(self): """Update current extra and alt base views. """ if self.extraView and self.extraView.isVisible(): self.extraView.updateData() if self.altBaseView: self.altBaseView.updateData() def toggleReg(self): """Toggle register display on LCD. """ viewReg = not self.calc.option.boolData('ViewRegisters') self.calc.option.changeData('ViewRegisters', viewReg and 'yes' or 'no', 1) if viewReg: for w in self.extraLabels + self.extraLcds: w.show() else: for w in self.extraLabels + self.extraLcds: w.hide() self.adjustSize() self.calc.updateXStr() def viewAltBases(self): """Show alternate base view. """ if self.optDlg: self.optDlg.reject() # unfortunately necessary? if not self.altBaseView: self.altBaseView = altbasedialog.AltBaseDialog(self) self.altBaseView.updateData() self.altBaseView.show() def findHelpFile(self): """Return the path to the help file. """ modPath = os.path.abspath(sys.path[0]) if modPath.endswith('.zip') or modPath.endswith('.exe'): modPath = os.path.dirname(modPath) # for py2exe/cx_freeze pathList = [helpFilePath, os.path.join(modPath, '../doc/'), modPath, 'doc/'] for path in pathList: if path: try: fullPath = os.path.join(path, 'README.html') with open(fullPath, 'r', encoding='utf-8') as f: pass return fullPath except IOError: pass return '' def help(self): """View the ReadMe file. """ if self.optDlg: self.optDlg.reject() # unfortunately necessary? if not self.helpView: path = self.findHelpFile() if not path: QMessageBox.warning(self, 'rpCalc', 'Read Me file not found') return self.helpView = helpview.HelpView(path, 'rpCalc README File', self.icons, self) self.helpView.show() def about(self): """About this program. """ QMessageBox.about(self, 'rpCalc', 'rpCalc, Version {0}\n by {1}'. format(__version__, __author__)) def addCmdButton(self, text, row, col): """Adds a CalcButton for command functions. """ button = CalcButton(text) self.cmdDict[text.upper()] = button self.cmdLay.addWidget(button, row, col) button.activated.connect(self.issueCmd) def addMainButton(self, key, text, row, col, extraRow=0, extraCol=0): """Adds a CalcButton for number and 4-function keys. """ button = CalcButton(text) self.mainDict[key] = button self.mainLay.addWidget(button, row, col, 1+extraRow, 1+extraCol) button.activated.connect(self.issueCmd) def updateLcd(self): """Sets display back to CalcCore string. """ numDigits = int(self.calc.option.numData('NumDecimalPlaces', 0, 9)) + 9 if self.calc.option.boolData('ThousandsSeparator') or \ self.calc.option.boolData('UseEngNotation'): numDigits += 2 self.lcd.setDisplay(self.calc.xStr, numDigits) if self.calc.option.boolData('ViewRegisters'): nums = [self.calc.formatNum(num) for num in self.calc.stack[1:]] for num, lcd in zip(nums, self.extraLcds): lcd.setDisplay(num, numDigits) self.updateExtra() def issueCmd(self, text): """Sends command text to CalcCore - connected to button signals. """ mode = self.calc.flag text = str(text).upper() if text == 'OPT': self.setOptions() elif text == 'SHOW': if not self.showMode: valueStr = self.calc.sciFormatX(11).replace('e', ' E', 1) self.lcd.setNumDigits(19) self.lcd.display(valueStr) self.showMode = True return elif text == 'EXIT': self.close() return else: self.calc.cmd(text) if text in ('SCI', 'DEG', 'OPT') or mode == Mode.decPlcMode: self.updateEntryLabel() self.showMode = False self.updateLcd() def textEntry(self, ch): """Searches for button match from text entry. """ if not ch: return False if ord(ch) == 8: # backspace key self.entryStr = self.entryStr[:-1] elif ord(ch) == 27: # escape key self.entryStr = '' elif ch == '\t': # tab key cmds = [key for key in self.cmdDict.keys() if key.startswith(self.entryStr.upper())] if len(cmds) == 1: button = self.cmdDict[cmds[0]] button.clickEvent() button.tmpDown(300) self.entryStr = '' else: QApplication.beep() elif ch == ':' and not self.entryStr: self.entryStr = ':' # optional command prefix else: newStr = (self.entryStr + ch).upper() if newStr == ':Q': # vim-like shortcut newStr = 'EXIT' button = self.cmdDict.get(newStr.lstrip(':')) if button: button.clickEvent() button.tmpDown(300) self.entryStr = '' else: if [key for key in self.cmdDict.keys() if key.startswith(newStr.lstrip(':'))]: self.entryStr += ch else: QApplication.beep() return False self.updateEntryLabel() return True def keyPressEvent(self, keyEvent): """Event handler for keys - checks for numbers and typed commands. """ button = self.mainDict.get(keyEvent.key()) if not self.entryStr and button: button.clickEvent() button.setDown(True) return letter = str(keyEvent.text()).upper() if keyEvent.modifiers() == Qt.AltModifier: if self.altBaseView and self.altBaseView.isVisible(): if letter in ('X', 'O', 'B', 'D'): self.altBaseView.setCodedBase(letter, False) elif letter == 'V': self.altBaseView.copyValue() elif letter == 'C': self.altBaseView.close() elif not self.entryStr and self.calc.base == 16 and \ 'A' <= letter <= 'F': self.issueCmd(keyEvent.text()) elif self.altBaseView and self.altBaseView.isVisible() and \ (self.calc.xStr == ' 0' or \ (self.calc.stack[0] == 0.0 and self.calc.base != 10)) and \ self.calc.flag == Mode.entryMode and \ letter in ('X', 'O', 'B', 'D'): self.altBaseView.setCodedBase(letter, True) elif not self.entryStr and keyEvent.key() == Qt.Key_Backspace: button = self.cmdDict['<-'] button.clickEvent() button.tmpDown(300) elif not self.entryStr and keyEvent.key() == Qt.Key_Escape: self.popupMenu.popup(self.mapToGlobal(QPoint(0, 0))) elif not self.textEntry(str(keyEvent.text())): QWidget.keyPressEvent(self, keyEvent) def keyReleaseEvent(self, keyEvent): """Event handler for keys - sets button back to raised position. """ button = self.mainDict.get(keyEvent.key()) if not self.entryStr and button: button.setDown(False) def closeEvent(self, event): """Saves the stack prior to closing. """ self.calc.saveStack() self.calc.option.changeData('MainDlgXSize', self.width(), True) self.calc.option.changeData('MainDlgYSize', self.height(), True) self.calc.option.changeData('MainDlgXPos', self.x(), True) self.calc.option.changeData('MainDlgYPos', self.y(), True) if self.extraView: self.calc.option.changeData('ExtraViewXSize', self.extraView.width(), True) self.calc.option.changeData('ExtraViewYSize', self.extraView.height(), True) self.calc.option.changeData('ExtraViewXPos', self.extraView.x(), True) self.calc.option.changeData('ExtraViewYPos', self.extraView.y(), True) if self.altBaseView: self.calc.option.changeData('AltBaseXPos', self.altBaseView.x(), True) self.calc.option.changeData('AltBaseYPos', self.altBaseView.y(), True) self.calc.option.writeChanges() QWidget.closeEvent(self, event)
class ApplicationWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setWindowTitle("程序主窗口") self.files = [] #---------file menu ------------------------------- self.file_menu = QMenu('&File', self) self.file_menu.addAction('&Quit', self.fileQuit, QtCore.Qt.CTRL + QtCore.Qt.Key_Q) self.menuBar().addMenu(self.file_menu) #====================================================== # ---------ta menu ---------------------------------------------- self.ta_menu = QMenu('&Ta', self) # ++++++++++++++++RSI analyse++++++++++++++++++++++++ self.add_menu_item(self.ta_menu, 'Ca&p 独立', self.taRSI, QtCore.Qt.CTRL + QtCore.Qt.Key_P) #+++++++++++++++++Cap analyse+++++++++++++++++++++++++ self.add_menu_item(self.ta_menu, '&Cap 集成', self.taCap, QtCore.Qt.CTRL + QtCore.Qt.Key_A) # ================================================================ # ---------control START/STOP menu ---------------------------------------------- ''' elf.start_menu = QMenu('&Start', self) 3self.menuBar().addMenu(self.start_menu) #self.start_menu.addAction('&Start', self.taStart) # 添加事件 self.start_menu.get.connect(self.taStart) ''' #---------help menu --------------------------------- self.help_menu = QMenu('&Help', self) self.menuBar().addSeparator() self.menuBar().addMenu(self.help_menu) self.help_menu.addAction('&About', self.about) # ====================================================== ''' self.main_widget = QWidget(self) l = QVBoxLayout(self.main_widget) self.fig=Widget(self.main_widget, width=16, height=12, dpi=100) l.addWidget(self.fig) self.main_widget.setFocus() self.setCentralWidget(self.main_widget) ''' # 状态条显示2秒 self.statusBar().showMessage("hello matplotlib", 2000) # start stop def taStart(self): QMessageBox.about(self, "taStart", "taStart") #资金流分析 def taCap(self): cap_path = 'data0322' filters = ['CAP-002', '005.dat'] if len(self.files) == 0: self.files = tls.get_filelist_from_path(cap_path, filters) stock, week, cap_data, kdata = tls.read_stock_data(self.files[0]) count = len(cap_data) self.files = self.files[1:] x = np.arange(0, count, 1) klen = len(kdata) if klen == count: flow = (cap_data['HugeBuy'] - cap_data['HugeSell'] + cap_data['BigBuy'] - cap_data['BigSell']).values # 累计主力总资金流 total_flow = [flow[0]] for i in range(1, count): total_flow.append(total_flow[i - 1] + flow[i]) self.fig.draw_fig(0, x, kdata.loc[:, 'close'], text=stock, ylabel='close') self.fig.draw_fig(1, x, total_flow, ylabel='flow') self.fig.draw_fig(2, x, flow, ylabel='delta') self.fig.set_xlabel(stock) main_ui.setWindowTitle(CAPITION + ' ' + stock) #self.fig.update_fig() # 资金流分析 def taRSI(self): cap_path = 'data0322' filters = ['CAP-002', '005.dat'] if len(self.files) == 0: self.files = tls.get_filelist_from_path(cap_path, filters) stock, week, cap_data, kdata = tls.read_stock_data(self.files[0]) count = len(cap_data) self.files = self.files[1:] x = np.arange(0, count, 1) klen = len(kdata) if klen == count: flow = (cap_data['HugeBuy'] - cap_data['HugeSell'] + cap_data['BigBuy'] - cap_data['BigSell']).values # 累计主力总资金流 total_flow = [flow[0]] for i in range(1, count): total_flow.append(total_flow[i - 1] + flow[i]) tls.draw_kline(stock, kdata, 0, 0, week, 100, 311, total_flow) # 增加菜单项 def add_menu_item(self, menu, menu_name, menu_op, op_link): menu.addAction(menu_name, menu_op, op_link) self.menuBar().addMenu(menu) def fileQuit(self): self.close() def closeEvent(self, ce): self.fileQuit() def about(self): QMessageBox.about( self, "About", """embedding_in_qt5.py example Copyright 2015 BoxControL This program is a simple example of a Qt5 application embedding matplotlib canvases. It is base on example from matplolib documentation, and initially was developed from Florent Rougon and Darren Dale. http://matplotlib.org/examples/user_interfaces/embedding_in_qt4.html It may be used and modified with no restriction; raw copies as well as modified versions may be distributed without limitation. """)
def contextMenuEvent(self, event): # Update selection self.updateSelection() # Set context menu mode app = get_app() app.context_menu_object = "files" menu = QMenu(self) menu.addAction(self.win.actionImportFiles) menu.addSeparator() if self.selected: # If file selected, show file related options menu.addAction(self.win.actionFile_Properties) menu.addAction(self.win.actionPreview_File) menu.addAction(self.win.actionSplitClip) menu.addAction(self.win.actionAdd_to_Timeline) menu.addSeparator() #menu.addAction(self.win.actionFile_Properties) menu.addAction(self.win.actionRemove_from_Project) menu.addSeparator() menu.addAction(self.win.actionThumbnailView) # Show menu menu.exec_(QCursor.pos())
class MainWindow(QMainWindow, Ui_MainWindow, buscaLargura, buscaProfundidade): def __init__(self, parent=None): QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.setupUi(self) #para colocar robo animado self.movie = QMovie("robot.gif") self.movie.frameChanged.connect(self.repaint) self.movie.start() self.timer = QTimer(self) self.paredes = 0 self.caminho = 1 self.entrada = 2 self.saida = 3 self.pegadas = 4 self.jaVisitado = 5 self.labirinto = [] #para armazenar historico do percurso self.fila_i = [] self.fila_j = [] self.fila_pegadas = [] self.createActions() self.createMenus() self.pushButton01.clicked.connect(self.simule) self.pushButton02.clicked.connect(self.limparCaminhada) self.events() self.timer.setInterval(200) self.timer.start() #funcao que anima robo def paintEvent(self, event): currentFrame = self.movie.currentPixmap() frameRect = currentFrame.rect() frameRect.moveCenter(self.rect().center()) if frameRect.intersects(event.rect()): painter = QPainter(self) painter.drawPixmap(frameRect.left(), frameRect.top(), currentFrame) def events(self): self.timer.timeout.connect(self.update) def update(self): if (len(self.labirinto) > 0 and len(self.fila_pegadas) > 0): self.alteraLabirinto() self.aplicateColors() self.pushButton02.setEnabled(True) def simule(self): if (self.radioButton01.isChecked()): self.limparCaminhada() self.buscaEmLargura() elif (self.radioButton02.isChecked()): self.limparCaminhada() self.buscaEmProfundidade() else: return def limparCaminhada(self): self.clear() self.labirinto = np.loadtxt(self.filename[0], dtype='int', delimiter=' ') self.aplicateColors() self.fila_i.clear() self.fila_j.clear() self.fila_pegadas.clear() def alteraLabirinto(self): if (len(self.fila_pegadas) > 0): self.labirinto[self.fila_i[0]][ self.fila_j[0]] = self.fila_pegadas[0] self.fila_i.pop(0) self.fila_j.pop(0) self.fila_pegadas.pop(0) def buscaEmLargura(self): self.variavel = buscaLargura(self.filename[0]) self.fila_i, self.fila_j, self.fila_pegadas = self.variavel.percorreLabirinto( ) #print(self.fila_i, self.fila_j, self.fila_pegadas) def buscaEmProfundidade(self): self.variavel = buscaProfundidade(self.filename[0]) self.fila_i, self.fila_j, self.fila_pegadas = self.variavel.percorreLabirinto( ) #print(self.fila_i, self.fila_j, self.fila_pegadas) def createActions(self): self.openAct = QAction("&Open Archive", self, shortcut="Ctrl+O", triggered=self.open) def open(self): self.filename = QFileDialog.getOpenFileName(self, 'Open File', os.getenv('HOME')) self.labirinto = np.loadtxt(self.filename[0], dtype='int', delimiter=' ') self.movie = QMovie() #retirando robozinho self.aplicateColors() self.pushButton01.setEnabled(True) self.radioButton01.setEnabled(True) self.radioButton02.setEnabled(True) #print(self.labirinto) #self.label.setText(filename[0]) def clear(self): while self.gridLayout_3.count(): item = self.gridLayout_3.takeAt(0) widget = item.widget() widget.deleteLater() def createMenus(self): self.fileMenu = QMenu("&Menu", self) self.fileMenu.addSeparator() self.fileMenu.addAction(self.openAct) self.fileMenu.addSeparator() self.menuBar().addMenu(self.fileMenu) def aplicateColors(self): sleep(0.2) self.clear() for i in range(len(self.labirinto)): for j in range(len(self.labirinto)): if (self.labirinto[i][j] == self.caminho or self.labirinto[i][j] == self.jaVisitado): self.b1 = QPushButton("pushButton_" + str(i) + "_" + str(j)) self.b1.setStyleSheet("background-color : white") self.b1.setFixedSize(int(500 / len(self.labirinto)), int(500 / len(self.labirinto))) self.b1.setText(" ") self.b1.setEnabled(False) self.gridLayout_3.addWidget(self.b1, i, j) elif (self.labirinto[i][j] == self.paredes): self.b1 = QPushButton("pushButton_" + str(i) + "_" + str(j)) self.b1.setStyleSheet("background-color : black") self.b1.setFixedSize(int(500 / len(self.labirinto)), int(500 / len(self.labirinto))) self.b1.setText(" ") self.b1.setEnabled(False) self.gridLayout_3.addWidget(self.b1, i, j) elif (self.labirinto[i][j] == self.entrada): self.b1 = QPushButton("pushButton_" + str(i) + "_" + str(j)) self.b1.setStyleSheet("background-color : red") self.b1.setFixedSize(int(500 / len(self.labirinto)), int(500 / len(self.labirinto))) self.b1.setText(" ") self.b1.setEnabled(False) self.gridLayout_3.addWidget(self.b1, i, j) elif (self.labirinto[i][j] == self.saida): self.b1 = QPushButton("pushButton_" + str(i) + "_" + str(j)) self.b1.setStyleSheet("background-color : green") self.b1.setFixedSize(int(500 / len(self.labirinto)), int(500 / len(self.labirinto))) self.b1.setText(" ") self.b1.setEnabled(False) self.gridLayout_3.addWidget(self.b1, i, j) elif (self.labirinto[i][j] == self.pegadas): self.b1 = QPushButton("pushButton_" + str(i) + "_" + str(j)) self.b1.setStyleSheet("background-color : yellow") self.b1.setFixedSize(int(500 / len(self.labirinto)), int(500 / len(self.labirinto))) self.b1.setText(" ") self.b1.setEnabled(False) self.gridLayout_3.addWidget(self.b1, i, j) else: return
class outlineBasics(QAbstractItemView): def __init__(self, parent=None): self._indexesToOpen = None self.menuCustomIcons = None def getSelection(self): sel = [] for i in self.selectedIndexes(): if i.column() != 0: continue if not i in sel: sel.append(i) return sel def mouseReleaseEvent(self, event): if event.button() == Qt.RightButton: self.menu = self.makePopupMenu() self.menu.popup(event.globalPos()) # We don't call QAbstractItemView.mouseReleaseEvent because # outlineBasics is never subclassed alone. So the others views # (outlineView, corkView, treeView) that subclass outlineBasics # call their respective mother class. def makePopupMenu(self): index = self.currentIndex() sel = self.getSelection() clipboard = qApp.clipboard() menu = QMenu(self) # Get index under cursor pos = self.viewport().mapFromGlobal(QCursor.pos()) mouseIndex = self.indexAt(pos) # Get index's title if mouseIndex.isValid(): title = mouseIndex.internalPointer().title() elif self.rootIndex().parent().isValid(): # mouseIndex is the background of an item, so we check the parent mouseIndex = self.rootIndex().parent() title = mouseIndex.internalPointer().title() else: title = qApp.translate("outlineBasics", "Root") if len(title) > 25: title = title[:25] + "…" # Open Item action self.actOpen = QAction( QIcon.fromTheme("go-right"), qApp.translate("outlineBasics", "Open {}".format(title)), menu) self.actOpen.triggered.connect(self.openItem) menu.addAction(self.actOpen) # Open item(s) in new tab if mouseIndex in sel and len(sel) > 1: actionTitle = qApp.translate("outlineBasics", "Open {} items in new tabs").format( len(sel)) self._indexesToOpen = sel else: actionTitle = qApp.translate("outlineBasics", "Open {} in a new tab").format(title) self._indexesToOpen = [mouseIndex] self.actNewTab = QAction(QIcon.fromTheme("go-right"), actionTitle, menu) self.actNewTab.triggered.connect(self.openItemsInNewTabs) menu.addAction(self.actNewTab) menu.addSeparator() # Add text / folder self.actAddFolder = QAction( QIcon.fromTheme("folder-new"), qApp.translate("outlineBasics", "New &Folder"), menu) self.actAddFolder.triggered.connect(self.addFolder) menu.addAction(self.actAddFolder) self.actAddText = QAction(QIcon.fromTheme("document-new"), qApp.translate("outlineBasics", "New &Text"), menu) self.actAddText.triggered.connect(self.addText) menu.addAction(self.actAddText) menu.addSeparator() # Copy, cut, paste, duplicate self.actCut = QAction(QIcon.fromTheme("edit-cut"), qApp.translate("outlineBasics", "C&ut"), menu) self.actCut.triggered.connect(self.cut) menu.addAction(self.actCut) self.actCopy = QAction(QIcon.fromTheme("edit-copy"), qApp.translate("outlineBasics", "&Copy"), menu) self.actCopy.triggered.connect(self.copy) menu.addAction(self.actCopy) self.actPaste = QAction(QIcon.fromTheme("edit-paste"), qApp.translate("outlineBasics", "&Paste"), menu) self.actPaste.triggered.connect(self.paste) menu.addAction(self.actPaste) # Rename / duplicate / remove items self.actDelete = QAction(QIcon.fromTheme("edit-delete"), qApp.translate("outlineBasics", "&Delete"), menu) self.actDelete.triggered.connect(self.delete) menu.addAction(self.actDelete) self.actRename = QAction(QIcon.fromTheme("edit-rename"), qApp.translate("outlineBasics", "&Rename"), menu) self.actRename.triggered.connect(self.rename) menu.addAction(self.actRename) menu.addSeparator() # POV self.menuPOV = QMenu(qApp.translate("outlineBasics", "Set POV"), menu) mw = mainWindow() a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuPOV) a.triggered.connect(lambda: self.setPOV("")) self.menuPOV.addAction(a) self.menuPOV.addSeparator() menus = [] for i in [ qApp.translate("outlineBasics", "Main"), qApp.translate("outlineBasics", "Secondary"), qApp.translate("outlineBasics", "Minor") ]: m = QMenu(i, self.menuPOV) menus.append(m) self.menuPOV.addMenu(m) mpr = QSignalMapper(self.menuPOV) for i in range(mw.mdlCharacter.rowCount()): a = QAction(mw.mdlCharacter.icon(i), mw.mdlCharacter.name(i), self.menuPOV) a.triggered.connect(mpr.map) mpr.setMapping(a, int(mw.mdlCharacter.ID(i))) imp = toInt(mw.mdlCharacter.importance(i)) menus[2 - imp].addAction(a) mpr.mapped.connect(self.setPOV) menu.addMenu(self.menuPOV) # Status self.menuStatus = QMenu(qApp.translate("outlineBasics", "Set Status"), menu) # a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus) # a.triggered.connect(lambda: self.setStatus("")) # self.menuStatus.addAction(a) # self.menuStatus.addSeparator() mpr = QSignalMapper(self.menuStatus) for i in range(mw.mdlStatus.rowCount()): a = QAction(mw.mdlStatus.item(i, 0).text(), self.menuStatus) a.triggered.connect(mpr.map) mpr.setMapping(a, i) self.menuStatus.addAction(a) mpr.mapped.connect(self.setStatus) menu.addMenu(self.menuStatus) # Labels self.menuLabel = QMenu(qApp.translate("outlineBasics", "Set Label"), menu) mpr = QSignalMapper(self.menuLabel) for i in range(mw.mdlLabels.rowCount()): a = QAction( mw.mdlLabels.item(i, 0).icon(), mw.mdlLabels.item(i, 0).text(), self.menuLabel) a.triggered.connect(mpr.map) mpr.setMapping(a, i) self.menuLabel.addAction(a) mpr.mapped.connect(self.setLabel) menu.addMenu(self.menuLabel) menu.addSeparator() # Custom icons if self.menuCustomIcons: menu.addMenu(self.menuCustomIcons) else: self.menuCustomIcons = QMenu( qApp.translate("outlineBasics", "Set Custom Icon"), menu) a = QAction(qApp.translate("outlineBasics", "Restore to default"), self.menuCustomIcons) a.triggered.connect(lambda: self.setCustomIcon("")) self.menuCustomIcons.addAction(a) self.menuCustomIcons.addSeparator() txt = QLineEdit() txt.textChanged.connect(self.filterLstIcons) txt.setPlaceholderText("Filter icons") txt.setStyleSheet( "QLineEdit { background: transparent; border: none; }") act = QWidgetAction(self.menuCustomIcons) act.setDefaultWidget(txt) self.menuCustomIcons.addAction(act) self.lstIcons = QListWidget() for i in customIcons(): item = QListWidgetItem() item.setIcon(QIcon.fromTheme(i)) item.setData(Qt.UserRole, i) item.setToolTip(i) self.lstIcons.addItem(item) self.lstIcons.itemClicked.connect(self.setCustomIconFromItem) self.lstIcons.setViewMode(self.lstIcons.IconMode) self.lstIcons.setUniformItemSizes(True) self.lstIcons.setResizeMode(self.lstIcons.Adjust) self.lstIcons.setMovement(self.lstIcons.Static) self.lstIcons.setStyleSheet( "background: transparent; background: none;") self.filterLstIcons("") act = QWidgetAction(self.menuCustomIcons) act.setDefaultWidget(self.lstIcons) self.menuCustomIcons.addAction(act) menu.addMenu(self.menuCustomIcons) # Disabling stuff if not clipboard.mimeData().hasFormat("application/xml"): self.actPaste.setEnabled(False) if len(sel) == 0: self.actCopy.setEnabled(False) self.actCut.setEnabled(False) self.actRename.setEnabled(False) self.actDelete.setEnabled(False) self.menuPOV.setEnabled(False) self.menuStatus.setEnabled(False) self.menuLabel.setEnabled(False) self.menuCustomIcons.setEnabled(False) if len(sel) > 1: self.actRename.setEnabled(False) return menu def openItem(self): #idx = self.currentIndex() idx = self._indexesToOpen[0] from manuskript.functions import MW MW.openIndex(idx) def openItemsInNewTabs(self): from manuskript.functions import MW MW.openIndexes(self._indexesToOpen) def rename(self): if len(self.getSelection()) == 1: index = self.currentIndex() self.edit(index) elif len(self.getSelection()) > 1: # FIXME: add smart rename pass def addFolder(self): self.addItem("folder") def addText(self): self.addItem("text") def addItem(self, _type="folder"): if len(self.selectedIndexes()) == 0: parent = self.rootIndex() else: parent = self.currentIndex() if _type == "text": _type = settings.defaultTextType item = outlineItem(title=qApp.translate("outlineBasics", "New"), _type=_type) self.model().appendItem(item, parent) def copy(self): mimeData = self.model().mimeData( self.selectionModel().selectedIndexes()) qApp.clipboard().setMimeData(mimeData) def paste(self, mimeData=None): """ Paste item from mimeData to selected item. If mimeData is not given, it is taken from clipboard. If not item selected, paste into root. """ index = self.currentIndex() if len(self.getSelection()) == 0: index = self.rootIndex() if not mimeData: mimeData = qApp.clipboard().mimeData() self.model().dropMimeData(mimeData, Qt.CopyAction, -1, 0, index) def cut(self): self.copy() self.delete() def delete(self): """ Shows a warning, and then deletes currently selected indexes. """ if not settings.dontShowDeleteWarning: msg = QMessageBox( QMessageBox.Warning, qApp.translate("outlineBasics", "About to remove"), qApp.translate( "outlineBasics", "<p><b>You're about to delete {} item(s).</b></p><p>Are you sure?</p>" ).format(len(self.getSelection())), QMessageBox.Yes | QMessageBox.Cancel) chk = QCheckBox("&Don't show this warning in the future.") msg.setCheckBox(chk) ret = msg.exec() if ret == QMessageBox.Cancel: return if chk.isChecked(): settings.dontShowDeleteWarning = True self.model().removeIndexes(self.getSelection()) def duplicate(self): """ Duplicates item(s), while preserving clipboard content. """ mimeData = self.model().mimeData( self.selectionModel().selectedIndexes()) self.paste(mimeData) def move(self, delta=1): """ Move selected items up or down. """ # we store selected indexes currentID = self.model().ID(self.currentIndex()) selIDs = [self.model().ID(i) for i in self.selectedIndexes()] # Block signals self.blockSignals(True) self.selectionModel().blockSignals(True) # Move each index individually for idx in self.selectedIndexes(): self.moveIndex(idx, delta) # Done the hardcore way, so inform views self.model().layoutChanged.emit() # restore selection selIdx = [self.model().getIndexByID(ID) for ID in selIDs] sm = self.selectionModel() sm.clear() [sm.select(idx, sm.Select) for idx in selIdx] sm.setCurrentIndex(self.model().getIndexByID(currentID), sm.Select) #self.setSmsgBoxelectionModel(sm) # Unblock signals self.blockSignals(False) self.selectionModel().blockSignals(False) def moveIndex(self, index, delta=1): """ Move the item represented by index. +1 means down, -1 means up. """ if not index.isValid(): return if index.parent().isValid(): parentItem = index.parent().internalPointer() else: parentItem = index.model().rootItem parentItem.childItems.insert(index.row() + delta, parentItem.childItems.pop(index.row())) parentItem.updateWordCount() def moveUp(self): self.move(-1) def moveDown(self): self.move(+1) def splitDialog(self): """ Opens a dialog to split selected items. Call context: if at least one index is selected. Folder or text. """ indexes = self.getSelection() if len(indexes) == 0: # No selection, we use parent indexes = [self.rootIndex()] splitDialog(self, indexes) def merge(self): """ Merges selected items together. Call context: Multiple selection, same parent. """ # Get selection indexes = self.getSelection() # Get items items = [i.internalPointer() for i in indexes if i.isValid()] # Remove folders items = [i for i in items if not i.isFolder()] # Check that we have at least 2 items if len(items) < 2: statusMessage(qApp.translate( "outlineBasics", "Select at least two items. Folders are ignored."), importance=2) return # Check that all share the same parent p = items[0].parent() for i in items: if i.parent() != p: statusMessage(qApp.translate( "outlineBasics", "All items must be on the same level (share the same parent)." ), importance=2) return # Sort items by row items = sorted(items, key=lambda i: i.row()) items[0].mergeWith(items[1:]) def setPOV(self, POV): for i in self.getSelection(): self.model().setData(i.sibling(i.row(), Outline.POV), str(POV)) def setStatus(self, status): for i in self.getSelection(): self.model().setData(i.sibling(i.row(), Outline.status), str(status)) def setLabel(self, label): for i in self.getSelection(): self.model().setData(i.sibling(i.row(), Outline.label), str(label)) def setCustomIcon(self, customIcon): for i in self.getSelection(): item = i.internalPointer() item.setCustomIcon(customIcon) def setCustomIconFromItem(self, item): icon = item.data(Qt.UserRole) self.setCustomIcon(icon) self.menu.close() def filterLstIcons(self, text): for l in self.lstIcons.findItems("", Qt.MatchContains): l.setHidden(not text in l.data(Qt.UserRole))
def showContextMenu(self, clickedObjectItem, screenPos): selection = self.mMapScene.selectedObjectItems() if (clickedObjectItem and not selection.contains(clickedObjectItem)): selection.clear() selection.insert(clickedObjectItem) self.mMapScene.setSelectedObjectItems(selection) if selection.isEmpty(): return selectedObjects = self.mapDocument().selectedObjects() objectGroups = self.mapDocument().map().objectGroups() menu = QMenu() duplicateAction = menu.addAction( self.tr("Duplicate %n Object(s)", "", selection.size()), self.duplicateObjects) removeAction = menu.addAction( self.tr("Remove %n Object(s)", "", selection.size()), self.removeObjects) duplicateAction.setIcon(QIcon("/images/16x16/stock-duplicate-16.png")) removeAction.setIcon(QIcon("/images/16x16/edit-delete.png")) menu.addSeparator() menu.addAction(self.tr("Flip Horizontally"), self.flipHorizontally, QKeySequence(self.tr("X"))) menu.addAction(self.tr("Flip Vertically"), self.flipVertically, QKeySequence(self.tr("Y"))) objectGroup = RaiseLowerHelper.sameObjectGroup(selection) if (objectGroup and objectGroup.drawOrder() == ObjectGroup.DrawOrder.IndexOrder): menu.addSeparator() menu.addAction(self.tr("Raise Object"), self.raise_, QKeySequence(self.tr("PgUp"))) menu.addAction(self.tr("Lower Object"), self.lower, QKeySequence(self.tr("PgDown"))) menu.addAction(self.tr("Raise Object to Top"), self.raiseToTop, QKeySequence(self.tr("Home"))) menu.addAction(self.tr("Lower Object to Bottom"), self.lowerToBottom, QKeySequence(self.tr("End"))) if (objectGroups.size() > 1): menu.addSeparator() moveToLayerMenu = menu.addMenu( self.tr("Move %n Object(s) to Layer", "", selectedObjects.size())) for objectGroup in objectGroups: action = moveToLayerMenu.addAction(objectGroup.name()) action.setData(objectGroup) menu.addSeparator() propIcon = QIcon("images/16x16/document-properties.png") propertiesAction = menu.addAction(propIcon, self.tr("Object &Properties...")) # TODO Implement editing of properties for multiple objects propertiesAction.setEnabled(selectedObjects.size() == 1) Utils.setThemeIcon(removeAction, "edit-delete") Utils.setThemeIcon(propertiesAction, "document-properties") action = menu.exec(screenPos) if not action: return if action == propertiesAction: mapObject = selectedObjects.first() self.mapDocument().setCurrentObject(mapObject) self.mapDocument().emitEditCurrentObject() return objectGroup = action.data() if type(objectGroup) == ObjectGroup: self.mapDocument().moveObjectsToGroup( self.mapDocument().selectedObjects(), objectGroup)
def device_discovery(self, devs): """Called when new devices have been added""" for menu in self._all_role_menus: role_menu = menu["rolemenu"] mux_menu = menu["muxmenu"] dev_group = QActionGroup(role_menu) dev_group.setExclusive(True) for d in devs: dev_node = QAction(d.name, role_menu, checkable=True, enabled=True) role_menu.addAction(dev_node) dev_group.addAction(dev_node) dev_node.toggled.connect(self._inputdevice_selected) map_node = None if d.supports_mapping: map_node = QMenu(" Input map", role_menu, enabled=False) map_group = QActionGroup(role_menu) map_group.setExclusive(True) # Connect device node to map node for easy # enabling/disabling when selection changes and device # to easily enable it dev_node.setData((map_node, d)) for c in ConfigManager().get_list_of_configs(): node = QAction(c, map_node, checkable=True, enabled=True) node.toggled.connect(self._inputconfig_selected) map_node.addAction(node) # Connect all the map nodes back to the device # action node where we can access the raw device node.setData(dev_node) map_group.addAction(node) # If this device hasn't been found before, then # select the default mapping for it. if d not in self._available_devices: last_map = Config().get("device_config_mapping") if d.name in last_map and last_map[d.name] == c: node.setChecked(True) role_menu.addMenu(map_node) dev_node.setData((map_node, d, mux_menu)) # Update the list of what devices we found # to avoid selecting default mapping for all devices when # a new one is inserted self._available_devices = () for d in devs: self._available_devices += (d, ) # Only enable MUX nodes if we have enough devies to cover # the roles for mux_node in self._all_mux_nodes: (mux, sub_nodes) = mux_node.data() if len(mux.supported_roles()) <= len(self._available_devices): mux_node.setEnabled(True) # TODO: Currently only supports selecting default mux if self._all_mux_nodes[0].isEnabled(): self._all_mux_nodes[0].setChecked(True) # If the previous length of the available devies was 0, then select # the default on. If that's not available then select the first # on in the list. # TODO: This will only work for the "Normal" mux so this will be # selected by default if Config().get("input_device") in [d.name for d in devs]: for dev_menu in self._all_role_menus[0]["rolemenu"].actions(): if dev_menu.text() == Config().get("input_device"): dev_menu.setChecked(True) else: # Select the first device in the first mux (will always be "Normal" # mux) self._all_role_menus[0]["rolemenu"].actions()[0].setChecked(True) logger.info("Select first device") self._update_input_device_footer()
def makePopupMenu(self): index = self.currentIndex() sel = self.getSelection() clipboard = qApp.clipboard() menu = QMenu(self) # Get index under cursor pos = self.viewport().mapFromGlobal(QCursor.pos()) mouseIndex = self.indexAt(pos) # Get index's title if mouseIndex.isValid(): title = mouseIndex.internalPointer().title() elif self.rootIndex().parent().isValid(): # mouseIndex is the background of an item, so we check the parent mouseIndex = self.rootIndex().parent() title = mouseIndex.internalPointer().title() else: title = qApp.translate("outlineBasics", "Root") if len(title) > 25: title = title[:25] + "…" # Open Item action self.actOpen = QAction( QIcon.fromTheme("go-right"), qApp.translate("outlineBasics", "Open {}".format(title)), menu) self.actOpen.triggered.connect(self.openItem) menu.addAction(self.actOpen) # Open item(s) in new tab if mouseIndex in sel and len(sel) > 1: actionTitle = qApp.translate("outlineBasics", "Open {} items in new tabs").format( len(sel)) self._indexesToOpen = sel else: actionTitle = qApp.translate("outlineBasics", "Open {} in a new tab").format(title) self._indexesToOpen = [mouseIndex] self.actNewTab = QAction(QIcon.fromTheme("go-right"), actionTitle, menu) self.actNewTab.triggered.connect(self.openItemsInNewTabs) menu.addAction(self.actNewTab) menu.addSeparator() # Add text / folder self.actAddFolder = QAction( QIcon.fromTheme("folder-new"), qApp.translate("outlineBasics", "New &Folder"), menu) self.actAddFolder.triggered.connect(self.addFolder) menu.addAction(self.actAddFolder) self.actAddText = QAction(QIcon.fromTheme("document-new"), qApp.translate("outlineBasics", "New &Text"), menu) self.actAddText.triggered.connect(self.addText) menu.addAction(self.actAddText) menu.addSeparator() # Copy, cut, paste, duplicate self.actCut = QAction(QIcon.fromTheme("edit-cut"), qApp.translate("outlineBasics", "C&ut"), menu) self.actCut.triggered.connect(self.cut) menu.addAction(self.actCut) self.actCopy = QAction(QIcon.fromTheme("edit-copy"), qApp.translate("outlineBasics", "&Copy"), menu) self.actCopy.triggered.connect(self.copy) menu.addAction(self.actCopy) self.actPaste = QAction(QIcon.fromTheme("edit-paste"), qApp.translate("outlineBasics", "&Paste"), menu) self.actPaste.triggered.connect(self.paste) menu.addAction(self.actPaste) # Rename / duplicate / remove items self.actDelete = QAction(QIcon.fromTheme("edit-delete"), qApp.translate("outlineBasics", "&Delete"), menu) self.actDelete.triggered.connect(self.delete) menu.addAction(self.actDelete) self.actRename = QAction(QIcon.fromTheme("edit-rename"), qApp.translate("outlineBasics", "&Rename"), menu) self.actRename.triggered.connect(self.rename) menu.addAction(self.actRename) menu.addSeparator() # POV self.menuPOV = QMenu(qApp.translate("outlineBasics", "Set POV"), menu) mw = mainWindow() a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuPOV) a.triggered.connect(lambda: self.setPOV("")) self.menuPOV.addAction(a) self.menuPOV.addSeparator() menus = [] for i in [ qApp.translate("outlineBasics", "Main"), qApp.translate("outlineBasics", "Secondary"), qApp.translate("outlineBasics", "Minor") ]: m = QMenu(i, self.menuPOV) menus.append(m) self.menuPOV.addMenu(m) mpr = QSignalMapper(self.menuPOV) for i in range(mw.mdlCharacter.rowCount()): a = QAction(mw.mdlCharacter.icon(i), mw.mdlCharacter.name(i), self.menuPOV) a.triggered.connect(mpr.map) mpr.setMapping(a, int(mw.mdlCharacter.ID(i))) imp = toInt(mw.mdlCharacter.importance(i)) menus[2 - imp].addAction(a) mpr.mapped.connect(self.setPOV) menu.addMenu(self.menuPOV) # Status self.menuStatus = QMenu(qApp.translate("outlineBasics", "Set Status"), menu) # a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus) # a.triggered.connect(lambda: self.setStatus("")) # self.menuStatus.addAction(a) # self.menuStatus.addSeparator() mpr = QSignalMapper(self.menuStatus) for i in range(mw.mdlStatus.rowCount()): a = QAction(mw.mdlStatus.item(i, 0).text(), self.menuStatus) a.triggered.connect(mpr.map) mpr.setMapping(a, i) self.menuStatus.addAction(a) mpr.mapped.connect(self.setStatus) menu.addMenu(self.menuStatus) # Labels self.menuLabel = QMenu(qApp.translate("outlineBasics", "Set Label"), menu) mpr = QSignalMapper(self.menuLabel) for i in range(mw.mdlLabels.rowCount()): a = QAction( mw.mdlLabels.item(i, 0).icon(), mw.mdlLabels.item(i, 0).text(), self.menuLabel) a.triggered.connect(mpr.map) mpr.setMapping(a, i) self.menuLabel.addAction(a) mpr.mapped.connect(self.setLabel) menu.addMenu(self.menuLabel) menu.addSeparator() # Custom icons if self.menuCustomIcons: menu.addMenu(self.menuCustomIcons) else: self.menuCustomIcons = QMenu( qApp.translate("outlineBasics", "Set Custom Icon"), menu) a = QAction(qApp.translate("outlineBasics", "Restore to default"), self.menuCustomIcons) a.triggered.connect(lambda: self.setCustomIcon("")) self.menuCustomIcons.addAction(a) self.menuCustomIcons.addSeparator() txt = QLineEdit() txt.textChanged.connect(self.filterLstIcons) txt.setPlaceholderText("Filter icons") txt.setStyleSheet( "QLineEdit { background: transparent; border: none; }") act = QWidgetAction(self.menuCustomIcons) act.setDefaultWidget(txt) self.menuCustomIcons.addAction(act) self.lstIcons = QListWidget() for i in customIcons(): item = QListWidgetItem() item.setIcon(QIcon.fromTheme(i)) item.setData(Qt.UserRole, i) item.setToolTip(i) self.lstIcons.addItem(item) self.lstIcons.itemClicked.connect(self.setCustomIconFromItem) self.lstIcons.setViewMode(self.lstIcons.IconMode) self.lstIcons.setUniformItemSizes(True) self.lstIcons.setResizeMode(self.lstIcons.Adjust) self.lstIcons.setMovement(self.lstIcons.Static) self.lstIcons.setStyleSheet( "background: transparent; background: none;") self.filterLstIcons("") act = QWidgetAction(self.menuCustomIcons) act.setDefaultWidget(self.lstIcons) self.menuCustomIcons.addAction(act) menu.addMenu(self.menuCustomIcons) # Disabling stuff if not clipboard.mimeData().hasFormat("application/xml"): self.actPaste.setEnabled(False) if len(sel) == 0: self.actCopy.setEnabled(False) self.actCut.setEnabled(False) self.actRename.setEnabled(False) self.actDelete.setEnabled(False) self.menuPOV.setEnabled(False) self.menuStatus.setEnabled(False) self.menuLabel.setEnabled(False) self.menuCustomIcons.setEnabled(False) if len(sel) > 1: self.actRename.setEnabled(False) return menu
def show_menu(self, p): """右键菜单""" menu = QMenu(self) action_info = menu.addAction('卸载') action_info.triggered.connect(self.uninstall) menu.exec_(QCursor.pos())
def create_menu(self, position): menu = QMenu() idx = self.indexAt(position) column = idx.column() or self.Columns.NAME selected_keys = [] for s_idx in self.selected_in_column(self.Columns.NAME): sel_key = self.model().itemFromIndex(s_idx).data(Qt.UserRole) selected_keys.append(sel_key) if not selected_keys or not idx.isValid(): menu.addAction(_("New contact"), lambda: self.parent.new_contact_dialog()) menu.addAction(_("Import file"), lambda: self.import_contacts()) menu.addAction(_("Export file"), lambda: self.export_contacts()) else: column_title = self.model().horizontalHeaderItem(column).text() column_data = '\n'.join(self.model().itemFromIndex(s_idx).text() for s_idx in self.selected_in_column(column)) menu.addAction(_("Copy {}").format(column_title), lambda: self.place_text_on_clipboard(column_data, title=column_title)) if column in self.editable_columns: item = self.model().itemFromIndex(idx) if item.isEditable(): # would not be editable if openalias persistent = QPersistentModelIndex(idx) menu.addAction(_("Edit {}").format(column_title), lambda p=persistent: self.edit(QModelIndex(p))) menu.addAction(_("Pay to"), lambda: self.parent.payto_contacts(selected_keys)) menu.addAction(_("Delete"), lambda: self.parent.delete_contacts(selected_keys)) URLs = [block_explorer_URL(self.config, 'addr', key) for key in filter(is_address, selected_keys)] if URLs: menu.addAction(_("View on block explorer"), lambda: [webopen(u) for u in URLs]) run_hook('create_contact_menu', menu, selected_keys) menu.exec_(self.viewport().mapToGlobal(position))
def contextMenuEvent(self, event): # Context menu menu = QMenu(self.centralWidget) # Populating the menu with actions menu.addAction(self.newAction) menu.addAction(self.openAction) menu.addAction(self.saveAction) # Separator separator = QAction(self) separator.setSeparator(True) menu.addAction(separator) menu.addAction(self.copyAction) menu.addAction(self.pasteAction) menu.addAction(self.cutAction) # Launching the menu menu.exec(event.globalPos())
class MainUI(QtWidgets.QMainWindow, main_window_class): connectionLostSignal = pyqtSignal(str, str) connectionInitiatedSignal = pyqtSignal(str) batteryUpdatedSignal = pyqtSignal(int, object, object) connectionDoneSignal = pyqtSignal(str) connectionFailedSignal = pyqtSignal(str, str) disconnectedSignal = pyqtSignal(str) linkQualitySignal = pyqtSignal(int) _input_device_error_signal = pyqtSignal(str) _input_discovery_signal = pyqtSignal(object) _log_error_signal = pyqtSignal(object, str) def __init__(self, *args): super(MainUI, self).__init__(*args) self.setupUi(self) # Restore window size if present in the config file try: size = Config().get("window_size") self.resize(size[0], size[1]) except KeyError: pass # self.setWindowState(QtCore.Qt.WindowMaximized) ###################################################### # By lxrocks # 'Skinny Progress Bar' tweak for Yosemite # Tweak progress bar - artistic I am not - so pick your own colors !!! # Only apply to Yosemite ###################################################### import platform if platform.system() == 'Darwin': (Version, junk, machine) = platform.mac_ver() logger.info("This is a MAC - checking if we can apply Progress " "Bar Stylesheet for Yosemite Skinny Bars ") yosemite = (10, 10, 0) tVersion = tuple(map(int, (Version.split(".")))) if tVersion >= yosemite: logger.info("Found Yosemite - applying stylesheet") tcss = """ QProgressBar { border: 1px solid grey; border-radius: 5px; text-align: center; } QProgressBar::chunk { background-color: """ + COLOR_BLUE + """; } """ self.setStyleSheet(tcss) else: logger.info("Pre-Yosemite - skinny bar stylesheet not applied") ###################################################### self.cf = Crazyflie(ro_cache=None, rw_cache=cfclient.config_path + "/cache") cflib.crtp.init_drivers( enable_debug_driver=Config().get("enable_debug_driver")) zmq_params = ZMQParamAccess(self.cf) zmq_params.start() zmq_leds = ZMQLEDDriver(self.cf) zmq_leds.start() self.scanner = ScannerThread() self.scanner.interfaceFoundSignal.connect(self.foundInterfaces) self.scanner.start() # Create and start the Input Reader self._statusbar_label = QLabel("No input-device found, insert one to" " fly.") self.statusBar().addWidget(self._statusbar_label) self.joystickReader = JoystickReader() self._active_device = "" # self.configGroup = QActionGroup(self._menu_mappings, exclusive=True) self._mux_group = QActionGroup(self._menu_inputdevice) self._mux_group.setExclusive(True) # TODO: Need to reload configs # ConfigManager().conf_needs_reload.add_callback(self._reload_configs) self.connect_input = QShortcut("Ctrl+I", self.connectButton, self._connect) self.cf.connection_failed.add_callback( self.connectionFailedSignal.emit) self.connectionFailedSignal.connect(self._connection_failed) self._input_device_error_signal.connect( self._display_input_device_error) self.joystickReader.device_error.add_callback( self._input_device_error_signal.emit) self._input_discovery_signal.connect(self.device_discovery) self.joystickReader.device_discovery.add_callback( self._input_discovery_signal.emit) # Hide the 'File' menu on OS X, since its only item, 'Exit', gets # merged into the application menu. if sys.platform == 'darwin': self.menuFile.menuAction().setVisible(False) # Connect UI signals self.logConfigAction.triggered.connect(self._show_connect_dialog) self.interfaceCombo.currentIndexChanged['QString'].connect( self.interfaceChanged) self.connectButton.clicked.connect(self._connect) self.scanButton.clicked.connect(self._scan) self.menuItemConnect.triggered.connect(self._connect) self.menuItemConfInputDevice.triggered.connect( self._show_input_device_config_dialog) self.menuItemExit.triggered.connect(self.closeAppRequest) self.batteryUpdatedSignal.connect(self._update_battery) self._menuitem_rescandevices.triggered.connect(self._rescan_devices) self._menuItem_openconfigfolder.triggered.connect( self._open_config_folder) self.address.setValue(0xE7E7E7E7E7) self._auto_reconnect_enabled = Config().get("auto_reconnect") self.autoReconnectCheckBox.toggled.connect( self._auto_reconnect_changed) self.autoReconnectCheckBox.setChecked(Config().get("auto_reconnect")) self._disable_input = False self.joystickReader.input_updated.add_callback( lambda *args: self._disable_input or self.cf.commander. send_setpoint(*args)) self.joystickReader.assisted_input_updated.add_callback( lambda *args: self._disable_input or self.cf.commander. send_velocity_world_setpoint(*args)) self.joystickReader.heighthold_input_updated.add_callback( lambda *args: self._disable_input or self.cf.commander. send_zdistance_setpoint(*args)) self.joystickReader.hover_input_updated.add_callback( self.cf.commander.send_hover_setpoint) # Connection callbacks and signal wrappers for UI protection self.cf.connected.add_callback(self.connectionDoneSignal.emit) self.connectionDoneSignal.connect(self._connected) self.cf.disconnected.add_callback(self.disconnectedSignal.emit) self.disconnectedSignal.connect(self._disconnected) self.cf.connection_lost.add_callback(self.connectionLostSignal.emit) self.connectionLostSignal.connect(self._connection_lost) self.cf.connection_requested.add_callback( self.connectionInitiatedSignal.emit) self.connectionInitiatedSignal.connect(self._connection_initiated) self._log_error_signal.connect(self._logging_error) self.batteryBar.setTextVisible(False) self.batteryBar.setStyleSheet(progressbar_stylesheet(COLOR_BLUE)) self.linkQualityBar.setTextVisible(False) self.linkQualityBar.setStyleSheet(progressbar_stylesheet(COLOR_BLUE)) # Connect link quality feedback self.cf.link_quality_updated.add_callback(self.linkQualitySignal.emit) self.linkQualitySignal.connect( lambda percentage: self.linkQualityBar.setValue(percentage)) self._selected_interface = None self._initial_scan = True self._scan() # Parse the log configuration files self.logConfigReader = LogConfigReader(self.cf) self._current_input_config = None self._active_config = None self._active_config = None self.inputConfig = None # Add things to helper so tabs can access it cfclient.ui.pluginhelper.cf = self.cf cfclient.ui.pluginhelper.inputDeviceReader = self.joystickReader cfclient.ui.pluginhelper.logConfigReader = self.logConfigReader cfclient.ui.pluginhelper.mainUI = self self.logConfigDialogue = LogConfigDialogue(cfclient.ui.pluginhelper) self._bootloader_dialog = BootloaderDialog(cfclient.ui.pluginhelper) self._cf2config_dialog = Cf2ConfigDialog(cfclient.ui.pluginhelper) self._cf1config_dialog = Cf1ConfigDialog(cfclient.ui.pluginhelper) self.menuItemBootloader.triggered.connect(self._bootloader_dialog.show) self._about_dialog = AboutDialog(cfclient.ui.pluginhelper) self.menuItemAbout.triggered.connect(self._about_dialog.show) self._menu_cf2_config.triggered.connect(self._cf2config_dialog.show) self._menu_cf1_config.triggered.connect(self._cf1config_dialog.show) # Load and connect tabs self.tabsMenuItem = QMenu("Tabs", self.menuView, enabled=True) self.menuView.addMenu(self.tabsMenuItem) # self.tabsMenuItem.setMenu(QtWidgets.QMenu()) tabItems = {} self.loadedTabs = [] for tabClass in cfclient.ui.tabs.available: tab = tabClass(self.tabs, cfclient.ui.pluginhelper) item = QtWidgets.QAction(tab.getMenuName(), self, checkable=True) item.toggled.connect(tab.toggleVisibility) self.tabsMenuItem.addAction(item) tabItems[tab.getTabName()] = item self.loadedTabs.append(tab) if not tab.enabled: item.setEnabled(False) # First instantiate all tabs and then open them in the correct order try: for tName in Config().get("open_tabs").split(","): logger.info("opening tabs [{}]".format(tName)) t = tabItems[tName] if (t is not None and t.isEnabled()): # Toggle though menu so it's also marked as open there t.toggle() except Exception as e: logger.warning("Exception while opening tabs [{}]".format(e)) # Loading toolboxes (A bit of magic for a lot of automatic) self.toolboxesMenuItem = QMenu("Toolboxes", self.menuView, enabled=True) self.menuView.addMenu(self.toolboxesMenuItem) self.toolboxes = [] for t_class in cfclient.ui.toolboxes.toolboxes: toolbox = t_class(cfclient.ui.pluginhelper) dockToolbox = MyDockWidget(toolbox.getName()) dockToolbox.setWidget(toolbox) self.toolboxes += [ dockToolbox, ] # Add menu item for the toolbox item = QtWidgets.QAction(toolbox.getName(), self) item.setCheckable(True) item.triggered.connect(self.toggleToolbox) self.toolboxesMenuItem.addAction(item) dockToolbox.closed.connect(lambda: self.toggleToolbox(False)) # Setup some introspection item.dockToolbox = dockToolbox item.menuItem = item dockToolbox.dockToolbox = dockToolbox dockToolbox.menuItem = item # References to all the device sub-menus in the "Input device" menu self._all_role_menus = () # Used to filter what new devices to add default mapping to self._available_devices = () # Keep track of mux nodes so we can enable according to how many # devices we have self._all_mux_nodes = () # Check which Input muxes are available self._mux_group = QActionGroup(self._menu_inputdevice) self._mux_group.setExclusive(True) for m in self.joystickReader.available_mux(): node = QAction(m.name, self._menu_inputdevice, checkable=True, enabled=False) node.toggled.connect(self._mux_selected) self._mux_group.addAction(node) self._menu_inputdevice.addAction(node) self._all_mux_nodes += (node, ) mux_subnodes = () for name in m.supported_roles(): sub_node = QMenu(" {}".format(name), self._menu_inputdevice, enabled=False) self._menu_inputdevice.addMenu(sub_node) mux_subnodes += (sub_node, ) self._all_role_menus += ({ "muxmenu": node, "rolemenu": sub_node }, ) node.setData((m, mux_subnodes)) self._mapping_support = True self.sendHexButton.clicked.connect(self.send_hex) def send_hex(self): import struct from cflib.crtp.crtpstack import CRTPPacket, CRTPPort hex_string = self.hexEdit.text() hex_string = hex_string.replace(":", " ") pk = CRTPPacket() pk.header = 0x00 pk.data = bytes.fromhex(hex_string) self.cf.send_packet(pk) def disable_input(self, disable): """ Disable the gamepad input to be able to send setpoint from a tab """ self._disable_input = disable def interfaceChanged(self, interface): if interface == INTERFACE_PROMPT_TEXT: self._selected_interface = None else: self._selected_interface = interface self._update_ui_state() def foundInterfaces(self, interfaces): selected_interface = self._selected_interface self.interfaceCombo.clear() self.interfaceCombo.addItem(INTERFACE_PROMPT_TEXT) formatted_interfaces = [] for i in interfaces: if len(i[1]) > 0: interface = "%s - %s" % (i[0], i[1]) else: interface = i[0] formatted_interfaces.append(interface) self.interfaceCombo.addItems(formatted_interfaces) if self._initial_scan: self._initial_scan = False try: if len(Config().get("link_uri")) > 0: formatted_interfaces.index(Config().get("link_uri")) selected_interface = Config().get("link_uri") except KeyError: # The configuration for link_uri was not found pass except ValueError: # The saved URI was not found while scanning pass if len(interfaces) == 1 and selected_interface is None: selected_interface = interfaces[0][0] newIndex = 0 if selected_interface is not None: try: newIndex = formatted_interfaces.index(selected_interface) + 1 except ValueError: pass self.interfaceCombo.setCurrentIndex(newIndex) self.uiState = UIState.DISCONNECTED self._update_ui_state() def _update_ui_state(self): if self.uiState == UIState.DISCONNECTED: self.setWindowTitle("Not connected") canConnect = self._selected_interface is not None self.menuItemConnect.setText("Connect to Crazyflie") self.menuItemConnect.setEnabled(canConnect) self.connectButton.setText("Connect") self.connectButton.setToolTip("Connect to the Crazyflie on" "the selected interface (Ctrl+I)") self.connectButton.setEnabled(canConnect) self.scanButton.setText("Scan") self.scanButton.setEnabled(True) self.address.setEnabled(True) self.batteryBar.setValue(3000) self._menu_cf2_config.setEnabled(False) self._menu_cf1_config.setEnabled(True) self.linkQualityBar.setValue(0) self.menuItemBootloader.setEnabled(True) self.logConfigAction.setEnabled(False) self.interfaceCombo.setEnabled(True) elif self.uiState == UIState.CONNECTED: s = "Connected on %s" % self._selected_interface self.setWindowTitle(s) self.menuItemConnect.setText("Disconnect") self.menuItemConnect.setEnabled(True) self.connectButton.setText("Disconnect") self.connectButton.setToolTip("Disconnect from" "the Crazyflie (Ctrl+I)") self.scanButton.setEnabled(False) self.logConfigAction.setEnabled(True) # Find out if there's an I2C EEPROM, otherwise don't show the # dialog. if len(self.cf.mem.get_mems(MemoryElement.TYPE_I2C)) > 0: self._menu_cf2_config.setEnabled(True) self._menu_cf1_config.setEnabled(False) elif self.uiState == UIState.CONNECTING: s = "Connecting to {} ...".format(self._selected_interface) self.setWindowTitle(s) self.menuItemConnect.setText("Cancel") self.menuItemConnect.setEnabled(True) self.connectButton.setText("Cancel") self.connectButton.setToolTip("Cancel connecting to the Crazyflie") self.scanButton.setEnabled(False) self.address.setEnabled(False) self.menuItemBootloader.setEnabled(False) self.interfaceCombo.setEnabled(False) elif self.uiState == UIState.SCANNING: self.setWindowTitle("Scanning ...") self.connectButton.setText("Connect") self.menuItemConnect.setEnabled(False) self.connectButton.setText("Connect") self.connectButton.setEnabled(False) self.scanButton.setText("Scanning...") self.scanButton.setEnabled(False) self.address.setEnabled(False) self.menuItemBootloader.setEnabled(False) self.interfaceCombo.setEnabled(False) @pyqtSlot(bool) def toggleToolbox(self, display): menuItem = self.sender().menuItem dockToolbox = self.sender().dockToolbox if display and not dockToolbox.isVisible(): dockToolbox.widget().enable() self.addDockWidget(dockToolbox.widget().preferedDockArea(), dockToolbox) dockToolbox.show() elif not display: dockToolbox.widget().disable() self.removeDockWidget(dockToolbox) dockToolbox.hide() menuItem.setChecked(False) def _rescan_devices(self): self._statusbar_label.setText("No inputdevice connected!") self._menu_devices.clear() self._active_device = "" self.joystickReader.stop_input() # for c in self._menu_mappings.actions(): # c.setEnabled(False) # devs = self.joystickReader.available_devices() # if (len(devs) > 0): # self.device_discovery(devs) def _show_input_device_config_dialog(self): self.inputConfig = InputConfigDialogue(self.joystickReader) self.inputConfig.show() def _auto_reconnect_changed(self, checked): self._auto_reconnect_enabled = checked Config().set("auto_reconnect", checked) logger.info("Auto reconnect enabled: {}".format(checked)) def _show_connect_dialog(self): self.logConfigDialogue.show() def _update_battery(self, timestamp, data, logconf): self.batteryBar.setValue(int(data["pm.vbat"] * 1000)) color = COLOR_BLUE # TODO firmware reports fully-charged state as 'Battery', # rather than 'Charged' if data["pm.state"] in [BatteryStates.CHARGING, BatteryStates.CHARGED]: color = COLOR_GREEN elif data["pm.state"] == BatteryStates.LOW_POWER: color = COLOR_RED self.batteryBar.setStyleSheet(progressbar_stylesheet(color)) self._aff_volts.setText(("%.3f" % data["pm.vbat"])) def _connected(self): self.uiState = UIState.CONNECTED self._update_ui_state() Config().set("link_uri", str(self._selected_interface)) lg = LogConfig("Battery", 1000) lg.add_variable("pm.vbat", "float") lg.add_variable("pm.state", "int8_t") try: self.cf.log.add_config(lg) lg.data_received_cb.add_callback(self.batteryUpdatedSignal.emit) lg.error_cb.add_callback(self._log_error_signal.emit) lg.start() except KeyError as e: logger.warning(str(e)) mems = self.cf.mem.get_mems(MemoryElement.TYPE_DRIVER_LED) if len(mems) > 0: mems[0].write_data(self._led_write_done) def _disconnected(self): self.uiState = UIState.DISCONNECTED self._update_ui_state() def _connection_initiated(self): self.uiState = UIState.CONNECTING self._update_ui_state() def _led_write_done(self, mem, addr): logger.info("LED write done callback") def _logging_error(self, log_conf, msg): QMessageBox.about( self, "Log error", "Error when starting log config" " [{}]: {}".format(log_conf.name, msg)) def _connection_lost(self, linkURI, msg): if not self._auto_reconnect_enabled: if self.isActiveWindow(): warningCaption = "Communication failure" error = "Connection lost to {}: {}".format(linkURI, msg) QMessageBox.critical(self, warningCaption, error) self.uiState = UIState.DISCONNECTED self._update_ui_state() else: self._connect() def _connection_failed(self, linkURI, error): if not self._auto_reconnect_enabled: msg = "Failed to connect on {}: {}".format(linkURI, error) warningCaption = "Communication failure" QMessageBox.critical(self, warningCaption, msg) self.uiState = UIState.DISCONNECTED self._update_ui_state() else: self._connect() def closeEvent(self, event): self.hide() self.cf.close_link() Config().save_file() def resizeEvent(self, event): Config().set( "window_size", [event.size().width(), event.size().height()]) def _connect(self): if self.uiState == UIState.CONNECTED: self.cf.close_link() elif self.uiState == UIState.CONNECTING: self.cf.close_link() self.uiState = UIState.DISCONNECTED self._update_ui_state() else: self.cf.open_link(self._selected_interface) def _scan(self): self.uiState = UIState.SCANNING self._update_ui_state() self.scanner.scanSignal.emit(self.address.value()) def _display_input_device_error(self, error): self.cf.close_link() QMessageBox.critical(self, "Input device error", error) def _mux_selected(self, checked): """Called when a new mux is selected. The menu item contains a reference to the raw mux object as well as to the associated device sub-nodes""" if not checked: (mux, sub_nodes) = self.sender().data() for s in sub_nodes: s.setEnabled(False) else: (mux, sub_nodes) = self.sender().data() for s in sub_nodes: s.setEnabled(True) self.joystickReader.set_mux(mux=mux) # Go though the tree and select devices/mapping that was # selected before it was disabled. for role_node in sub_nodes: for dev_node in role_node.children(): if type(dev_node) is QAction and dev_node.isChecked(): dev_node.toggled.emit(True) self._update_input_device_footer() def _get_dev_status(self, device): msg = "{}".format(device.name) if device.supports_mapping: map_name = "No input mapping" if device.input_map: map_name = device.input_map_name msg += " ({})".format(map_name) return msg def _update_input_device_footer(self): """Update the footer in the bottom of the UI with status for the input device and its mapping""" msg = "" if len(self.joystickReader.available_devices()) > 0: mux = self.joystickReader._selected_mux msg = "Using {} mux with ".format(mux.name) for key in list(mux._devs.keys())[:-1]: if mux._devs[key]: msg += "{}, ".format(self._get_dev_status(mux._devs[key])) else: msg += "N/A, " # Last item key = list(mux._devs.keys())[-1] if mux._devs[key]: msg += "{}".format(self._get_dev_status(mux._devs[key])) else: msg += "N/A" else: msg = "No input device found" self._statusbar_label.setText(msg) def _inputdevice_selected(self, checked): """Called when a new input device has been selected from the menu. The data in the menu object is the associated map menu (directly under the item in the menu) and the raw device""" (map_menu, device, mux_menu) = self.sender().data() if not checked: if map_menu: map_menu.setEnabled(False) # Do not close the device, since we don't know exactly # how many devices the mux can have open. When selecting a # new mux the old one will take care of this. else: if map_menu: map_menu.setEnabled(True) (mux, sub_nodes) = mux_menu.data() for role_node in sub_nodes: for dev_node in role_node.children(): if type(dev_node) is QAction and dev_node.isChecked(): if device.id == dev_node.data()[1].id \ and dev_node is not self.sender(): dev_node.setChecked(False) role_in_mux = str(self.sender().parent().title()).strip() logger.info("Role of {} is {}".format(device.name, role_in_mux)) Config().set("input_device", str(device.name)) self._mapping_support = self.joystickReader.start_input( device.name, role_in_mux) self._update_input_device_footer() def _inputconfig_selected(self, checked): """Called when a new configuration has been selected from the menu. The data in the menu object is a referance to the device QAction in parent menu. This contains a referance to the raw device.""" if not checked: return selected_mapping = str(self.sender().text()) device = self.sender().data().data()[1] self.joystickReader.set_input_map(device.name, selected_mapping) self._update_input_device_footer() def device_discovery(self, devs): """Called when new devices have been added""" for menu in self._all_role_menus: role_menu = menu["rolemenu"] mux_menu = menu["muxmenu"] dev_group = QActionGroup(role_menu) dev_group.setExclusive(True) for d in devs: dev_node = QAction(d.name, role_menu, checkable=True, enabled=True) role_menu.addAction(dev_node) dev_group.addAction(dev_node) dev_node.toggled.connect(self._inputdevice_selected) map_node = None if d.supports_mapping: map_node = QMenu(" Input map", role_menu, enabled=False) map_group = QActionGroup(role_menu) map_group.setExclusive(True) # Connect device node to map node for easy # enabling/disabling when selection changes and device # to easily enable it dev_node.setData((map_node, d)) for c in ConfigManager().get_list_of_configs(): node = QAction(c, map_node, checkable=True, enabled=True) node.toggled.connect(self._inputconfig_selected) map_node.addAction(node) # Connect all the map nodes back to the device # action node where we can access the raw device node.setData(dev_node) map_group.addAction(node) # If this device hasn't been found before, then # select the default mapping for it. if d not in self._available_devices: last_map = Config().get("device_config_mapping") if d.name in last_map and last_map[d.name] == c: node.setChecked(True) role_menu.addMenu(map_node) dev_node.setData((map_node, d, mux_menu)) # Update the list of what devices we found # to avoid selecting default mapping for all devices when # a new one is inserted self._available_devices = () for d in devs: self._available_devices += (d, ) # Only enable MUX nodes if we have enough devies to cover # the roles for mux_node in self._all_mux_nodes: (mux, sub_nodes) = mux_node.data() if len(mux.supported_roles()) <= len(self._available_devices): mux_node.setEnabled(True) # TODO: Currently only supports selecting default mux if self._all_mux_nodes[0].isEnabled(): self._all_mux_nodes[0].setChecked(True) # If the previous length of the available devies was 0, then select # the default on. If that's not available then select the first # on in the list. # TODO: This will only work for the "Normal" mux so this will be # selected by default if Config().get("input_device") in [d.name for d in devs]: for dev_menu in self._all_role_menus[0]["rolemenu"].actions(): if dev_menu.text() == Config().get("input_device"): dev_menu.setChecked(True) else: # Select the first device in the first mux (will always be "Normal" # mux) self._all_role_menus[0]["rolemenu"].actions()[0].setChecked(True) logger.info("Select first device") self._update_input_device_footer() def _open_config_folder(self): QDesktopServices.openUrl( QUrl("file:///" + QDir.toNativeSeparators(cfclient.config_path))) def closeAppRequest(self): subprocess.Popen("./run_cfclient.sh stop", shell=True) self.close()
def create_menu(self, position): selected = self.get_selected_outpoints() if not selected: return menu = QMenu() menu.setSeparatorsCollapsible(True) # consecutive separators are merged together coins = [self.utxo_dict[name] for name in selected] menu.addAction(_("Spend"), lambda: self.set_spend_list(coins)) assert len(coins) >= 1, len(coins) if len(coins) == 1: utxo = coins[0] addr = utxo.address txid = utxo.prevout.txid.hex() # "Details" tx = self.wallet.db.get_transaction(txid) if tx: label = self.wallet.get_label(txid) or None # Prefer None if empty (None hides the Description: field in the window) menu.addAction(_("Details"), lambda: self.parent.show_transaction(tx, tx_desc=label)) # "Copy ..." idx = self.indexAt(position) if not idx.isValid(): return self.add_copy_menu(menu, idx) # "Freeze coin" if not self.wallet.is_frozen_coin(utxo): menu.addAction(_("Freeze Coin"), lambda: self.parent.set_frozen_state_of_coins([utxo], True)) else: menu.addSeparator() menu.addAction(_("Coin is frozen"), lambda: None).setEnabled(False) menu.addAction(_("Unfreeze Coin"), lambda: self.parent.set_frozen_state_of_coins([utxo], False)) menu.addSeparator() # "Freeze address" if not self.wallet.is_frozen_address(addr): menu.addAction(_("Freeze Address"), lambda: self.parent.set_frozen_state_of_addresses([addr], True)) else: menu.addSeparator() menu.addAction(_("Address is frozen"), lambda: None).setEnabled(False) menu.addAction(_("Unfreeze Address"), lambda: self.parent.set_frozen_state_of_addresses([addr], False)) menu.addSeparator() else: # multiple items selected menu.addSeparator() addrs = [utxo.address for utxo in coins] is_coin_frozen = [self.wallet.is_frozen_coin(utxo) for utxo in coins] is_addr_frozen = [self.wallet.is_frozen_address(utxo.address) for utxo in coins] if not all(is_coin_frozen): menu.addAction(_("Freeze Coins"), lambda: self.parent.set_frozen_state_of_coins(coins, True)) if any(is_coin_frozen): menu.addAction(_("Unfreeze Coins"), lambda: self.parent.set_frozen_state_of_coins(coins, False)) if not all(is_addr_frozen): menu.addAction(_("Freeze Addresses"), lambda: self.parent.set_frozen_state_of_addresses(addrs, True)) if any(is_addr_frozen): menu.addAction(_("Unfreeze Addresses"), lambda: self.parent.set_frozen_state_of_addresses(addrs, False)) menu.exec_(self.viewport().mapToGlobal(position))
def create_menu(self, position): menu = QMenu() menu.setSeparatorsCollapsible( True) # consecutive separators are merged together selected = self.selected_in_column(self.Columns.NODE_ALIAS) if not selected: menu.addAction( _("Import channel backup"), lambda: self.parent.do_process_from_text_channel_backup()) menu.exec_(self.viewport().mapToGlobal(position)) return multi_select = len(selected) > 1 if multi_select: return idx = self.indexAt(position) if not idx.isValid(): return item = self.model().itemFromIndex(idx) if not item: return channel_id = idx.sibling(idx.row(), self.Columns.NODE_ALIAS).data(ROLE_CHANNEL_ID) if channel_id in self.lnworker.channel_backups: menu.addAction(_("Request force-close"), lambda: self.request_force_close(channel_id)) menu.addAction(_("Delete"), lambda: self.remove_channel_backup(channel_id)) menu.exec_(self.viewport().mapToGlobal(position)) return chan = self.lnworker.channels[channel_id] menu.addAction(_("Details..."), lambda: self.parent.show_channel(channel_id)) cc = self.add_copy_menu(menu, idx) cc.addAction( _("Node ID"), lambda: self.place_text_on_clipboard(chan.node_id.hex(), title=_("Node ID"))) cc.addAction( _("Long Channel ID"), lambda: self.place_text_on_clipboard(channel_id.hex(), title=_("Long Channel ID"))) if not chan.is_closed(): if not chan.is_frozen_for_sending(): menu.addAction( _("Freeze (for sending)"), lambda: self.freeze_channel_for_sending(chan, True)) else: menu.addAction( _("Unfreeze (for sending)"), lambda: self.freeze_channel_for_sending(chan, False)) if not chan.is_frozen_for_receiving(): menu.addAction(_("Freeze (for receiving)"), lambda: chan.set_frozen_for_receiving(True)) else: menu.addAction(_("Unfreeze (for receiving)"), lambda: chan.set_frozen_for_receiving(False)) funding_tx = self.parent.wallet.db.get_transaction( chan.funding_outpoint.txid) if funding_tx: menu.addAction(_("View funding transaction"), lambda: self.parent.show_transaction(funding_tx)) if not chan.is_closed(): menu.addSeparator() if chan.peer_state == PeerState.GOOD: menu.addAction(_("Close channel"), lambda: self.close_channel(channel_id)) menu.addAction(_("Force-close channel"), lambda: self.force_close(channel_id)) else: item = chan.get_closing_height() if item: txid, height, timestamp = item closing_tx = self.lnworker.lnwatcher.db.get_transaction(txid) if closing_tx: menu.addAction( _("View closing transaction"), lambda: self.parent.show_transaction(closing_tx)) menu.addSeparator() menu.addAction(_("Export backup"), lambda: self.export_channel_backup(channel_id)) if chan.is_redeemed(): menu.addSeparator() menu.addAction(_("Delete"), lambda: self.remove_channel(channel_id)) menu.exec_(self.viewport().mapToGlobal(position))
def create_menu(self, position: QPoint): org_idx: QModelIndex = self.indexAt(position) idx = self.proxy.mapToSource(org_idx) if not idx.isValid(): # can happen e.g. before list is populated for the first time return tx_item = self.hm.transactions.value_from_pos(idx.row()) column = idx.column() if column == HistoryColumns.STATUS_ICON: column_title = _('Transaction ID') column_data = tx_item['txid'] else: column_title = self.hm.headerData(column, Qt.Horizontal, Qt.DisplayRole) column_data = self.hm.data(idx, Qt.DisplayRole).value() tx_hash = tx_item['txid'] tx = self.wallet.transactions[tx_hash] tx_URL = block_explorer_URL(self.config, 'tx', tx_hash) height = self.wallet.get_tx_height(tx_hash).height is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx) is_unconfirmed = height <= 0 pr_key = self.wallet.invoices.paid.get(tx_hash) menu = QMenu() if height == TX_HEIGHT_LOCAL: menu.addAction(_("Remove"), lambda: self.remove_local_tx(tx_hash)) menu.addAction( _("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data)) for c in self.editable_columns: if self.isColumnHidden(c): continue label = self.hm.headerData(c, Qt.Horizontal, Qt.DisplayRole) # TODO use siblingAtColumn when min Qt version is >=5.11 persistent = QPersistentModelIndex( org_idx.sibling(org_idx.row(), c)) menu.addAction(_("Edit {}").format(label), lambda p=persistent: self.edit(QModelIndex(p))) menu.addAction(_("Details"), lambda: self.show_transaction(tx_hash)) if is_unconfirmed and tx: # note: the current implementation of RBF *needs* the old tx fee rbf = is_mine and not tx.is_final() and fee is not None if rbf: menu.addAction(_("Increase fee"), lambda: self.parent.bump_fee_dialog(tx)) else: child_tx = self.wallet.cpfp(tx, 0) if child_tx: menu.addAction(_("Child pays for parent"), lambda: self.parent.cpfp(tx, child_tx)) if pr_key: menu.addAction(read_QIcon("seal"), _("View invoice"), lambda: self.parent.show_invoice(pr_key)) if tx_URL: menu.addAction(_("View on block explorer"), lambda: webbrowser.open(tx_URL)) menu.exec_(self.viewport().mapToGlobal(position))
class CodeMetricsDialog(QDialog, Ui_CodeMetricsDialog): """ Class implementing a dialog to display the code metrics. """ def __init__(self, parent=None): """ Constructor @param parent parent widget (QWidget) """ super(CodeMetricsDialog, self).__init__(parent) self.setupUi(self) self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self.summaryList.headerItem().setText( self.summaryList.columnCount(), "") self.summaryList.header().resizeSection(0, 200) self.summaryList.header().resizeSection(1, 100) self.resultList.headerItem().setText(self.resultList.columnCount(), "") self.cancelled = False self.__menu = QMenu(self) self.__menu.addAction(self.tr("Collapse all"), self.__resultCollapse) self.__menu.addAction(self.tr("Expand all"), self.__resultExpand) self.resultList.setContextMenuPolicy(Qt.CustomContextMenu) self.resultList.customContextMenuRequested.connect( self.__showContextMenu) self.__fileList = [] self.__project = None self.filterFrame.setVisible(False) def __resizeResultColumns(self): """ Private method to resize the list columns. """ self.resultList.header().resizeSections(QHeaderView.ResizeToContents) self.resultList.header().setStretchLastSection(True) def __createResultItem(self, parent, values): """ Private slot to create a new item in the result list. @param parent parent of the new item (QTreeWidget or QTreeWidgetItem) @param values values to be displayed (list) @return the generated item """ itm = QTreeWidgetItem(parent) for col in range(len(values)): itm.setData(col, Qt.DisplayRole, values[col]) for col in range(1, 7): itm.setTextAlignment(col, Qt.Alignment(Qt.AlignRight)) return itm def __resizeSummaryColumns(self): """ Private method to resize the list columns. """ self.summaryList.header().resizeSections(QHeaderView.ResizeToContents) self.summaryList.header().setStretchLastSection(True) def __createSummaryItem(self, col0, col1): """ Private slot to create a new item in the summary list. @param col0 string for column 0 (string) @param col1 string for column 1 (string) """ itm = QTreeWidgetItem(self.summaryList, [col0, col1]) itm.setTextAlignment(1, Qt.Alignment(Qt.AlignRight)) def prepare(self, fileList, project): """ Public method to prepare the dialog with a list of filenames. @param fileList list of filenames (list of strings) @param project reference to the project object (Project) """ self.__fileList = fileList[:] self.__project = project self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) self.filterFrame.setVisible(True) self.__data = self.__project.getData("OTHERTOOLSPARMS", "CodeMetrics") if self.__data is None or "ExcludeFiles" not in self.__data: self.__data = {"ExcludeFiles": ""} self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) def start(self, fn): """ Public slot to start the code metrics determination. @param fn file or list of files or directory to show the code metrics for (string or list of strings) """ self.cancelled = False self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) QApplication.processEvents() loc = QLocale() if isinstance(fn, list): files = fn elif os.path.isdir(fn): files = Utilities.direntries(fn, True, '*.py', False) else: files = [fn] files.sort() # check for missing files for f in files[:]: if not os.path.exists(f): files.remove(f) self.checkProgress.setMaximum(len(files)) QApplication.processEvents() total = {} CodeMetrics.summarize(total, 'files', len(files)) progress = 0 try: # disable updates of the list for speed self.resultList.setUpdatesEnabled(False) self.resultList.setSortingEnabled(False) # now go through all the files for file in files: if self.cancelled: return stats = CodeMetrics.analyze(file, total) v = self.__getValues(loc, stats, 'TOTAL ') fitm = self.__createResultItem(self.resultList, [file] + v) identifiers = stats.identifiers for identifier in identifiers: v = self.__getValues(loc, stats, identifier) self.__createResultItem(fitm, [identifier] + v) self.resultList.expandItem(fitm) progress += 1 self.checkProgress.setValue(progress) QApplication.processEvents() finally: # reenable updates of the list self.resultList.setSortingEnabled(True) self.resultList.setUpdatesEnabled(True) self.__resizeResultColumns() # now do the summary stuff docstrings = total['lines'] - total['comments'] - \ total['empty lines'] - total['non-commentary lines'] self.__createSummaryItem(self.tr("files"), loc.toString(total['files'])) self.__createSummaryItem(self.tr("lines"), loc.toString(total['lines'])) self.__createSummaryItem(self.tr("bytes"), loc.toString(total['bytes'])) self.__createSummaryItem(self.tr("comments"), loc.toString(total['comments'])) self.__createSummaryItem(self.tr("empty lines"), loc.toString(total['empty lines'])) self.__createSummaryItem(self.tr("non-commentary lines"), loc.toString(total['non-commentary lines'])) self.__createSummaryItem(self.tr("documentation lines"), loc.toString(docstrings)) self.__resizeSummaryColumns() self.__finish() def __getValues(self, loc, stats, identifier): """ Private method to extract the code metric values. @param loc reference to the locale object (QLocale) @param stats reference to the code metric statistics object @param identifier identifier to get values for @return list of values suitable for display (list of strings) """ counters = stats.counters.get(identifier, {}) v = [] for key in ('start', 'end', 'lines', 'nloc', 'comments', 'empty'): if counters.get(key, 0): v.append(counters[key]) else: v.append('') return v def __finish(self): """ Private slot called when the action finished or the user pressed the button. """ self.cancelled = True self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) if qVersion() >= "5.0.0": self.resultList.header().setSectionResizeMode( QHeaderView.Interactive) self.summaryList.header().setSectionResizeMode( QHeaderView.Interactive) else: self.resultList.header().setResizeMode(QHeaderView.Interactive) self.summaryList.header().setResizeMode(QHeaderView.Interactive) def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. @param button button that was clicked (QAbstractButton) """ if button == self.buttonBox.button(QDialogButtonBox.Close): self.close() elif button == self.buttonBox.button(QDialogButtonBox.Cancel): self.__finish() @pyqtSlot() def on_startButton_clicked(self): """ Private slot to start a code metrics run. """ fileList = self.__fileList[:] filterString = self.excludeFilesEdit.text() if "ExcludeFiles" not in self.__data or \ filterString != self.__data["ExcludeFiles"]: self.__data["ExcludeFiles"] = filterString self.__project.setData("OTHERTOOLSPARMS", "CodeMetrics", self.__data) filterList = filterString.split(",") if filterList: for filter in filterList: fileList = [f for f in fileList if not fnmatch.fnmatch(f, filter.strip())] self.resultList.clear() self.summaryList.clear() self.start(fileList) def __showContextMenu(self, coord): """ Private slot to show the context menu of the listview. @param coord the position of the mouse pointer (QPoint) """ if self.resultList.topLevelItemCount() > 0: self.__menu.popup(self.mapToGlobal(coord)) def __resultCollapse(self): """ Private slot to collapse all entries of the resultlist. """ for index in range(self.resultList.topLevelItemCount()): self.resultList.topLevelItem(index).setExpanded(False) def __resultExpand(self): """ Private slot to expand all entries of the resultlist. """ for index in range(self.resultList.topLevelItemCount()): self.resultList.topLevelItem(index).setExpanded(True)
class Palette_Docker(DockWidget): # Init the docker def __init__(self): super(Palette_Docker, self).__init__() # make base-widget and layout widget = QWidget() layout = QVBoxLayout() buttonLayout = QHBoxLayout() widget.setLayout(layout) self.setWindowTitle(i18n("Python Palette Docker")) # Make a combobox and add palettes self.cmb_palettes = QComboBox() allPalettes = Application.resources("palette") for palette_name in allPalettes: self.cmb_palettes.addItem(palette_name) self.cmb_palettes.model().sort(0) if len(allPalettes.keys()) > 0: self.currentPalette = Palette(allPalettes[list( allPalettes.keys())[0]]) else: self.currentPalette = None self.cmb_palettes.currentTextChanged.connect(self.slot_paletteChanged) layout.addWidget(self.cmb_palettes) # add combobox to the layout self.paletteView = PaletteView() self.paletteView.setPalette(self.currentPalette) layout.addWidget(self.paletteView) self.paletteView.entrySelectedForeGround.connect( self.slot_swatchSelected) self.colorComboBox = QComboBox() self.colorList = list() buttonLayout.addWidget(self.colorComboBox) self.bnSetColor = QToolButton() self.bnSetColor.setText(i18n("Set")) self.bnSetColor.clicked.connect(self.slot_get_color_from_combobox) buttonLayout.addWidget(self.bnSetColor) self.addEntry = QAction(self) self.addEntry.setIconText(i18n("+")) self.addEntry.triggered.connect(self.slot_add_entry) self.addGroup = QAction(self) self.addGroup.triggered.connect(self.slot_add_group) self.addGroup.setText(i18n("Add Group")) self.addGroup.setIconText(str("\U0001F4C2")) self.removeEntry = QAction(self) self.removeEntry.setText(i18n("Remove Entry")) self.removeEntry.setIconText("-") self.removeEntry.triggered.connect(self.slot_remove_entry) addEntryButton = QToolButton() addEntryButton.setDefaultAction(self.addEntry) buttonLayout.addWidget(addEntryButton) addGroupButton = QToolButton() addGroupButton.setDefaultAction(self.addGroup) buttonLayout.addWidget(addGroupButton) removeEntryButton = QToolButton() removeEntryButton.setDefaultAction(self.removeEntry) buttonLayout.addWidget(removeEntryButton) # QActions self.extra = QToolButton() self.editPaletteData = QAction(self) self.editPaletteData.setText(i18n("Edit Palette Settings")) self.editPaletteData.triggered.connect(self.slot_edit_palette_data) self.extra.setDefaultAction(self.editPaletteData) buttonLayout.addWidget(self.extra) self.actionMenu = QMenu() self.exportToGimp = QAction(self) self.exportToGimp.setText(i18n("Export as GIMP Palette File")) self.exportToGimp.triggered.connect(self.slot_export_to_gimp_palette) self.exportToInkscape = QAction(self) self.exportToInkscape.setText( i18n("Export as Inkscape SVG with Swatches")) self.exportToInkscape.triggered.connect( self.slot_export_to_inkscape_svg) self.sortColors = QAction(self) self.sortColors.setText(i18n("Sort Colors")) self.sortColors.triggered.connect(self.slot_sort_colors) self.actionMenu.addAction(self.editPaletteData) self.actionMenu.addAction(self.exportToGimp) self.actionMenu.addAction(self.exportToInkscape) # self.actionMenu.addAction(self.sortColors) self.extra.setMenu(self.actionMenu) layout.addLayout(buttonLayout) self.slot_fill_combobox() self.setWidget(widget) # add widget to the docker def slot_paletteChanged(self, name): allPalettes = Application.resources("palette") if len(allPalettes) > 0 and name in allPalettes: self.currentPalette = Palette( Application.resources("palette")[name]) self.paletteView.setPalette(self.currentPalette) self.slot_fill_combobox() @pyqtSlot('KisSwatch') def slot_swatchSelected(self, entry): if (self.canvas()) is not None: if (self.canvas().view()) is not None: name = entry.name() if len(entry.id) > 0: name = entry.id() + " - " + entry.name() if len(name) > 0: if name in self.colorList: self.colorComboBox.setCurrentIndex( self.colorList.index(name)) color = self.currentPalette.colorForEntry(entry) self.canvas().view().setForeGroundColor(color) ''' A function for making a combobox with the available colors. We use QCompleter on the colorComboBox so that people can type in the name of a color to select it. This is useful for people with carefully made palettes where the colors are named properly, which makes it easier for them to find colors. ''' def slot_fill_combobox(self): if self.currentPalette is None: pass palette = self.currentPalette self.colorComboBox.clear() self.colorList = list() # for info in palette.infoList(): # entry = info.swatch # color = palette.colorForEntry(entry).colorForCanvas(self.canvas()) # colorSquare = QPixmap(12, 12) # if entry.spotColor() is True: # img = colorSquare.toImage() # circlePainter = QPainter() # img.fill(self.colorComboBox.palette().color(QPalette.Base)) # circlePainter.begin(img) # brush = QBrush(Qt.SolidPattern) # brush.setColor(color) # circlePainter.setBrush(brush) # circlePainter.pen().setWidth(0) # circlePainter.drawEllipse(0, 0, 11, 11) # circlePainter.end() # colorSquare = QPixmap.fromImage(img) # else: # colorSquare.fill(color) # name = entry.name() # if len(entry.id()) > 0: # name = entry.id() + " - " + entry.name() # self.colorList.append(name) # self.colorComboBox.addItem(QIcon(colorSquare), name) self.colorComboBox.setEditable(True) self.colorComboBox.setInsertPolicy(QComboBox.NoInsert) self.colorComboBox.completer().setCompletionMode( QCompleter.PopupCompletion) self.colorComboBox.completer().setCaseSensitivity(False) self.colorComboBox.completer().setFilterMode(Qt.MatchContains) def slot_get_color_from_combobox(self): if self.currentPalette is not None: entry = self.currentPalette.colorSetEntryByIndex( self.colorComboBox.currentIndex()) self.slot_swatchSelected(entry) def slot_add_entry(self): if (self.canvas()) is not None: if (self.canvas().view()) is not None: color = self.canvas().view().foregroundColor() success = self.paletteView.addEntryWithDialog(color) if success is True: self.slot_fill_combobox() def slot_add_group(self): success = self.paletteView.addGroupWithDialog() if success is True: self.slot_fill_combobox() def slot_remove_entry(self): success = self.paletteView.removeSelectedEntryWithDialog() if success is True: self.slot_fill_combobox() ''' A function for giving a gui to edit palette metadata... I also want this to be the way to edit the settings of the palette docker. ''' def slot_edit_palette_data(self): dialog = QDialog(self) tabWidget = QTabWidget() dialog.setWindowTitle(i18n("Edit Palette Data")) dialog.setLayout(QVBoxLayout()) dialog.layout().addWidget(tabWidget) paletteWidget = QWidget() paletteWidget.setLayout(QVBoxLayout()) tabWidget.addTab(paletteWidget, i18n("Palette Data")) paletteName = QLineEdit() paletteName.setText(self.cmb_palettes.currentText()) paletteWidget.layout().addWidget(paletteName) paletteColumns = QSpinBox() paletteColumns.setValue(self.currentPalette.columnCount()) paletteWidget.layout().addWidget(paletteColumns) paletteComment = QPlainTextEdit() paletteComment.appendPlainText(self.currentPalette.comment()) paletteWidget.layout().addWidget(paletteComment) buttons = QDialogButtonBox(QDialogButtonBox.Ok) dialog.layout().addWidget(buttons) buttons.accepted.connect(dialog.accept) # buttons.rejected.connect(dialog.reject()) if dialog.exec_() == QDialog.Accepted: Resource = Application.resources("palette")[ self.cmb_palettes.currentText()] Resource.setName(paletteName.text()) self.currentPalette = Palette(Resource) self.currentPalette.setColumnCount(paletteColumns.value()) self.paletteView.setPalette(self.currentPalette) self.slot_fill_combobox() self.currentPalette.setComment(paletteComment.toPlainText()) self.currentPalette.save() def slot_export_to_gimp_palette(self): palette_exporter_gimppalette.gimpPaletteExporter( self.cmb_palettes.currentText()) def slot_export_to_inkscape_svg(self): palette_exporter_inkscapeSVG.inkscapeSVGExporter( self.cmb_palettes.currentText()) def slot_sort_colors(self): colorSorter = palette_sortColors.sortColors( self.cmb_palettes.currentText()) self.paletteView.setPalette(colorSorter.palette()) def canvasChanged(self, canvas): self.cmb_palettes.clear() allPalettes = Application.resources("palette") for palette_name in allPalettes: self.cmb_palettes.addItem(palette_name) self.cmb_palettes.model().sort(0) if self.currentPalette == None and len(allPalettes.keys()) > 0: self.currentPalette = Palette(allPalettes[list( allPalettes.keys())[0]])
def _on_contextmenu(self, pos): """ ContextMenu """ index = self.indexAt(pos).row() glbl_pt = self.mapToGlobal(pos) context_menu = QMenu(self) if index != -1: mem_prot = self._ranges_model.item(index, 2).text() # is readable if 'r' in mem_prot: context_menu.addAction( 'Dump Binary', lambda: self._on_dumprange( self._ranges_model.item(index, 0).text(), self._ranges_model.item(index, 1).text())) context_menu.addSeparator() context_menu.addAction( 'Add Watcher', lambda: self._on_addwatcher( self._ranges_model.item(index, 0).text())) context_menu.addAction( 'Copy address', lambda: utils.copy_hex_to_clipboard( self._ranges_model.item(index, 0).text())) context_menu.addSeparator() if self._ranges_model.item(index, 5): file_path = self._ranges_model.item(index, 5).text() if file_path: context_menu.addAction( 'Copy Path', lambda: utils.copy_str_to_clipboard(file_path)) context_menu.addSeparator() if self._app_window.dwarf._platform == 'linux': context_menu.addAction( 'Show ELF Info', lambda: self._on_parse_elf(file_path)) context_menu.addSeparator() if self.search_enabled: context_menu.addSeparator() context_menu.addAction('Search', self._on_cm_search) context_menu.addSeparator() context_menu.addAction('Refresh', self.update_ranges) context_menu.exec_(glbl_pt)
def descrittivo_finestraMain(self): """questa è la doc string della funzione, richiamabile con nomemodulo.nomefunzione.__doc__ Qui definisco come è fatta la finestra principale""" # creo una statusbar (nella mainwindow in basso) che mostra la scritta "Caricamento completato..." self.statusBar().showMessage("Caricamento completato - Ver.0.1.180714") # creo una barra dei menu (in alto nella mainwindow) barraMenu = self.menuBar() # aggiungo alla barra dei menu creata sopra la prima voce: "File" fileMenu = barraMenu.addMenu("&File") # alla voce File creata sopra aggiungo una sotto voce "Nuovo". # queste sottovoci vengono chiamate QAction (azioni della barra del menu). Azione_Nuovo = QAction("Indirizzo", self) fileMenu.addAction( Azione_Nuovo ) #aggiungo alla barra dei menu creata prima l'azione appena creta # ora voglio aggiungere una voce che sia un "sotto menu". # Quindi creo prima di tutto un QMenu serverString_subMenu = QMenu("Stringa Server", self) # creo un'azione che andrò poi a legare stavolta al sottomenu importAct = QAction("Import mail", self) # aggiungo l'azione creata sopra al sottomenu serverString_subMenu.addAction(importAct) # aggiungo il sottomenu al menu principale creato prima. fileMenu.addMenu(serverString_subMenu) # creo anche la voce (azione) esci e la aggiungo nel sottomenu esciAct = QAction( QIcon("exit.png"), "&Esci", self ) #NB alla voce esci ho associato anche un'icona (png presente nella cartella) esciAct.setShortcut("Ctrl+Q") esciAct.setStatusTip("Exit Application") fileMenu.addAction( esciAct ) #NB l'ordine in cui vengono aggiunti gli oggetti nel menu è poi l'ordine delle voci # ora definisco cosa fanno le voci (azioni) nella barra dei menu Azione_Nuovo.triggered.connect(self.on_click5) esciAct.triggered.connect(qApp.quit) # **** parametri della finestra **** left = 300 top = 300 width = 300 height = 300 self.setWindowTitle("Test a caso") self.setGeometry(left, top, width, height) #pulsante esercizio 1 self.button = QPushButton("Esercizio 1", self) self.button.move(20, 40) self.button.clicked.connect(self.on_click) #pulsante esercizio 2 self.button2 = QPushButton("Esercizio 2", self) self.button2.move(20, 80) self.button2.clicked.connect(self.on_click2) #pulsante esercizio 3 self.button3 = QPushButton("Esercizio 3", self) self.button3.move(20, 120) self.button3.clicked.connect(self.on_click3) #pulsante cambio finestra self.button4 = QPushButton("Opzioni", self) self.button4.move(20, 160) self.button4.clicked.connect(self.on_click4) self.serverstring = QLineEdit(self) self.serverstring.move(20, 200) self.serverstring.text = self.stringaServer
def create_menu(self, position): wallet = self.parent.wallet items = self.selected_in_column(0) if len(items) > 1: keys = [item.data(ROLE_REQUEST_ID) for item in items] invoices = [wallet.invoices.get(key) for key in keys] can_batch_pay = all([ i.type == PR_TYPE_ONCHAIN and wallet.get_invoice_status(i) == PR_UNPAID for i in invoices ]) menu = QMenu(self) if can_batch_pay: menu.addAction( _("Batch pay invoices") + "...", lambda: self.parent.pay_multiple_invoices(invoices)) menu.addAction(_("Delete invoices"), lambda: self.parent.delete_invoices(keys)) menu.exec_(self.viewport().mapToGlobal(position)) return idx = self.indexAt(position) item = self.item_from_index(idx) item_col0 = self.item_from_index( idx.sibling(idx.row(), self.Columns.DATE)) if not item or not item_col0: return key = item_col0.data(ROLE_REQUEST_ID) invoice = self.parent.wallet.get_invoice(key) menu = QMenu(self) self.add_copy_menu(menu, idx) if invoice.is_lightning(): menu.addAction(_("Details"), lambda: self.parent.show_lightning_invoice(invoice)) else: if len(invoice.outputs) == 1: menu.addAction( _("Copy Address"), lambda: self.parent.do_copy(invoice.get_address(), title='Bitcoin Address')) menu.addAction(_("Details"), lambda: self.parent.show_onchain_invoice(invoice)) status = wallet.get_invoice_status(invoice) if status == PR_UNPAID: menu.addAction( _("Pay") + "...", lambda: self.parent.do_pay_invoice(invoice)) if status == PR_FAILED: menu.addAction(_("Retry"), lambda: self.parent.do_pay_invoice(invoice)) if self.parent.wallet.lnworker: log = self.parent.wallet.lnworker.logs.get(key) if log: menu.addAction(_("View log"), lambda: self.show_log(key, log)) menu.addAction(_("Delete"), lambda: self.parent.delete_invoices([key])) menu.exec_(self.viewport().mapToGlobal(position))
def myContextMenu(self, pos): menu = QMenu(self) menu.addAction('&+', self.addSticker, 'Ctrl+T') menu.addAction('&background color', self.backgroundColorDialog, 'Ctrl+B') menu.addAction('text colo&r', self.textColorDialog, 'Ctrl+R') menu.addAction('text f&ormat', self.fontDialog, 'Ctrl+O') menu.addAction('&save', self.save, 'Ctrl+S') menu.addAction('&load', self.load, 'Ctrl+L') menu.addAction('&close', self.close, 'Ctrl+W') menu.addAction('&quit', qApp.myQuit, 'Ctrl+Q') menu.addAction('reo&pen last closed', self.loadLastClosed, 'Shift+Ctrl+T') menu.exec_(self.mapToGlobal(pos))
class Gala(QWidget): """ Main window that holds the main layout """ MAX_TIME = 604800 # self.maxTime == Monday 12:00 am or 0 seconds def __init__(self, parent=None): super().__init__() self.threads = [] self.ignoreQuit = True self.columnWidth = 100 self.numRow = 20 self.numColumn = 2 self.validDate = ["mon", "tues", "wed", "thurs", "fri", "sat", "sun"] self.AM = "am" self.PM = "pm" self.data_path = os.path.abspath("UserData/GalaData.json") self.icon_path = os.path.abspath("Icon/orange.png") self.trayMenu = QMenu(self) self.trayMenu.addAction("Open", self.open_) self.trayMenu.addAction("Hide", self.hide) self.trayMenu.addAction("Quit", self.quit) self.tray = QSystemTrayIcon(QIcon(self.icon_path), self) self.tray.setContextMenu(self.trayMenu) self.tray.activated.connect(self.onClickEvent) self.tray.show() self.firstHeader = "Time" self.secondHeader = "Description" self.table = QTableWidget(self) self.table.setRowCount(self.numRow) self.table.setColumnCount(self.numColumn) self.table.setHorizontalHeaderLabels( [self.firstHeader, self.secondHeader]) #self.table.setColumnWidth(0, self.columnWidth) #self.table.setColumnWidth(1, self.columnWidth) self.tableScrollW = self.table.verticalScrollBar().sizeHint().width() self.tableHeaderW = self.table.horizontalHeader().length() self.tableVertHeaderW = self.table.verticalHeader().width() self.tableFrameW = self.table.frameWidth() * 2 self.tableWidth = (self.tableScrollW + self.tableHeaderW + self.tableFrameW) self.table.setFixedWidth(self.tableWidth) self.table.verticalHeader().hide() self.header = self.table.horizontalHeader() self.header.setSectionResizeMode(0, QHeaderView.Interactive) self.header.setSectionResizeMode(1, QHeaderView.Stretch) self.headerMidPoint = self.header.length() / 2 self.header.setMinimumSectionSize(self.headerMidPoint * 0.10) self.header.setMaximumSectionSize(self.headerMidPoint * 1.90) self.saveButton = self.createButton("Save", self.saveButtonClick) self.galaButton = self.createButton("Gala", self.galaButtonClick) self.loadButton = self.createButton("Load", self.loadButtonClick) self.infoButton = self.createButton("Info", self.infoButtonClick) # self.checkButton = self.createButton("Check", self.checkButtonClick) self.clearButton = self.createButton("Clear", self.clearButtonClick) layout = QGridLayout(self) layout.addWidget(self.table, 0, 0, 1, 6) layout.addWidget(self.loadButton, 1, 0) layout.addWidget(self.saveButton, 1, 1) layout.addWidget(self.clearButton, 1, 2) # layout.addWidget(self.checkButton, 1, 3) layout.addWidget(self.infoButton, 1, 4) layout.addWidget(self.galaButton, 1, 5) # only vertical resize allowed #layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.autoLoad() # load user data height = self.table.verticalHeader().width() * 20 width = self.sizeHint().width() self.resize(width, height) self.setWindowIcon(QIcon(self.icon_path)) self.setFixedWidth(width) self.setWindowTitle("Gala") def autoLoad(self): self.load() def createButton(self, text, func): btn = QToolButton() btn.setText(text) btn.clicked.connect(func) return btn def onClickEvent(self, event): self.open_() def closeEvent(self, closeEvent): if self.ignoreQuit: closeEvent.ignore() self.hide() else: QCoreApplication.exit() def hideEvent(self, hideEvent): self.hide() def galaButtonClick(self): if self.validTimes(msgHint="Failed to start.") == True: for i in range(0, len(self.threads)): self.threads[i].stop() self.hide() now = Gala.timeNow() minTime = None num = None for row in range(0, self.numRow): txt = self.table.item(row, 0).text() if txt == "": continue end = Gala.parseTime(txt) end = Gala.normalizeTime(end[0], end[1], end[2]) if end < now: deltaTime = Gala.MAX_TIME - abs(end - now) else: deltaTime = end - now if minTime is None or deltaTime < minTime: minTime = deltaTime num = row galaThread = GalaThread( self.table.item(num, 0).text(), self.table.item(num, 1).text()) galaThread.signal.connect(self.delivMsg) galaThread.start() self.threads.append(galaThread) def saveButtonClick(self): self.setFocus() if self.validTimes(msgHint="Failed to save.") == True: os.makedirs("UserData", exist_ok=True) with open(self.data_path, 'w') as f: data = self.convertTableToJson() f.write(data) f.close() def loadButtonClick(self): self.load() def infoButtonClick(self): ex = GalaPopup( "Examples", "Tues 1:00 pm | Fri 3:00 pm | Sat 8:30 am\n\n" "Valid days\n" "Mon | Tues | Wed | Thurs | Fri | Sat | Sun\n\n" "Valid times\n" "12:00 am ... 11:59 pm") ex.setWindowTitle("Info") ex.exec_() def checkButtonClick(self): pass def clearButtonClick(self): self.clearTable() def load(self): self.loadJsonToTable(self.data_path) def open_(self): self.setVisible(True) self.raise_() def quit(self): self.ignoreQuit = False self.close() def hide(self): self.setVisible(False) @staticmethod def timeNow(): now = datetime.datetime.now() nowTime = Gala.normalizeTime(now.weekday(), now.hour, now.minute) return nowTime @staticmethod def parseTime(text): text = text.split() weekday = text[0].lower() weekday = Weekday[weekday].value time = text[1].split(':') hour = int(time[0]) min_ = int(time[1]) amPM = text[2].lower() if amPM == "pm" and hour in range(1, 12): hour += 12 elif hour is 12 and amPM is "am": hour -= 12 return [weekday, hour, min_] @staticmethod def normalizeTime(day, hour, min_): """ days = [Mon...Sun] = [0...6] hours = [0...24] minutes = [0...60] Normalize to/with Monday 00:00 (12:00 am) as 0 or self.maxNorm in seconds. Example: Thursday 14:00 (2:00 pm) = 396,000 seconds from 0 """ day = day * 24 * 60 * 60 hour = hour * 60 * 60 min_ = min_ * 60 normTime = day + hour + min_ return normTime def delivMsg(self, timeMsg, msg): msgBox = GalaPopup("Gala delivery", timeMsg, msg) msgBox.exec_() def errTimeMsg(self, row, msgHint=""): errMsg = self.table.item(row, 0).text() err = GalaPopup( msgHint, "Invalid time at row " + str(row + 1) + ":\n\n" + errMsg) err.setWindowTitle("Invalid time") err.exec_() def validTimes(self, msgHint=""): """ Validate time Assume (or enforce) time format as "DATE TIME AM/PM". Example (from string to an array): ["Tues", "11:00", "am"] """ # TODO More strict time check. i.e right now Tues 0:00 pm is okay... # maybe more checks or simplify some steps? for row in range(0, self.numRow): galaTime = self.table.item(row, 0) if galaTime is None or galaTime.text() is "": continue galaTime = galaTime.text().split() if len(galaTime) != 3: self.errTimeMsg(row, msgHint) return False date = galaTime[0] time = galaTime[1] am_pm = galaTime[2] if self.isDate(date) and self.isTime(time) and self.isAmPm(am_pm): continue else: self.errTimeMsg(row, msgHint) return False return True def isDate(self, date): date = date.lower() if date in self.validDate: return True return False def isTime(self, time): time = time.split(':') if len(time) != 2: return False hour = int(time[0]) minute = int(time[1]) hourRange = lambda: range(1, 13) minuteRange = lambda: range(0, 61) if hour in hourRange() and minute in minuteRange(): return True else: return False def isAmPm(self, am_pm): if am_pm.lower() == self.AM or am_pm.lower() == self.PM: return True else: return False def clearTable(self): for row in range(0, self.numRow): for col in range(0, self.numColumn): g = QTableWidgetItem("") self.table.setItem(row, col, g) def convertTableToJson(self): items = [] for row in range(0, self.numRow): item = {} item["row"] = row for col in range(0, self.numColumn): tableItem = self.table.item(row, col) if tableItem is None: text = None else: text = tableItem.text() if col == 0: item["time"] = text elif col == 1: item["description"] = text items.append(item) galaItems = {"gala_items": items} jsonString = json.dumps(galaItems, indent=4) return jsonString def loadJsonToTable(self, path): if not os.path.isfile(path): return 0 galaData = open(path).read() galaData = json.loads(galaData) for i in range(0, len(galaData["gala_items"])): row = galaData["gala_items"][i]["row"] time = galaData["gala_items"][i]["time"] info = galaData["gala_items"][i]["description"] self.table.setItem(row, 0, QTableWidgetItem(time)) self.table.setItem(row, 1, QTableWidgetItem(info)) def convertTableToDict(self): jobArr = [] for row in range(0, self.numRow): newJob = {} for col in range(0, self.numColumn): if col == 1: newJob["time"] = self.table.item(row, col) elif col == 2: newJob["description"] = self.table.item(row, col) jobArr.append(newJob) return jobArr