From febdd512474a7ffe358b01c15b72871c3f862170 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 20 Oct 2026 11:26:06 +0200 Subject: Ctrl+A / Ctrl+Shift+A: select visible and clear, Packages and Hints The search field keeps Ctrl+A for its own text. Co-Authored-By: Claude Opus 5.5 --- README.md | 3 ++- sb_builder/hints_tab.py | 10 +++++++--- sb_builder/packages.py | 11 ++++++++--- tests/test_gui.py | 11 +++++++++-- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e1f93cc..6d03f06 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ Every key is optional. `File > Reload config` rereads the GUI config. - **Open > Packages** (or click the Packages tile): every package of the repository, with built version and status (`ok`, `failed`, `never`, `outdated`). Search by name or summary, or with `cat:`, `maint:`, `req:`, - `status:`; toggle the overlay and status chips. The detail pane shows the + `status:`; toggle the overlay and status chips. Ctrl+A ticks every visible + package, Ctrl+Shift+A unticks all (here and in Hints). The detail pane shows the package's versions, its dependencies after hints (dropped ones struck through), and what its hint file does, section by section. - Tick packages (or select one row) and press Build, Update, Rebuild or diff --git a/sb_builder/hints_tab.py b/sb_builder/hints_tab.py index f4bc378..8d0bed4 100644 --- a/sb_builder/hints_tab.py +++ b/sb_builder/hints_tab.py @@ -20,7 +20,7 @@ import difflib import os from PyQt6.QtCore import Qt, pyqtSignal -from PyQt6.QtGui import QColor, QFontDatabase +from PyQt6.QtGui import QColor, QFontDatabase, QKeySequence, QShortcut from PyQt6.QtWidgets import (QCheckBox, QDialog, QHBoxLayout, QLabel, QLineEdit, QListWidget, QListWidgetItem, QMessageBox, QPlainTextEdit, QPushButton, QSplitter, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget) @@ -81,10 +81,14 @@ class HintsTab(QWidget): self.no_dl.setToolTip('Write DOWNLOAD="no": slackrepo uses the source already in its cache') bar = QHBoxLayout() bar.addWidget(self.status) - for label, on in (("Select visible", True), ("Clear", False)): - b = QPushButton(label) + self.keys = [] + for label, on, key in (("Select visible", True, "Ctrl+A"), ("Clear", False, "Ctrl+Shift+A")): + b = QPushButton(label, toolTip=key) b.clicked.connect(lambda _c, on=on: self.check_rows(on)) bar.addWidget(b) + # in the search field Ctrl+A still selects its text: QLineEdit overrides it + self.keys.append(QShortcut(QKeySequence(key), self, lambda on=on: self.check_rows(on), + context=Qt.ShortcutContext.WidgetWithChildrenShortcut)) bar.addStretch() for w in (self.check_btn, self.update_btn, self.no_dl): bar.addWidget(w) diff --git a/sb_builder/packages.py b/sb_builder/packages.py index 146db51..3ccbf40 100644 --- a/sb_builder/packages.py +++ b/sb_builder/packages.py @@ -19,7 +19,7 @@ import html from PyQt6.QtCore import QAbstractTableModel, QModelIndex, QSortFilterProxyModel, Qt, pyqtSignal -from PyQt6.QtGui import QColor +from PyQt6.QtGui import QColor, QKeySequence, QShortcut from PyQt6.QtWidgets import (QCheckBox, QDialog, QDialogButtonBox, QFormLayout, QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPushButton, QScrollArea, QSplitter, QTableView, QVBoxLayout, QWidget) @@ -271,10 +271,15 @@ class PackagesTab(QWidget): self.count = QLabel() bar = QHBoxLayout() bar.addWidget(self.count) - for label, slot in (("Select visible", self.select_visible), ("Clear", self.clear)): - b = QPushButton(label) + self.keys = [] + for label, slot, key in (("Select visible", self.select_visible, "Ctrl+A"), + ("Clear", self.clear, "Ctrl+Shift+A")): + b = QPushButton(label, toolTip=key) b.clicked.connect(slot) bar.addWidget(b) + # in the search field Ctrl+A still selects its text: QLineEdit overrides it + self.keys.append(QShortcut(QKeySequence(key), self, slot, + context=Qt.ShortcutContext.WidgetWithChildrenShortcut)) bar.addStretch() for action in ("build", "update", "rebuild", "remove"): b = QPushButton(action.capitalize()) diff --git a/tests/test_gui.py b/tests/test_gui.py index 69f3a69..891584b 100644 --- a/tests/test_gui.py +++ b/tests/test_gui.py @@ -402,6 +402,11 @@ class SmokeTest(unittest.TestCase): tab.table.setCurrentIndex(tab.proxy.index(1, 1)) self.assertIn("x", tab.detail.text()) tab.act("update") + select, clear = tab.keys + select.activated.emit() + self.assertEqual(len(tab.model.checked), 4) + clear.activated.emit() + self.assertEqual(tab.model.checked, set()) tab.model.checked.update({"nuclei", "curl"}) tab.act("build") tab.update_all() @@ -475,9 +480,11 @@ class SmokeTest(unittest.TestCase): tab.chips["current"].setChecked(True) visible = [tab.table.item(i, 1).text() for i in range(3) if not tab.table.isRowHidden(i)] self.assertEqual(visible, ["curl"]) - tab.check_rows(True) # visible only: curl, under the "current" chip + select, clear = tab.keys + self.assertEqual((select.key().toString(), clear.key().toString()), ("Ctrl+A", "Ctrl+Shift+A")) + select.activated.emit() # visible only: curl, under the "current" chip self.assertEqual(sorted(tab.checked()), ["curl", "nuclei"]) - tab.check_rows(False) + clear.activated.emit() self.assertEqual(tab.checked(), []) tab.chips["current"].setChecked(False) tab.check_rows(True) -- cgit v1.2.3