def createButton(self, button, propertyDict = dict()): """ Creates the buttons according to the user size definition button: Button name propertyDict: optional dict parameters that may contain other properties to button, such as color, tooltip and custom category """ pushButton = QtGui.QPushButton(button) keys = propertyDict.keys() styleSheet = '' if 'buttonColor' in keys: r, g, b, a = propertyDict['buttonColor'].split(',') styleSheet += "background-color:rgba({0},{1},{2},{3});".format(r, g, b, a) if 'buttonToolTip' in keys: pushButton.setToolTip(propertyDict['buttonToolTip']) if 'buttonShortcut' in keys: keySequence = QKeySequence(propertyDict['buttonShortcut']) pushButton.setText('{0} [{1}]'.format(button, keySequence.toString(format = QKeySequence.NativeText))) pushButton.setShortcut(keySequence) pushButton.clicked.connect(self.reclassify) pushButton.toggled.connect(self.acquire) if self.size == 0: pushButton.setMinimumSize(100, 25) styleSheet += 'font-size:12px;' elif self.size == 1: pushButton.setMinimumSize(100, 40) styleSheet += 'font-size:20px;' elif self.size == 2: pushButton.setMinimumSize(100, 80) styleSheet += 'font-size:30px;' pushButton.setStyleSheet(styleSheet) self.buttons.append(pushButton) return pushButton
def change_keyseq(self, group, name, old_keyseq, keyseq): """ Customize a shortcut's activating key sequence. """ if old_keyseq: old_keyseq = QKeySequence(old_keyseq) old_keytext = str(old_keyseq.toString()) self._keyseq_target_actions[old_keytext].remove( (group, name) ) try: keyseq = QKeySequence(keyseq) keytext = str(keyseq.toString()) target_name_set = self._keyseq_target_actions[keytext] except KeyError: target_name_set = self._keyseq_target_actions[keytext] = set() self._add_global_shortcut_listener( keyseq ) target_name_set.add( (group, name) ) self._update_tooltip( group, name, keyseq )
def change_keyseq(self, group, name, old_keyseq, keyseq): """ Customize a shortcut's activating key sequence. """ if old_keyseq: old_keyseq = QKeySequence(old_keyseq) old_keytext = str(old_keyseq.toString()) self._keyseq_target_actions[old_keytext].remove((group, name)) try: keyseq = QKeySequence(keyseq) keytext = str(keyseq.toString()) target_name_set = self._keyseq_target_actions[keytext] except KeyError: target_name_set = self._keyseq_target_actions[keytext] = set() self._add_global_shortcut_listener(keyseq) target_name_set.add((group, name)) self._update_tooltip(group, name, keyseq)
def test_load_default_shortcuts(self): shorts_count = self.shortcuts_manager.result_widget.topLevelItemCount() item = self.shortcuts_manager.result_widget.topLevelItem(0) shortcut_keys = item.text(1) # Expected data expected_key = QKeySequence(Qt.CTRL + Qt.Key_N) expected_key_str = expected_key.toString(QKeySequence.NativeText) # Just one shortcut should be loaded self.assertEqual(shorts_count, 1) # The key should be the same as the expected self.assertEqual(shortcut_keys, expected_key_str)
def test_load_default_shortcuts(self): shorts_count = self.shortcuts_manager.result_widget.topLevelItemCount() item = self.shortcuts_manager.result_widget.topLevelItem(0) shortcut_keys = item.text(1) # Expected data expected_key = QKeySequence(Qt.CTRL + Qt.Key_N) expected_key_str = expected_key.toString(QKeySequence.NativeText) # Just one shortcut should be loaded self.assertEqual(shorts_count, 1) # The key should be the same as the expected self.assertEqual(shortcut_keys, expected_key_str)
def _add_global_shortcut_listener(self, keyseq): # Create a shortcut for this new key sequence # Note: We associate the shortcut with the ENTIRE WINDOW. # We intercept the shortcut and decide which widget to direct it to. # (We don't rely on Qt to do this for us.) # Note: This class assumes that all widgets using shortcuts belong to the SAME main window. assert keyseq not in self._global_shortcuts keyseq = QKeySequence(keyseq) keytext = str(keyseq.toString()) self._global_shortcuts[keytext] = QShortcut( QKeySequence(keyseq), getMainWindow(), member=partial(self._handle_shortcut_pressed, keytext), context=Qt.ApplicationShortcut )
def _add_global_shortcut_listener(self, keyseq): # Create a shortcut for this new key sequence # Note: We associate the shortcut with the ENTIRE WINDOW. # We intercept the shortcut and decide which widget to direct it to. # (We don't rely on Qt to do this for us.) # Note: This class assumes that all widgets using shortcuts belong to the SAME main window. assert keyseq not in self._global_shortcuts keyseq = QKeySequence(keyseq) keytext = str(keyseq.toString()) self._global_shortcuts[keytext] = QShortcut( QKeySequence(keyseq), getMainWindow(), member=partial(self._handle_shortcut_pressed, keytext), context=Qt.ApplicationShortcut)
def shortcut(item): """Returns a suitable text for the keyboard shortcut of the given item. Item may be a QAction, a QShortcut, a QKeySequence or a QKeySequence.StandardKey. The text is meant to be used in the help docs. """ if isinstance(item, QAction): seq = item.shortcut() elif isinstance(item, QShortcut): seq = item.key() elif isinstance(item, QKeySequence.StandardKey): seq = QKeySequence(item) else: seq = item return seq.toString(QKeySequence.NativeText) or _("(no key defined)")
def eventFilter(self, object, event): """ Filters out key press events for the shortcut section for this edit. :param object | <QObject> event | <QEvent> """ if (object != self.uiShortcutTXT): return False if (event.type() == event.KeyPress): seq = QKeySequence(event.key() + int(event.modifiers())) self.uiShortcutTXT.setText(seq.toString()) return True elif (event.type() == event.KeyRelease): return True return False
def eventFilter( self, object, event ): """ Filters out key press events for the shortcut section for this edit. :param object | <QObject> event | <QEvent> """ if ( object != self.uiShortcutTXT ): return False if ( event.type() == event.KeyPress ): seq = QKeySequence(event.key() + int(event.modifiers())) self.uiShortcutTXT.setText( seq.toString() ) return True elif ( event.type() == event.KeyRelease): return True return False
def test_save_shortcuts(self): data = [] def called(): data.append(True) actions = gui.FakeActions() setattr(actions, 'update_shortcuts', called) self.patch(shortcut_manager.actions, 'Actions', lambda: actions) self.shortcuts_manager.result_widget.clear() key = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_N) key_str = key.toString(QKeySequence.NativeText) tree_data = ["New File", key_str, "New-File"] item = QTreeWidgetItem(self.shortcuts_manager.result_widget, tree_data) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) # Before save there is nothing in QSettings self.assertEqual(self.settings.value("New-File", None), None) # Save self.shortcuts_manager.save() # After save there is a value for New-File QSettings self.assertEqual(self.settings.values["New-File"], key_str) # After save check if NINJA call the update_shortcuts in actios.Actions self.assertEqual(data, [True])
def test_save_shortcuts(self): data = [] def called(): data.append(True) actions = gui.FakeActions() setattr(actions, 'update_shortcuts', called) self.patch(shortcut_manager.actions, 'Actions', lambda: actions) self.shortcuts_manager.result_widget.clear() key = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_N) key_str = key.toString(QKeySequence.NativeText) tree_data = ["New File", key_str, "New-File"] item = QTreeWidgetItem(self.shortcuts_manager.result_widget, tree_data) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) # Before save there is nothing in QSettings self.assertEqual(self.settings.value("New-File", None), None) # Save self.shortcuts_manager.save() # After save there is a value for New-File QSettings self.assertEqual(self.settings.values["New-File"], key_str) # After save check if NINJA call the update_shortcuts in actios.Actions self.assertEqual(data, [True])
def createButton(self, button, propertyDict=dict()): """ Creates the buttons according to the user size definition button: Button name propertyDict: optional dict parameters that may contain other properties to button, such as color, tooltip and custom category """ pushButton = QtGui.QPushButton(button) keys = propertyDict.keys() styleSheet = '' if 'buttonColor' in keys: r, g, b, a = propertyDict['buttonColor'].split(',') styleSheet += "background-color:rgba({0},{1},{2},{3});".format( r, g, b, a) if 'buttonToolTip' in keys: pushButton.setToolTip(propertyDict['buttonToolTip']) if 'buttonShortcut' in keys: keySequence = QKeySequence(propertyDict['buttonShortcut']) pushButton.setText('{0} [{1}]'.format( button, keySequence.toString(format=QKeySequence.NativeText))) pushButton.setShortcut(keySequence) pushButton.clicked.connect(self.reclassify) pushButton.toggled.connect(self.acquire) if self.size == 0: pushButton.setMinimumSize(100, 25) styleSheet += 'font-size:12px;' elif self.size == 1: pushButton.setMinimumSize(100, 40) styleSheet += 'font-size:20px;' elif self.size == 2: pushButton.setMinimumSize(100, 80) styleSheet += 'font-size:30px;' pushButton.setStyleSheet(styleSheet) self.buttons.append(pushButton) return pushButton
def stringWithAppendedShortcut(string: str, shortcut: QKeySequence) -> str: """ :returns: An HTML string that contains the given string with a suffixed shortcut key in grey. """ s = shortcut.toString(QKeySequence.NativeText) return "{0} <span style=\"color: gray; font-size: small\">{1}</span>".format(string, s)
class ShortcutChooserWidget(QtGui.QWidget, FORM_CLASS): keyPressed = pyqtSignal() def __init__(self, parent=None): """ Initializates ShortcutChooserWidget """ super(ShortcutChooserWidget, self).__init__(parent) self.resetVariables() self.setupUi(self) @pyqtSlot(bool) def on_assignShortcutPushButton_clicked(self): """ After button is clicked, focus is needed to use keyPressEvent and keyReleaseEvent """ self.setFocus() @pyqtSlot(bool) def on_assignShortcutPushButton_toggled(self, toggled): """ Button toggled reset self.modifiers and self.keys and also prepairs button text """ if toggled: self.resetVariables() self.assignShortcutPushButton.setText(self.tr('Enter Value')) @pyqtSlot(bool, name='on_clearPushButton_clicked') def clearAll(self): """ Clears push button and also resets self.modifiers and self.keys """ self.assignShortcutPushButton.setChecked(False) self.assignShortcutPushButton.setText(self.tr('Assign Shortcut')) self.resetVariables() def resetVariables(self): """ Resets self.modifiers, self.key and self.keySequence to 0 """ self.modifiers = 0 self.key = 0 self.keySequence = 0 def keyPressEvent(self, event): """ """ if not self.assignShortcutPushButton.isChecked(): super(ShortcutChooserWidget, self).keyPressEvent(event) return key = int(event.key()) if key == Qt.Key_Meta: self.modifiers |= Qt.META self.updateShortcutText() elif key == Qt.Key_Alt: self.modifiers |= Qt.ALT self.updateShortcutText() elif key == Qt.Key_Control: self.modifiers |= Qt.CTRL self.updateShortcutText() elif key == Qt.Key_Shift: self.modifiers |= Qt.SHIFT self.updateShortcutText() elif key == Qt.Key_Escape: self.assignShortcutPushButton.setChecked(False) return else: self.key = key self.updateShortcutText() def keyReleaseEvent(self, event): if not self.assignShortcutPushButton.isChecked(): super(ShortcutChooserWidget, self).keyReleaseEvent(event) return key = event.key() if key == Qt.Key_Meta: self.modifiers &= Qt.META self.updateShortcutText() elif key == Qt.Key_Alt: self.modifiers &= Qt.ALT self.updateShortcutText() elif key == Qt.Key_Control: self.modifiers &= Qt.CTRL self.updateShortcutText() elif key == Qt.Key_Shift: self.modifiers &= Qt.SHIFT self.updateShortcutText() elif key == Qt.Key_Escape: return else: self.assignShortcutPushButton.setChecked(False) self.updateShortcutText() self.setShortcut(self.keySequence) def setEnabled(self, enabled): if not enabled: self.clearAll() super(ShortcutChooserWidget, self).setEnabled(enabled) def setShortcut(self, shortcut): self.keySequence = QKeySequence(shortcut) self.assignShortcutPushButton.setChecked(False) self.assignShortcutPushButton.setText( self.keySequence.toString(format=QKeySequence.NativeText)) def getShortcut(self, asQKeySequence=False): if asQKeySequence: return self.keySequence else: return int(self.keySequence) def updateShortcutText(self): self.keySequence = QKeySequence(self.modifiers + self.key) #this uses QKeySequence.NativeText to show in the interface. To store data, no filter should be provided self.assignShortcutPushButton.setText( self.tr('Input: {0}').format( self.keySequence.toString(format=QKeySequence.NativeText)))
class KeySequenceButton(QPushButton): def __init__(self, parent=None): super(KeySequenceButton, self).__init__(parent) self.setIcon(icons.get("configure")) self._modifierlessAllowed = False self._seq = QKeySequence() self._timer = QTimer() self._timer.setSingleShot(True) self._isrecording = False self.clicked.connect(self.startRecording) self._timer.timeout.connect(self.doneRecording) def setKeySequence(self, seq): self._seq = seq self.updateDisplay() def keySequence(self): if self._isrecording: self.doneRecording() return self._seq def updateDisplay(self): if self._isrecording: s = self._recseq.toString(QKeySequence.NativeText).replace("&", "&&") if self._modifiers: if s: s += "," s += QKeySequence(self._modifiers).toString(QKeySequence.NativeText) elif self._recseq.isEmpty(): s = _("Input") s += " ..." else: s = self._seq.toString(QKeySequence.NativeText).replace("&", "&&") self.setText(s) def isRecording(self): return self._isrecording def event(self, ev): if self._isrecording: # prevent Qt from special casing Tab and Backtab if ev.type() == QEvent.KeyPress: self.keyPressEvent(ev) return True return super(KeySequenceButton, self).event(ev) def keyPressEvent(self, ev): if not self._isrecording: return super(KeySequenceButton, self).keyPressEvent(ev) if ev.isAutoRepeat(): return modifiers = int(ev.modifiers() & (Qt.SHIFT | Qt.CTRL | Qt.ALT | Qt.META)) ev.accept() key = ev.key() # check if key is a modifier or a character key without modifier (and if that is allowed) if ( # don't append the key if the key is -1 (garbage) or a modifier ... key not in (-1, Qt.Key_AltGr, Qt.Key_Shift, Qt.Key_Control, Qt.Key_Alt, Qt.Key_Meta, Qt.Key_Menu) # or if this is the first key and without modifier and modifierless keys are not allowed and ( self._modifierlessAllowed or self._recseq.count() > 0 or modifiers & ~Qt.SHIFT or not ev.text() or ( modifiers & Qt.SHIFT and key in ( Qt.Key_Return, Qt.Key_Space, Qt.Key_Tab, Qt.Key_Backtab, Qt.Key_Backspace, Qt.Key_Delete, Qt.Key_Escape, ) ) ) ): # change Shift+Backtab into Shift+Tab if key == Qt.Key_Backtab and modifiers & Qt.SHIFT: key = Qt.Key_Tab | modifiers # remove the Shift modifier if it doesn't make sense # elif (Qt.Key_Exclam <= key <= Qt.Key_At # or Qt.Key_Z < key <= 0x0ff): # key = key | (modifiers & ~Qt.SHIFT) else: key = key | modifiers # append max. 4 keystrokes if self._recseq.count() < 4: l = list(self._recseq) l.append(key) self._recseq = QKeySequence(*l) self._modifiers = modifiers self.controlTimer() self.updateDisplay() def keyReleaseEvent(self, ev): if not self._isrecording: return super(KeySequenceButton, self).keyReleaseEvent(ev) modifiers = int(ev.modifiers() & (Qt.SHIFT | Qt.CTRL | Qt.ALT | Qt.META)) ev.accept() self._modifiers = modifiers self.controlTimer() self.updateDisplay() def hideEvent(self, ev): if self._isrecording: self.cancelRecording() super(KeySequenceButton, self).hideEvent(ev) def controlTimer(self): if self._modifiers or self._recseq.isEmpty(): self._timer.stop() else: self._timer.start(600) def startRecording(self): self.setFocus(True) # because of QTBUG 17810 self.setDown(True) self.setStyleSheet("text-align: left;") self._isrecording = True self._recseq = QKeySequence() self._modifiers = int(QApplication.keyboardModifiers() & (Qt.SHIFT | Qt.CTRL | Qt.ALT | Qt.META)) self.grabKeyboard() self.updateDisplay() def doneRecording(self): self._seq = self._recseq self.cancelRecording() self.clearFocus() self.parentWidget().keySequenceChanged.emit(self.parentWidget().num()) def cancelRecording(self): if not self._isrecording: return self.setDown(False) self.setStyleSheet(None) self._isrecording = False self.releaseKeyboard() self.updateDisplay()
class ShortcutChooserWidget(QtGui.QWidget, FORM_CLASS): keyPressed = pyqtSignal() def __init__(self, parent=None): """ Initializates ShortcutChooserWidget """ super(ShortcutChooserWidget, self).__init__(parent) self.resetVariables() self.setupUi(self) @pyqtSlot(bool) def on_assignShortcutPushButton_clicked(self): """ After button is clicked, focus is needed to use keyPressEvent and keyReleaseEvent """ self.setFocus() @pyqtSlot(bool) def on_assignShortcutPushButton_toggled(self, toggled): """ Button toggled reset self.modifiers and self.keys and also prepairs button text """ if toggled: self.resetVariables() self.assignShortcutPushButton.setText(self.tr('Enter Value')) @pyqtSlot(bool, name = 'on_clearPushButton_clicked') def clearAll(self): """ Clears push button and also resets self.modifiers and self.keys """ self.assignShortcutPushButton.setChecked(False) self.assignShortcutPushButton.setText(self.tr('Assign Shortcut')) self.resetVariables() def resetVariables(self): """ Resets self.modifiers, self.key and self.keySequence to 0 """ self.modifiers = 0 self.key = 0 self.keySequence = 0 def keyPressEvent(self, event): """ """ if not self.assignShortcutPushButton.isChecked(): super(ShortcutChooserWidget, self).keyPressEvent(event) return key = int(event.key()) if key == Qt.Key_Meta: self.modifiers |= Qt.META self.updateShortcutText() elif key == Qt.Key_Alt: self.modifiers |= Qt.ALT self.updateShortcutText() elif key == Qt.Key_Control: self.modifiers |= Qt.CTRL self.updateShortcutText() elif key == Qt.Key_Shift: self.modifiers |= Qt.SHIFT self.updateShortcutText() elif key == Qt.Key_Escape: self.assignShortcutPushButton.setChecked(False) return else: self.key = key self.updateShortcutText() def keyReleaseEvent(self, event): if not self.assignShortcutPushButton.isChecked(): super(ShortcutChooserWidget, self).keyReleaseEvent(event) return key = event.key() if key == Qt.Key_Meta: self.modifiers &= Qt.META self.updateShortcutText() elif key == Qt.Key_Alt: self.modifiers &= Qt.ALT self.updateShortcutText() elif key == Qt.Key_Control: self.modifiers &= Qt.CTRL self.updateShortcutText() elif key == Qt.Key_Shift: self.modifiers &= Qt.SHIFT self.updateShortcutText() elif key == Qt.Key_Escape: return else: self.assignShortcutPushButton.setChecked(False) self.updateShortcutText() self.setShortcut(self.keySequence) def setEnabled(self, enabled): if not enabled: self.clearAll() super(ShortcutChooserWidget, self).setEnabled(enabled) def setShortcut(self, shortcut): self.keySequence = QKeySequence(shortcut) self.assignShortcutPushButton.setChecked(False) self.assignShortcutPushButton.setText(self.keySequence.toString(format = QKeySequence.NativeText)) def getShortcut(self, asQKeySequence = False): if asQKeySequence: return self.keySequence else: return int(self.keySequence) def updateShortcutText(self): self.keySequence = QKeySequence(self.modifiers+self.key) #this uses QKeySequence.NativeText to show in the interface. To store data, no filter should be provided self.assignShortcutPushButton.setText(self.tr('Input: {0}').format(self.keySequence.toString(format = QKeySequence.NativeText)))
class KeySequenceButton(QPushButton): def __init__(self, parent=None): super(KeySequenceButton, self).__init__(parent) self.setIcon(icons.get("configure")) self._modifierlessAllowed = False self._seq = QKeySequence() self._timer = QTimer() self._timer.setSingleShot(True) self._isrecording = False self.clicked.connect(self.startRecording) self._timer.timeout.connect(self.doneRecording) def setKeySequence(self, seq): self._seq = seq self.updateDisplay() def keySequence(self): if self._isrecording: self.doneRecording() return self._seq def updateDisplay(self): if self._isrecording: s = self._recseq.toString(QKeySequence.NativeText).replace( '&', '&&') if self._modifiers: if s: s += "," s += QKeySequence(self._modifiers).toString( QKeySequence.NativeText) elif self._recseq.isEmpty(): s = _("Input") s += " ..." else: s = self._seq.toString(QKeySequence.NativeText).replace('&', '&&') self.setText(s) def isRecording(self): return self._isrecording def event(self, ev): if self._isrecording: # prevent Qt from special casing Tab and Backtab if ev.type() == QEvent.KeyPress: self.keyPressEvent(ev) return True return super(KeySequenceButton, self).event(ev) def keyPressEvent(self, ev): if not self._isrecording: return super(KeySequenceButton, self).keyPressEvent(ev) if ev.isAutoRepeat(): return modifiers = int(ev.modifiers() & (Qt.SHIFT | Qt.CTRL | Qt.ALT | Qt.META)) ev.accept() key = ev.key() # check if key is a modifier or a character key without modifier (and if that is allowed) if ( # don't append the key if the key is -1 (garbage) or a modifier ... key not in (-1, Qt.Key_AltGr, Qt.Key_Shift, Qt.Key_Control, Qt.Key_Alt, Qt.Key_Meta, Qt.Key_Menu) # or if this is the first key and without modifier and modifierless keys are not allowed and (self._modifierlessAllowed or self._recseq.count() > 0 or modifiers & ~Qt.SHIFT or not ev.text() or (modifiers & Qt.SHIFT and key in (Qt.Key_Return, Qt.Key_Space, Qt.Key_Tab, Qt.Key_Backtab, Qt.Key_Backspace, Qt.Key_Delete, Qt.Key_Escape)))): # change Shift+Backtab into Shift+Tab if key == Qt.Key_Backtab and modifiers & Qt.SHIFT: key = Qt.Key_Tab | modifiers # remove the Shift modifier if it doesn't make sense # elif (Qt.Key_Exclam <= key <= Qt.Key_At # or Qt.Key_Z < key <= 0x0ff): # key = key | (modifiers & ~Qt.SHIFT) else: key = key | modifiers # append max. 4 keystrokes if self._recseq.count() < 4: l = list(self._recseq) l.append(key) self._recseq = QKeySequence(*l) self._modifiers = modifiers self.controlTimer() self.updateDisplay() def keyReleaseEvent(self, ev): if not self._isrecording: return super(KeySequenceButton, self).keyReleaseEvent(ev) modifiers = int(ev.modifiers() & (Qt.SHIFT | Qt.CTRL | Qt.ALT | Qt.META)) ev.accept() self._modifiers = modifiers self.controlTimer() self.updateDisplay() def hideEvent(self, ev): if self._isrecording: self.cancelRecording() super(KeySequenceButton, self).hideEvent(ev) def controlTimer(self): if self._modifiers or self._recseq.isEmpty(): self._timer.stop() else: self._timer.start(600) def startRecording(self): self.setFocus(True) # because of QTBUG 17810 self.setDown(True) self.setStyleSheet("text-align: left;") self._isrecording = True self._recseq = QKeySequence() self._modifiers = int(QApplication.keyboardModifiers() & (Qt.SHIFT | Qt.CTRL | Qt.ALT | Qt.META)) self.grabKeyboard() self.updateDisplay() def doneRecording(self): self._seq = self._recseq self.cancelRecording() self.clearFocus() self.parentWidget().keySequenceChanged.emit(self.parentWidget().num()) def cancelRecording(self): if not self._isrecording: return self.setDown(False) self.setStyleSheet(None) self._isrecording = False self.releaseKeyboard() self.updateDisplay()