Python PyQt5.QtCore.Qt.ShiftModifier() Examples

The following are 30 code examples of PyQt5.QtCore.Qt.ShiftModifier(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module PyQt5.QtCore.Qt , or try the search function .
Example #1
Source File: keyutils.py    From qutebrowser with GNU General Public License v3.0 9 votes vote down vote up
def text(self) -> str:
        """Get the text which would be displayed when pressing this key."""
        control = {
            Qt.Key_Space: ' ',
            Qt.Key_Tab: '\t',
            Qt.Key_Backspace: '\b',
            Qt.Key_Return: '\r',
            Qt.Key_Enter: '\r',
            Qt.Key_Escape: '\x1b',
        }

        if self.key in control:
            return control[self.key]
        elif not _is_printable(self.key):
            return ''

        text = QKeySequence(self.key).toString()
        if not self.modifiers & Qt.ShiftModifier:  # type: ignore[operator]
            text = text.lower()
        return text 
Example #2
Source File: webelem.py    From qutebrowser with GNU General Public License v3.0 8 votes vote down vote up
def _click_fake_event(self, click_target: usertypes.ClickTarget,
                          button: Qt.MouseButton = Qt.LeftButton) -> None:
        """Send a fake click event to the element."""
        pos = self._mouse_pos()

        log.webelem.debug("Sending fake click to {!r} at position {} with "
                          "target {}".format(self, pos, click_target))

        target_modifiers = {
            usertypes.ClickTarget.normal: Qt.NoModifier,
            usertypes.ClickTarget.window: Qt.AltModifier | Qt.ShiftModifier,
            usertypes.ClickTarget.tab: Qt.ControlModifier,
            usertypes.ClickTarget.tab_bg: Qt.ControlModifier,
        }
        if config.val.tabs.background:
            target_modifiers[usertypes.ClickTarget.tab] |= Qt.ShiftModifier
        else:
            target_modifiers[usertypes.ClickTarget.tab_bg] |= Qt.ShiftModifier

        modifiers = typing.cast(Qt.KeyboardModifiers,
                                target_modifiers[click_target])

        events = [
            QMouseEvent(QEvent.MouseMove, pos, Qt.NoButton, Qt.NoButton,
                        Qt.NoModifier),
            QMouseEvent(QEvent.MouseButtonPress, pos, button, button,
                        modifiers),
            QMouseEvent(QEvent.MouseButtonRelease, pos, button, Qt.NoButton,
                        modifiers),
        ]

        for evt in events:
            self._tab.send_event(evt)

        QTimer.singleShot(0, self._move_text_cursor) 
Example #3
Source File: cue_widget.py    From linux-show-player with GNU General Public License v3.0 6 votes vote down vote up
def mouseMoveEvent(self, event):
        if (event.buttons() == Qt.LeftButton and
                (event.modifiers() == Qt.ControlModifier or
                         event.modifiers() == Qt.ShiftModifier)):
            mime_data = QMimeData()
            mime_data.setText(PageWidget.DRAG_MAGIC)

            drag = QDrag(self)
            drag.setMimeData(mime_data)
            drag.setPixmap(self.grab(self.rect()))

            if event.modifiers() == Qt.ControlModifier:
                drag.exec_(Qt.MoveAction)
            else:
                drag.exec_(Qt.CopyAction)

            event.accept()
        else:
            event.ignore() 
Example #4
Source File: webview.py    From qutebrowser with GNU General Public License v3.0 6 votes vote down vote up
def mousePressEvent(self, e):
        """Set the tabdata ClickTarget on a mousepress.

        This is implemented here as we don't need it for QtWebEngine.
        """
        if e.button() == Qt.MidButton or e.modifiers() & Qt.ControlModifier:
            background = config.val.tabs.background
            if e.modifiers() & Qt.ShiftModifier:
                background = not background
            if background:
                target = usertypes.ClickTarget.tab_bg
            else:
                target = usertypes.ClickTarget.tab
            self._tabdata.open_target = target
            log.mouse.debug("Ctrl/Middle click, setting target: {}".format(
                target))
        else:
            self._tabdata.open_target = usertypes.ClickTarget.normal
            log.mouse.debug("Normal click, setting normal target")
        super().mousePressEvent(e) 
Example #5
Source File: page_widget.py    From linux-show-player with GNU General Public License v3.0 5 votes vote down vote up
def dropEvent(self, event):
        row, column = self._event_index(event)
        if self.layout().itemAtPosition(row, column) is None:
            if qApp.keyboardModifiers() == Qt.ControlModifier:
                event.setDropAction(Qt.MoveAction)
                event.accept()
                self.move_drop_event.emit(event.source(), row, column)
            elif qApp.keyboardModifiers() == Qt.ShiftModifier:
                event.setDropAction(Qt.CopyAction)
                self.copy_drop_event.emit(event.source(), row, column)
                event.accept()

        event.ignore() 
Example #6
Source File: CuraSceneController.py    From Cura with GNU Lesser General Public License v3.0 5 votes vote down vote up
def changeSelection(self, index):
        """Either select or deselect an item"""

        modifiers = QApplication.keyboardModifiers()
        ctrl_is_active = modifiers & Qt.ControlModifier
        shift_is_active = modifiers & Qt.ShiftModifier

        if ctrl_is_active:
            item = self._objects_model.getItem(index)
            node = item["node"]
            if Selection.isSelected(node):
                Selection.remove(node)
            else:
                Selection.add(node)
        elif shift_is_active:
            polarity = 1 if index + 1 > self._last_selected_index else -1
            for i in range(self._last_selected_index, index + polarity, polarity):
                item = self._objects_model.getItem(i)
                node = item["node"]
                Selection.add(node)
        else:
            # Single select
            item = self._objects_model.getItem(index)
            node = item["node"]
            build_plate_number = node.callDecoration("getBuildPlateNumber")
            if build_plate_number is not None and build_plate_number != -1:
                self.setActiveBuildPlate(build_plate_number)
            Selection.clear()
            Selection.add(node)

        self._last_selected_index = index 
Example #7
Source File: cue_widget.py    From linux-show-player with GNU General Public License v3.0 5 votes vote down vote up
def _clicked(self, event):
        if not (self.seekSlider.geometry().contains(event.pos()) and
                    self.seekSlider.isVisible()):
            if event.button() != Qt.RightButton:
                if event.modifiers() == Qt.ShiftModifier:
                    self.edit_request.emit(self.cue)
                elif event.modifiers() == Qt.ControlModifier:
                    self.selected = not self.selected
                else:
                    self.cue_executed.emit(self.cue)
                    self.cue.execute() 
Example #8
Source File: layout.py    From linux-show-player with GNU General Public License v3.0 5 votes vote down vote up
def dragEnterEvent(self, event):
        if qApp.keyboardModifiers() == Qt.ControlModifier:
            event.setDropAction(Qt.MoveAction)
            event.accept()
        elif qApp.keyboardModifiers() == Qt.ShiftModifier:
            event.setDropAction(Qt.MoveAction)
            event.accept()
        else:
            event.ignore() 
Example #9
Source File: Q7VTKRenderWindowInteractor.py    From pyCGNS with GNU Lesser General Public License v2.1 5 votes vote down vote up
def _GetCtrlShift(self, ev):
        ctrl = shift = False

        if hasattr(ev, 'modifiers'):
            if ev.modifiers() & Qt.ShiftModifier:
                shift = True
            if ev.modifiers() & Qt.ControlModifier:
                ctrl = True
        else:
            if self.__saveModifiers & Qt.ShiftModifier:
                shift = True
            if self.__saveModifiers & Qt.ControlModifier:
                ctrl = True

        return ctrl, shift 
Example #10
Source File: QVTKRenderWindowInteractor.py    From pyCGNS with GNU Lesser General Public License v2.1 5 votes vote down vote up
def _GetCtrlShift(self, ev):
        ctrl = shift = False

        if hasattr(ev, 'modifiers'):
            if ev.modifiers() & Qt.ShiftModifier:
                shift = True
            if ev.modifiers() & Qt.ControlModifier:
                ctrl = True
        else:
            if self.__saveModifiers & Qt.ShiftModifier:
                shift = True
            if self.__saveModifiers & Qt.ControlModifier:
                ctrl = True

        return ctrl, shift 
Example #11
Source File: mainwindow.py    From bluesky with GNU General Public License v3.0 5 votes vote down vote up
def keyPressEvent(self, event):
        if event.modifiers() & Qt.ShiftModifier \
                and event.key() in [Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right]:
            dlat = 1.0 / (self.radarwidget.zoom * self.radarwidget.ar)
            dlon = 1.0 / (self.radarwidget.zoom * self.radarwidget.flat_earth)
            if event.key() == Qt.Key_Up:
                self.radarwidget.panzoom(pan=(dlat, 0.0))
            elif event.key() == Qt.Key_Down:
                self.radarwidget.panzoom(pan=(-dlat, 0.0))
            elif event.key() == Qt.Key_Left:
                self.radarwidget.panzoom(pan=(0.0, -dlon))
            elif event.key() == Qt.Key_Right:
                self.radarwidget.panzoom(pan=(0.0, dlon))

        elif event.key() == Qt.Key_Escape:
            self.closeEvent()

        elif event.key() == Qt.Key_F11:  # F11 = Toggle Full Screen mode
            if not self.isFullScreen():
                self.showFullScreen()
            else:
                self.showNormal()

        else:
            # All other events go to the BlueSky console
            self.console.keyPressEvent(event)
        event.accept() 
Example #12
Source File: SelectableGraphicView.py    From urh with GNU General Public License v3.0 5 votes vote down vote up
def mousePressEvent(self, event: QMouseEvent):
        if self.scene() is None:
            return

        cursor = self.cursor().shape()
        has_shift_modifier = event.modifiers() == Qt.ShiftModifier
        is_in_shift_mode = (has_shift_modifier and self.hold_shift_to_drag) \
                           or (not has_shift_modifier and not self.hold_shift_to_drag) \
                              and cursor != Qt.SplitHCursor and cursor != Qt.SplitVCursor

        if event.buttons() == Qt.LeftButton and is_in_shift_mode:
            self.setCursor(Qt.ClosedHandCursor)
            self.grab_start = event.pos()
        elif event.buttons() == Qt.LeftButton:
            if self.is_pos_in_separea(self.mapToScene(event.pos())):
                self.separation_area_moving = True
                self.setCursor(Qt.SplitVCursor)

            elif self.selection_area.is_empty or self.selection_area.selected_edge is None:
                # Create new selection
                self.mouse_press_pos = event.pos()
                self.mouse_pos = event.pos()
                scene_pos = self.mapToScene(self.mouse_press_pos)
                self.__set_selection_area(x=scene_pos.x(), y=scene_pos.y(), w=0, h=0)
                self.selection_area.finished = False

            elif self.selection_area.selected_edge is not None:
                self.selection_area.resizing = True 
Example #13
Source File: test_panes.py    From mu with GNU General Public License v3.0 5 votes vote down vote up
def test_MicroPythonREPLPane_keyPressEvent_CTRL_C_Darwin(qtapp):
    """
    Ensure end key in the REPL is handled correctly.
    """
    mock_serial = mock.MagicMock()
    rp = mu.interface.panes.MicroPythonREPLPane(mock_serial)
    rp.copy = mock.MagicMock()
    data = mock.MagicMock()
    data.key = mock.MagicMock(return_value=Qt.Key_C)
    data.text = mock.MagicMock(return_value="1b")
    data.modifiers.return_value = Qt.ControlModifier | Qt.ShiftModifier
    rp.keyPressEvent(data)
    rp.copy.assert_called_once_with() 
Example #14
Source File: test_panes.py    From mu with GNU General Public License v3.0 5 votes vote down vote up
def test_MicroPythonREPLPane_keyPressEvent_CTRL_V_Darwin(qtapp):
    """
    Ensure end key in the REPL is handled correctly.
    """
    mock_serial = mock.MagicMock()
    rp = mu.interface.panes.MicroPythonREPLPane(mock_serial)
    rp.paste = mock.MagicMock()
    data = mock.MagicMock()
    data.key = mock.MagicMock(return_value=Qt.Key_V)
    data.text = mock.MagicMock(return_value="1b")
    data.modifiers.return_value = Qt.ControlModifier | Qt.ShiftModifier
    rp.keyPressEvent(data)
    rp.paste.assert_called_once_with() 
Example #15
Source File: test_panes.py    From mu with GNU General Public License v3.0 5 votes vote down vote up
def test_PythonProcessPane_parse_input_paste(qtapp):
    """
    Control-Shift-V (paste) character causes a paste to happen.
    """
    ppp = mu.interface.panes.PythonProcessPane()
    key = Qt.Key_V
    text = ""
    modifiers = Qt.ControlModifier | Qt.ShiftModifier
    ppp.paste = mock.MagicMock()
    ppp.parse_input(key, text, modifiers)
    ppp.paste.assert_called_once_with() 
Example #16
Source File: test_panes.py    From mu with GNU General Public License v3.0 5 votes vote down vote up
def test_PythonProcessPane_parse_input_copy(qtapp):
    """
    Control-Shift-C (copy) character causes copy to happen.
    """
    ppp = mu.interface.panes.PythonProcessPane()
    key = Qt.Key_C
    text = ""
    modifiers = Qt.ControlModifier | Qt.ShiftModifier
    ppp.copy = mock.MagicMock()
    ppp.parse_input(key, text, modifiers)
    ppp.copy.assert_called_once_with() 
Example #17
Source File: QVTKRenderWindowInteractor.py    From Det3D with Apache License 2.0 5 votes vote down vote up
def _GetCtrlShift(self, ev):
        ctrl = shift = False

        if hasattr(ev, "modifiers"):
            if ev.modifiers() & Qt.ShiftModifier:
                shift = True
            if ev.modifiers() & Qt.ControlModifier:
                ctrl = True
        else:
            if self.__saveModifiers & Qt.ShiftModifier:
                shift = True
            if self.__saveModifiers & Qt.ControlModifier:
                ctrl = True

        return ctrl, shift 
Example #18
Source File: layout.py    From linux-show-player with GNU General Public License v3.0 5 votes vote down vote up
def onKeyPressEvent(self, e):
        if not e.isAutoRepeat():
            keys = e.key()
            modifiers = e.modifiers()

            if modifiers & Qt.ShiftModifier:
                keys += Qt.SHIFT
            if modifiers & Qt.ControlModifier:
                keys += Qt.CTRL
            if modifiers & Qt.AltModifier:
                keys += Qt.ALT
            if modifiers & Qt.MetaModifier:
                keys += Qt.META

            if QKeySequence(keys) in self._go_key_sequence:
                self.go()
            elif e.key() == Qt.Key_Space:
                if qApp.keyboardModifiers() == Qt.ShiftModifier:
                    cue = self.current_cue()
                    if cue is not None:
                        self.edit_cue(cue)
                elif qApp.keyboardModifiers() == Qt.ControlModifier:
                    item = self.current_item()
                    if item is not None:
                        item.selected = not item.selected
            else:
                self.key_pressed.emit(e)

        e.accept() 
Example #19
Source File: test_miscwidgets.py    From qutebrowser with GNU General Public License v3.0 5 votes vote down vote up
def test_selection_cursor_left(self, qtbot, cmd_edit):
        """Test selection persisting when moving to the first char."""
        qtbot.keyClicks(cmd_edit, ':hello')
        assert cmd_edit.text() == ':hello'
        assert cmd_edit.cursorPosition() == len(':hello')
        for _ in ':hello':
            qtbot.keyClick(cmd_edit, Qt.Key_Left, modifier=Qt.ShiftModifier)
        assert cmd_edit.cursorPosition() == len(':')
        assert cmd_edit.selectionStart() == len(':') 
Example #20
Source File: qt_helper.py    From uPyLoader with MIT License 5 votes vote down vote up
def key_event_sequence(event):
        val = event.key()
        mod = event.modifiers()
        if mod & Qt.ShiftModifier:
            val += Qt.SHIFT
        if mod & Qt.ControlModifier:
            val += Qt.CTRL
        if mod & Qt.AltModifier:
            val += Qt.ALT
        if mod & Qt.MetaModifier:
            val += Qt.META
        return QKeySequence(val) 
Example #21
Source File: keyutils.py    From qutebrowser with GNU General Public License v3.0 5 votes vote down vote up
def __str__(self) -> str:
        """Convert this KeyInfo to a meaningful name.

        Return:
            A name of the key (combination) as a string.
        """
        key_string = _key_to_string(self.key)
        modifiers = int(self.modifiers)

        if self.key in _MODIFIER_MAP:
            # Don't return e.g. <Shift+Shift>
            modifiers &= ~_MODIFIER_MAP[self.key]
        elif _is_printable(self.key):
            # "normal" binding
            if not key_string:  # pragma: no cover
                raise ValueError("Got empty string for key 0x{:x}!"
                                 .format(self.key))

            assert len(key_string) == 1, key_string
            if self.modifiers == Qt.ShiftModifier:
                assert not is_special(self.key, self.modifiers)
                return key_string.upper()
            elif self.modifiers == Qt.NoModifier:
                assert not is_special(self.key, self.modifiers)
                return key_string.lower()
            else:
                # Use special binding syntax, but <Ctrl-a> instead of <Ctrl-A>
                key_string = key_string.lower()

        modifiers = Qt.KeyboardModifier(modifiers)

        # "special" binding
        assert is_special(self.key, self.modifiers)
        modifier_string = _modifiers_to_string(modifiers)
        return '<{}{}>'.format(modifier_string, key_string) 
Example #22
Source File: keyutils.py    From qutebrowser with GNU General Public License v3.0 5 votes vote down vote up
def is_special(key: Qt.Key, modifiers: _ModifierType) -> bool:
    """Check whether this key requires special key syntax."""
    _assert_plain_key(key)
    _assert_plain_modifier(modifiers)
    return not (_is_printable(key) and
                modifiers in [Qt.ShiftModifier, Qt.NoModifier]) 
Example #23
Source File: test_keyutils.py    From qutebrowser with GNU General Public License v3.0 5 votes vote down vote up
def test_key_info_to_int():
    info = keyutils.KeyInfo(Qt.Key_A, Qt.ShiftModifier)
    assert info.to_int() == Qt.Key_A | Qt.ShiftModifier 
Example #24
Source File: test_keyutils.py    From qutebrowser with GNU General Public License v3.0 5 votes vote down vote up
def test_key_info_to_event():
    info = keyutils.KeyInfo(Qt.Key_A, Qt.ShiftModifier)
    ev = info.to_event()
    assert ev.key() == Qt.Key_A
    assert ev.modifiers() == Qt.ShiftModifier
    assert ev.text() == 'A' 
Example #25
Source File: test_keyutils.py    From qutebrowser with GNU General Public License v3.0 5 votes vote down vote up
def test_repr(self):
        seq = keyutils.KeySequence(Qt.Key_A | Qt.ControlModifier,
                                   Qt.Key_B | Qt.ShiftModifier)
        assert repr(seq) == ("<qutebrowser.keyinput.keyutils.KeySequence "
                             "keys='<Ctrl+a>B'>") 
Example #26
Source File: test_keyutils.py    From qutebrowser with GNU General Public License v3.0 5 votes vote down vote up
def test_iter(self):
        seq = keyutils.KeySequence(Qt.Key_A | Qt.ControlModifier,
                                   Qt.Key_B | Qt.ShiftModifier,
                                   Qt.Key_C,
                                   Qt.Key_D,
                                   Qt.Key_E)
        expected = [keyutils.KeyInfo(Qt.Key_A, Qt.ControlModifier),
                    keyutils.KeyInfo(Qt.Key_B, Qt.ShiftModifier),
                    keyutils.KeyInfo(Qt.Key_C, Qt.NoModifier),
                    keyutils.KeyInfo(Qt.Key_D, Qt.NoModifier),
                    keyutils.KeyInfo(Qt.Key_E, Qt.NoModifier)]
        assert list(seq) == expected 
Example #27
Source File: test_keyutils.py    From qutebrowser with GNU General Public License v3.0 5 votes vote down vote up
def test_text(self, qt_key, upper):
        """Test KeyInfo.text() with all possible keys.

        See key_data.py for inputs and expected values.
        """
        modifiers = Qt.ShiftModifier if upper else Qt.KeyboardModifiers()
        info = keyutils.KeyInfo(qt_key.member, modifiers=modifiers)
        expected = qt_key.uppertext if upper else qt_key.text
        assert info.text() == expected 
Example #28
Source File: test_basekeyparser.py    From qutebrowser with GNU General Public License v3.0 5 votes vote down vote up
def test_binding_with_shift(self, prompt_keyparser):
        """Simulate a binding which involves shift."""
        for key, modifiers in [(Qt.Key_Y, Qt.NoModifier),
                               (Qt.Key_Shift, Qt.ShiftModifier),
                               (Qt.Key_Y, Qt.ShiftModifier)]:
            info = keyutils.KeyInfo(key, modifiers)
            prompt_keyparser.handle(info.to_event())

        prompt_keyparser.execute.assert_called_once_with('yank -s', None) 
Example #29
Source File: modeman.py    From qutebrowser with GNU General Public License v3.0 4 votes vote down vote up
def _handle_keypress(self, event: QKeyEvent, *,
                         dry_run: bool = False) -> bool:
        """Handle filtering of KeyPress events.

        Args:
            event: The KeyPress to examine.
            dry_run: Don't actually handle the key, only filter it.

        Return:
            True if event should be filtered, False otherwise.
        """
        curmode = self.mode
        parser = self.parsers[curmode]
        if curmode != usertypes.KeyMode.insert:
            log.modes.debug("got keypress in mode {} - delegating to "
                            "{}".format(curmode, utils.qualname(parser)))
        match = parser.handle(event, dry_run=dry_run)

        has_modifier = event.modifiers() not in [
            Qt.NoModifier,
            Qt.ShiftModifier,
        ]  # type: ignore[comparison-overlap]
        is_non_alnum = has_modifier or not event.text().strip()

        forward_unbound_keys = config.cache['input.forward_unbound_keys']

        if match:
            filter_this = True
        elif (parser.passthrough or forward_unbound_keys == 'all' or
              (forward_unbound_keys == 'auto' and is_non_alnum)):
            filter_this = False
        else:
            filter_this = True

        if not filter_this and not dry_run:
            self._releaseevents_to_pass.add(KeyEvent.from_event(event))

        if curmode != usertypes.KeyMode.insert:
            focus_widget = QApplication.instance().focusWidget()
            log.modes.debug("match: {}, forward_unbound_keys: {}, "
                            "passthrough: {}, is_non_alnum: {}, dry_run: {} "
                            "--> filter: {} (focused: {!r})".format(
                                match, forward_unbound_keys,
                                parser.passthrough, is_non_alnum, dry_run,
                                filter_this, focus_widget))
        return filter_this 
Example #30
Source File: keyutils.py    From qutebrowser with GNU General Public License v3.0 4 votes vote down vote up
def append_event(self, ev: QKeyEvent) -> 'KeySequence':
        """Create a new KeySequence object with the given QKeyEvent added."""
        key = Qt.Key(ev.key())

        _assert_plain_key(key)
        _assert_plain_modifier(ev.modifiers())

        key = _remap_unicode(key, ev.text())
        modifiers = int(ev.modifiers())

        if key == _NIL_KEY:
            raise KeyParseError(None, "Got nil key!")

        # We always remove Qt.GroupSwitchModifier because QKeySequence has no
        # way to mention that in a binding anyways...
        modifiers &= ~Qt.GroupSwitchModifier

        # We change Qt.Key_Backtab to Key_Tab here because nobody would
        # configure "Shift-Backtab" in their config.
        if modifiers & Qt.ShiftModifier and key == Qt.Key_Backtab:
            key = Qt.Key_Tab

        # We don't care about a shift modifier with symbols (Shift-: should
        # match a : binding even though we typed it with a shift on an
        # US-keyboard)
        #
        # However, we *do* care about Shift being involved if we got an
        # upper-case letter, as Shift-A should match a Shift-A binding, but not
        # an "a" binding.
        #
        # In addition, Shift also *is* relevant when other modifiers are
        # involved. Shift-Ctrl-X should not be equivalent to Ctrl-X.
        if (modifiers == Qt.ShiftModifier and
                _is_printable(key) and
                not ev.text().isupper()):
            modifiers = Qt.KeyboardModifiers()  # type: ignore[assignment]

        # On macOS, swap Ctrl and Meta back
        # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-51293
        if utils.is_mac:
            if modifiers & Qt.ControlModifier and modifiers & Qt.MetaModifier:
                pass
            elif modifiers & Qt.ControlModifier:
                modifiers &= ~Qt.ControlModifier
                modifiers |= Qt.MetaModifier
            elif modifiers & Qt.MetaModifier:
                modifiers &= ~Qt.MetaModifier
                modifiers |= Qt.ControlModifier

        keys = list(self._iter_keys())
        keys.append(key | int(modifiers))

        return self.__class__(*keys)