feat(qtermwidget): add clipboard shortcuts for copy and paste functionality

This commit is contained in:
2026-07-09 11:30:37 +02:00
committed by Christian Appel
parent 007fde4aa5
commit bcc39400e7
2 changed files with 51 additions and 2 deletions
@@ -2,12 +2,13 @@
Simply displays a message in a QLabel if the dependency is not installed."""
import os
import sys
from functools import wraps
from typing import Sequence
from qtpy.QtCore import QIODevice, QPoint, QSize, QUrl, Signal # type: ignore
from qtpy.QtGui import QAction, QFont, QKeyEvent, QResizeEvent, Qt # type: ignore
from qtpy.QtWidgets import QLabel, QVBoxLayout, QWidget
from qtpy.QtGui import QAction, QFont, QKeyEvent, QKeySequence, QResizeEvent, Qt # type: ignore
from qtpy.QtWidgets import QLabel, QShortcut, QVBoxLayout, QWidget
try:
from pyside6_qtermwidget import QTermWidget
@@ -50,6 +51,7 @@ class BecQTerm(QWidget):
super().__init__(parent)
self._layout = QVBoxLayout()
self.setLayout(self._layout)
self._clipboard_shortcuts: dict[str, QShortcut] = {}
if QTermWidget:
self._main_widget = QTermWidget(parent=self)
self._main_widget.activity.connect(self.activity)
@@ -71,6 +73,7 @@ class BecQTerm(QWidget):
self._layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
self._main_widget = QLabel("pyside6_qterminal is not installed!")
self._install_clipboard_shortcuts()
self._layout.addWidget(self._main_widget)
def write(self, text: str, add_newline: bool = True):
@@ -97,6 +100,36 @@ class BecQTerm(QWidget):
"""Send Ctrl+C to the terminal."""
self.write("\x03", add_newline=False) # Send Ctrl+C character to the terminal
def _install_clipboard_shortcuts(self) -> None:
copy_sequence: QKeySequence | str
paste_sequence: QKeySequence | str
if sys.platform == "darwin":
copy_sequence = QKeySequence(QKeySequence.StandardKey.Copy)
paste_sequence = QKeySequence(QKeySequence.StandardKey.Paste)
else:
# Let's not override the Ctrl+C shortcut
copy_sequence = "Ctrl+Shift+C"
paste_sequence = "Ctrl+Shift+V"
self._clipboard_shortcuts["copy"] = self._make_shortcut(
copy_sequence, self._handle_copy_shortcut
)
self._clipboard_shortcuts["paste"] = self._make_shortcut(
paste_sequence, self._handle_paste_shortcut
)
def _make_shortcut(self, sequence: QKeySequence | str, slot) -> QShortcut:
shortcut = QShortcut(QKeySequence(sequence), self)
shortcut.setContext(Qt.ShortcutContext.WidgetWithChildrenShortcut)
shortcut.activated.connect(slot)
return shortcut
def _handle_copy_shortcut(self) -> None:
self._copyClipboard()
def _handle_paste_shortcut(self) -> None:
self._pasteClipboard()
# automatically forwarded to the widget only if it exists
@_forward
def _addCustomColorSchemeDir(self, custom_dir: str, /) -> None: ...
+16
View File
@@ -14,6 +14,7 @@ from bec_widgets.widgets.editors.bec_console.bec_console import (
ConsoleMode,
_bec_console_registry,
)
from bec_widgets.widgets.utility.bec_term.qtermwidget_wrapper import BecQTerm
from .client_mocks import mocked_client
@@ -354,3 +355,18 @@ def test_plain_console_terminal_removed_after_last_unregister(qtbot):
_bec_console_registry.unregister(widget)
assert "plain_terminal" not in _bec_console_registry._terminal_registry
def test_bec_qterm_clipboard_shortcuts_call_terminal_clipboard_methods(qtbot):
term = BecQTerm()
qtbot.addWidget(term)
with (
mock.patch.object(term, "_copyClipboard") as mock_copy,
mock.patch.object(term, "_pasteClipboard") as mock_paste,
):
term._clipboard_shortcuts["copy"].activated.emit()
term._clipboard_shortcuts["paste"].activated.emit()
mock_copy.assert_called_once_with()
mock_paste.assert_called_once_with()