def _on_view_context_menu(self, pos): widget = self.scene.widget if widget is None: return assert isinstance(widget, HeatmapGridWidget) menu = QMenu(self.view.viewport()) menu.setAttribute(Qt.WA_DeleteOnClose) menu.addActions(self.view.actions()) menu.addSeparator() menu.addActions([self.__font_inc, self.__font_dec]) menu.addSeparator() a = QAction("Keep aspect ratio", menu, checkable=True) a.setChecked(self.keep_aspect) def ontoggled(state): self.keep_aspect = state self.__aspect_mode_changed() a.toggled.connect(ontoggled) menu.addAction(a) menu.popup(self.view.viewport().mapToGlobal(pos))
def __init__(self): super().__init__() self.data = None self.editors = {} box = gui.vBox(self.controlArea, "Variable Definitions") toplayout = QHBoxLayout() toplayout.setContentsMargins(0, 0, 0, 0) box.layout().addLayout(toplayout) self.editorstack = QStackedWidget( sizePolicy=QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) ) for descclass, editorclass in self.EDITORS: editor = editorclass() editor.featureChanged.connect(self._on_modified) self.editors[descclass] = editor self.editorstack.addWidget(editor) self.editorstack.setEnabled(False) buttonlayout = QVBoxLayout(spacing=10) buttonlayout.setContentsMargins(0, 0, 0, 0) self.addbutton = QPushButton( "New", toolTip="Create a new variable", minimumWidth=120, shortcut=QKeySequence.New ) def unique_name(fmt, reserved): candidates = (fmt.format(i) for i in count(1)) return next(c for c in candidates if c not in reserved) def reserved_names(): varnames = [] if self.data is not None: varnames = [var.name for var in self.data.domain.variables + self.data.domain.metas] varnames += [desc.name for desc in self.featuremodel] return set(varnames) def generate_newname(fmt): return unique_name(fmt, reserved_names()) menu = QMenu(self.addbutton) cont = menu.addAction("Continuous") cont.triggered.connect( lambda: self.addFeature( ContinuousDescriptor(generate_newname("X{}"), "", 3)) ) disc = menu.addAction("Discrete") disc.triggered.connect( lambda: self.addFeature( DiscreteDescriptor(generate_newname("D{}"), "", ("A", "B"), -1, False)) ) string = menu.addAction("String") string.triggered.connect( lambda: self.addFeature( StringDescriptor(generate_newname("S{}"), "")) ) menu.addSeparator() self.duplicateaction = menu.addAction("Duplicate Selected Variable") self.duplicateaction.triggered.connect(self.duplicateFeature) self.duplicateaction.setEnabled(False) self.addbutton.setMenu(menu) self.removebutton = QPushButton( "Remove", toolTip="Remove selected variable", minimumWidth=120, shortcut=QKeySequence.Delete ) self.removebutton.clicked.connect(self.removeSelectedFeature) buttonlayout.addWidget(self.addbutton) buttonlayout.addWidget(self.removebutton) buttonlayout.addStretch(10) toplayout.addLayout(buttonlayout, 0) toplayout.addWidget(self.editorstack, 10) # Layout for the list view layout = QVBoxLayout(spacing=1, margin=0) self.featuremodel = DescriptorModel(parent=self) self.featureview = QListView( minimumWidth=200, sizePolicy=QSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) ) self.featureview.setItemDelegate(FeatureItemDelegate(self)) self.featureview.setModel(self.featuremodel) self.featureview.selectionModel().selectionChanged.connect( self._on_selectedVariableChanged ) layout.addWidget(self.featureview) box.layout().addLayout(layout, 1) box = gui.hBox(self.controlArea) box.layout().addWidget(self.report_button) self.report_button.setMinimumWidth(180) gui.rubber(box) commit = gui.button(box, self, "Send", callback=self.apply, default=True) commit.setMinimumWidth(180)
def __init__(self): super().__init__() self.data = None self.editors = {} box = gui.vBox(self.controlArea, "Variable Definitions") toplayout = QHBoxLayout() toplayout.setContentsMargins(0, 0, 0, 0) box.layout().addLayout(toplayout) self.editorstack = QStackedWidget( sizePolicy=QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) ) for descclass, editorclass in self.EDITORS: editor = editorclass() editor.featureChanged.connect(self._on_modified) self.editors[descclass] = editor self.editorstack.addWidget(editor) self.editorstack.setEnabled(False) buttonlayout = QVBoxLayout(spacing=10) buttonlayout.setContentsMargins(0, 0, 0, 0) self.addbutton = QPushButton( "New", toolTip="Create a new variable", minimumWidth=120, shortcut=QKeySequence.New ) def unique_name(fmt, reserved): candidates = (fmt.format(i) for i in count(1)) return next(c for c in candidates if c not in reserved) def reserved_names(): varnames = [] if self.data is not None: varnames = [var.name for var in self.data.domain.variables + self.data.domain.metas] varnames += [desc.name for desc in self.featuremodel] return set(varnames) def generate_newname(fmt): return unique_name(fmt, reserved_names()) menu = QMenu(self.addbutton) cont = menu.addAction("Numeric") cont.triggered.connect( lambda: self.addFeature( ContinuousDescriptor(generate_newname("X{}"), "", 3)) ) disc = menu.addAction("Categorical") disc.triggered.connect( lambda: self.addFeature( DiscreteDescriptor(generate_newname("D{}"), "", ("A", "B"), -1, False)) ) string = menu.addAction("Text") string.triggered.connect( lambda: self.addFeature( StringDescriptor(generate_newname("S{}"), "")) ) menu.addSeparator() self.duplicateaction = menu.addAction("Duplicate Selected Variable") self.duplicateaction.triggered.connect(self.duplicateFeature) self.duplicateaction.setEnabled(False) self.addbutton.setMenu(menu) self.removebutton = QPushButton( "Remove", toolTip="Remove selected variable", minimumWidth=120, shortcut=QKeySequence.Delete ) self.removebutton.clicked.connect(self.removeSelectedFeature) buttonlayout.addWidget(self.addbutton) buttonlayout.addWidget(self.removebutton) buttonlayout.addStretch(10) toplayout.addLayout(buttonlayout, 0) toplayout.addWidget(self.editorstack, 10) # Layout for the list view layout = QVBoxLayout(spacing=1, margin=0) self.featuremodel = DescriptorModel(parent=self) self.featureview = QListView( minimumWidth=200, sizePolicy=QSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) ) self.featureview.setItemDelegate(FeatureItemDelegate(self)) self.featureview.setModel(self.featuremodel) self.featureview.selectionModel().selectionChanged.connect( self._on_selectedVariableChanged ) layout.addWidget(self.featureview) box.layout().addLayout(layout, 1) box = gui.hBox(self.controlArea) gui.rubber(box) commit = gui.button(box, self, "Send", callback=self.apply, default=True) commit.setMinimumWidth(180)
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowIcon(QIcon(':/res/box.png')) self._tray = QSystemTrayIcon() self._tray.setIcon(QIcon(':/res/box.png')) self._tray.activated.connect(self.show_tray_menu) self._tray.show() self._menu = None self._action_screen = None self._action_clip = None self._screenshot_wnd = None self.rebuild_menu() self._hotkey = hotkeys.initialize() if not settings['initialized']: settings['initialized'] = True settings['hotkey/screenshot'] = 'Print' settings['hotkey/clipboard'] = 'Ctrl+Alt+P' settings.save() self.register_hotkeys() def rebuild_menu(self): # Terrible way to clear hotkey shortcuts set to actions because Qt can not do that. self._menu = QMenu() self._action_screen = self._menu.addAction(self.tr('Make Screenshot')) self._action_screen.triggered.connect(self.capture_screen) self._action_clip = self._menu.addAction(self.tr('Share Clipboard')) self._action_clip.triggered.connect(self.share_clipboard) self._menu.addSeparator() self._menu.addAction(self.tr('Settings')).triggered.connect(self.show_settings) self._menu.addSeparator() self._menu.addAction(self.tr('Exit')).triggered.connect(lambda: QApplication.exit(0)) self._tray.setContextMenu(self._menu) def __del__(self): hotkey = getattr(self, '_hotkey', None) if hotkey: hotkey.destroy() def show_tray_menu(self): self._menu.popup(QCursor.pos()) def capture_screen(self): if self._screenshot_wnd: return self._screenshot_wnd = wnd = Screenshot() result = wnd.exec_() self._screenshot_wnd = None if result == QDialog.Accepted: wnd = ShareDialog(self, image=wnd.selected_image) wnd.show() wnd.exec_() def share_clipboard(self): mime = QApplication.clipboard().mimeData() try: wnd = ShareDialog(self, mime=mime) except ValueError as e: QMessageBox.critical(self, self.tr('Error'), str(e)) return else: wnd.show() wnd.exec_() def register_hotkeys(self): if self._hotkey is not None: self.rebuild_menu() self._hotkey.unregister(winid=self.winId()) hotkey_bindings = { settings['hotkey/clipboard']: (self.share_clipboard, self._action_clip), settings['hotkey/screenshot']: (self.capture_screen, self._action_screen) } for hotkey, (callback, action) in hotkey_bindings.items(): if hotkey: if self._hotkey.register(hotkey, callback, self.winId()): sequence = QKeySequence(hotkey) if hotkey else QKeySequence() action.setShortcut(sequence) else: QMessageBox.critical(self, 'Error', 'Could not bind {} hotkey!\n' 'Key combination {} is probably already in use.' .format(const.APP_NAME, hotkey)) else: qDebug('Hotkeys are not supported on this platform') def show_settings(self): self._hotkey.unregister(winid=self.winId()) dlg = SettingsDialog(self) dlg.show() dlg.exec_() # WORKAROUND: On windows calling register_hotkeys() directly often results in a crash. QTimer.singleShot(10, self.register_hotkeys)
def __init__(self): super().__init__() self.data = None self.editors = {} box = gui.vBox(self.controlArea, "变量定义") toplayout = QHBoxLayout() toplayout.setContentsMargins(0, 0, 0, 0) box.layout().addLayout(toplayout) self.editorstack = QStackedWidget(sizePolicy=QSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) for descclass, editorclass in self.EDITORS: editor = editorclass() editor.featureChanged.connect(self._on_modified) self.editors[descclass] = editor self.editorstack.addWidget(editor) self.editorstack.setEnabled(False) buttonlayout = QVBoxLayout(spacing=10) buttonlayout.setContentsMargins(0, 0, 0, 0) self.addbutton = QPushButton("新建", toolTip="Create a new variable", minimumWidth=120, shortcut=QKeySequence.New) def unique_name(fmt, reserved): candidates = (fmt.format(i) for i in count(1)) return next(c for c in candidates if c not in reserved) def generate_newname(fmt): return unique_name(fmt, self.reserved_names()) menu = QMenu(self.addbutton) cont = menu.addAction("数值数据") cont.triggered.connect(lambda: self.addFeature( ContinuousDescriptor(generate_newname("X{}"), "", 3))) disc = menu.addAction("分类数据") disc.triggered.connect(lambda: self.addFeature( DiscreteDescriptor(generate_newname("D{}"), "", (), False))) string = menu.addAction("文本") string.triggered.connect(lambda: self.addFeature( StringDescriptor(generate_newname("S{}"), ""))) datetime = menu.addAction("日期/时间") datetime.triggered.connect(lambda: self.addFeature( DateTimeDescriptor(generate_newname("T{}"), ""))) menu.addSeparator() self.duplicateaction = menu.addAction("复制选中变量") self.duplicateaction.triggered.connect(self.duplicateFeature) self.duplicateaction.setEnabled(False) self.addbutton.setMenu(menu) self.removebutton = QPushButton("删除", toolTip="删除选中变量", minimumWidth=120, shortcut=QKeySequence.Delete) self.removebutton.clicked.connect(self.removeSelectedFeature) buttonlayout.addWidget(self.addbutton) buttonlayout.addWidget(self.removebutton) buttonlayout.addStretch(10) toplayout.addLayout(buttonlayout, 0) toplayout.addWidget(self.editorstack, 10) # Layout for the list view layout = QVBoxLayout(spacing=1, margin=0) self.featuremodel = DescriptorModel(parent=self) self.featureview = QListView(minimumWidth=200, minimumHeight=50, sizePolicy=QSizePolicy( QSizePolicy.Minimum, QSizePolicy.MinimumExpanding)) self.featureview.setItemDelegate(FeatureItemDelegate(self)) self.featureview.setModel(self.featuremodel) self.featureview.selectionModel().selectionChanged.connect( self._on_selectedVariableChanged) layout.addWidget(self.featureview) box.layout().addLayout(layout, 1) self.fix_button = gui.button(self.buttonsArea, self, "Upgrade Expressions", callback=self.fix_expressions) self.fix_button.setHidden(True) gui.button(self.buttonsArea, self, "Send", callback=self.apply, default=True)
def createStandardContextMenu(item: QGraphicsTextItem, pos: QPointF, parent: Optional[QWidget] = None, acceptRichText=False) -> Optional[QMenu]: """ Like the private QWidgetTextControl::createStandardContextMenu """ def setActionIcon(action: QAction, name: str): icon = QIcon.fromTheme(name) if not icon.isNull(): action.setIcon(icon) def createMimeDataFromSelection( fragment: QTextDocumentFragment) -> QMimeData: mime = QMimeData() mime.setText(fragment.toPlainText()) mime.setHtml(fragment.toHtml(b"utf-8")) # missing here is odf return mime def copy(): cursor = item.textCursor() if cursor.hasSelection(): mime = createMimeDataFromSelection(QTextDocumentFragment(cursor)) QApplication.clipboard().setMimeData(mime) def cut(): copy() item.textCursor().removeSelectedText() def copyLinkLocation(): mime = QMimeData() mime.setText(link) QApplication.clipboard().setMimeData(mime) def canPaste(): mime = QApplication.clipboard().mimeData() return mime.hasFormat("text/plain") or mime.hasFormat("text/html") def paste(): mime = QApplication.clipboard().mimeData() if mime is not None: insertFromMimeData(mime) def insertFromMimeData(mime: QMimeData): fragment: Optional[QTextDocumentFragment] = None if mime.hasHtml() and acceptRichText: fragment = QTextDocumentFragment.fromHtml(mime.html()) elif mime.hasText(): fragment = QTextDocumentFragment.fromPlainText(mime.text()) if fragment is not None: item.textCursor().insertFragment(fragment) def deleteSelected(): cursor = item.textCursor() cursor.removeSelectedText() def selectAll(): cursor = item.textCursor() cursor.select(QTextCursor.Document) item.setTextCursor(cursor) def addAction(menu: QMenu, text: str, slot: Callable[[], Any], shortcut: Optional[QKeySequence.StandardKey] = None, enabled=True, objectName="", icon="") -> QAction: ac = menu.addAction(text) ac.triggered.connect(slot) ac.setEnabled(enabled) if shortcut: ac.setShortcut(shortcut) if objectName: ac.setObjectName(objectName) if icon: setActionIcon(ac, icon) return ac flags = item.textInteractionFlags() showTextSelectionActions = flags & (Qt.TextEditable | Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse) doc = item.document() cursor = item.textCursor() assert doc is not None layout = doc.documentLayout() link = layout.anchorAt(pos) if not link and not showTextSelectionActions: return None menu = QMenu(parent) menu.setAttribute(Qt.WA_DeleteOnClose) if flags & Qt.TextEditable: addAction( menu, "&Undo", doc.undo, shortcut=QKeySequence.Undo, enabled=doc.isUndoAvailable(), objectName="edit-undo", icon="edit-undo", ) addAction( menu, "&Redo", doc.redo, shortcut=QKeySequence.Redo, enabled=doc.isRedoAvailable(), objectName="edit-redo", icon="edit-redo", ) menu.addSeparator() addAction( menu, "Cu&t", cut, shortcut=QKeySequence.Cut, enabled=cursor.hasSelection(), objectName="edit-cut", icon="edit-cut", ) if showTextSelectionActions: addAction(menu, "&Copy", copy, shortcut=QKeySequence.Copy, enabled=cursor.hasSelection(), objectName="edit-copy", icon="edit-copy") if flags & (Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard): addAction( menu, "Copy &Link Location", copyLinkLocation, enabled=bool(link), objectName="link-copy", ) if flags & Qt.TextEditable: addAction( menu, "&Paste", paste, shortcut=QKeySequence.Paste, enabled=canPaste(), objectName="edit-paste", icon="edit-paste", ) addAction( menu, "Delete", deleteSelected, enabled=cursor.hasSelection(), objectName="edit-delete", icon="edit-delete", ) if showTextSelectionActions: addAction( menu, "Select All", selectAll, shortcut=QKeySequence.SelectAll, enabled=not doc.isEmpty(), objectName="select-all", ) return menu