aboutsummaryrefslogtreecommitdiffstats
path: root/sb_builder
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-20 12:52:16 +0200
committerDanilo M. <danix@danix.xyz>2026-10-20 12:52:16 +0200
commit81604635b5a15ce36d14c04931ace058552ee2f3 (patch)
treea4daa1626da006ba50eb205e096adae603407066 /sb_builder
parentc7acbfc7d9146a4440f45f3efd4246935c2ffd19 (diff)
downloadsb-builder-81604635b5a15ce36d14c04931ace058552ee2f3.tar.gz
sb-builder-81604635b5a15ce36d14c04931ace058552ee2f3.zip
Hints: Phantom deps dialog
The list with Add and Remove, suggestions (required names no package of the tree has, with who needs them) to tick and add, and Apply to hints, which starts fix-current; its end opens the diff dialog with Revert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'sb_builder')
-rw-r--r--sb_builder/hints_tab.py117
1 files changed, 112 insertions, 5 deletions
diff --git a/sb_builder/hints_tab.py b/sb_builder/hints_tab.py
index fbf8a70..ca16354 100644
--- a/sb_builder/hints_tab.py
+++ b/sb_builder/hints_tab.py
@@ -21,9 +21,9 @@ import os
from PyQt6.QtCore import Qt, pyqtSignal
from PyQt6.QtGui import QColor, QFontDatabase, QKeySequence, QShortcut, QSyntaxHighlighter
-from PyQt6.QtWidgets import (QDialog, QHBoxLayout, QLabel, QListWidget, QListWidgetItem,
- QMessageBox, QPlainTextEdit, QPushButton, QSplitter, QTableWidget,
- QTableWidgetItem, QVBoxLayout, QWidget)
+from PyQt6.QtWidgets import (QAbstractItemView, QDialog, QHBoxLayout, QLabel, QLineEdit,
+ QListWidget, QListWidgetItem, QMessageBox, QPlainTextEdit, QPushButton,
+ QSplitter, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget)
from . import upstream
from .dashboard import STATUS
@@ -34,7 +34,7 @@ STATES = ("outdated", "current", "no stanza", "not checked", "nvchecker error")
STATE_COLOR = {"outdated": STATUS["aborted"], "current": STATUS["ok"],
"nvchecker error": STATUS["failed"]}
COLUMNS = ("", "package", "hint", ".info", "upstream", "state")
-HINT_JOBS = ("hint-update", "hint-new")
+HINT_JOBS = ("hint-update", "hint-new", "fix-current")
class HintsTab(QWidget):
@@ -78,7 +78,10 @@ class HintsTab(QWidget):
self.act_update = action(self, "Update selected", "document-save", SP.SP_DialogSaveButton,
self.update_selected)
self.act_delete = action(self, "Delete hint", "edit-delete", SP.SP_TrashIcon, self.delete)
- self.actions = [self.act_check, self.act_update, self.act_delete]
+ self.actions = [self.act_check, self.act_update, self.act_delete,
+ action(self, "Phantom deps…", "view-list-details", SP.SP_FileDialogListView,
+ self.phantom)]
+ self.phantom_dialog = None
self.no_dl = action(self, "No download", "network-offline", SP.SP_DriveNetIcon, checkable=True)
self.no_dl.setToolTip('Update selected writes DOWNLOAD="no": slackrepo uses the source '
"already in its cache")
@@ -212,6 +215,14 @@ class HintsTab(QWidget):
self.start_requested.emit(["hint-update", *self.pairs()]
+ (["--no-dl"] if self.no_dl.isChecked() else []))
+ def phantom(self):
+ if self.phantom_dialog is None:
+ self.phantom_dialog = d = PhantomDialog(self.remote, self)
+ d.apply_requested.connect(lambda: self.start_requested.emit(["fix-current"]))
+ d.finished.connect(lambda _r: setattr(self, "phantom_dialog", None))
+ d.show()
+ self.phantom_dialog.raise_()
+
def confirm(self, title, text):
return QMessageBox.question(self, title, text) == QMessageBox.StandardButton.Yes
@@ -332,3 +343,99 @@ class HintResultDialog(QDialog):
if pkgs:
self.build_requested.emit(pkgs)
self.accept()
+
+
+class PhantomDialog(QDialog):
+ """The -current phantom deps: the list, suggestions from the tree, Apply = fix-current."""
+
+ apply_requested = pyqtSignal()
+
+ def __init__(self, remote, parent=None):
+ super().__init__(parent)
+ self.remote = remote
+ self.setWindowTitle("Phantom deps: shipped by -current, DELREQUIREd from SBo packages")
+ self.resize(900, 600)
+ self.deps = QListWidget(selectionMode=QAbstractItemView.SelectionMode.ExtendedSelection)
+ self.name = QLineEdit(placeholderText="package name")
+ self.name.returnPressed.connect(self.add_name)
+ add = QPushButton("Add")
+ add.clicked.connect(self.add_name)
+ remove = QPushButton("Remove")
+ remove.clicked.connect(self.remove_selected)
+ self.suggestions = QListWidget()
+ self.suggestions.itemClicked.connect(lambda item: item.setCheckState(
+ Qt.CheckState.Unchecked if item.checkState() == Qt.CheckState.Checked else Qt.CheckState.Checked))
+ add_ticked = QPushButton("Add ticked")
+ add_ticked.clicked.connect(self.add_ticked)
+ apply = QPushButton("Apply to hints", default=True)
+ apply.setToolTip("Start fix-current: the listed deps go into DELREQUIRES of the "
+ "packages that require them")
+ apply.clicked.connect(self.apply)
+ close = QPushButton("Close")
+ close.clicked.connect(self.accept)
+
+ left = QVBoxLayout()
+ left.addWidget(QLabel("<b>Listed</b>"))
+ left.addWidget(self.deps)
+ left.addWidget(self.name)
+ row = QHBoxLayout()
+ row.addWidget(add)
+ row.addWidget(remove)
+ left.addLayout(row)
+ right = QVBoxLayout()
+ right.addWidget(QLabel("<b>Suggested</b>: required, but no package of the tree has them"))
+ right.addWidget(self.suggestions)
+ right.addWidget(add_ticked)
+ lists = QHBoxLayout()
+ lists.addLayout(left, 1)
+ lists.addLayout(right, 2)
+ bar = QHBoxLayout()
+ bar.addStretch()
+ bar.addWidget(close)
+ bar.addWidget(apply)
+ layout = QVBoxLayout(self)
+ layout.addLayout(lists, 1)
+ layout.addLayout(bar)
+ self.reload()
+
+ def reload(self):
+ self.remote.call(self._loaded, "phantom-list")
+
+ def _loaded(self, data, err):
+ if err:
+ QMessageBox.warning(self, "Phantom deps", err)
+ return
+ self.deps.clear()
+ self.deps.addItems(data["deps"])
+ self.suggestions.clear()
+ for s in data["suggestions"]:
+ needed = s["needed_by"]
+ more = f" (+{len(needed) - 5})" if len(needed) > 5 else ""
+ item = QListWidgetItem(f"{s['name']} needed by {', '.join(needed[:5])}{more}")
+ item.setData(Qt.ItemDataRole.UserRole, s["name"])
+ item.setToolTip(", ".join(needed))
+ item.setFlags(Qt.ItemFlag.ItemIsEnabled) # the click handler toggles: no double toggle
+ item.setCheckState(Qt.CheckState.Unchecked)
+ self.suggestions.addItem(item)
+
+ def _change(self, cmd, names):
+ if names:
+ self.remote.call(lambda _d, err: self._loaded(None, err) if err else self.reload(),
+ cmd, *names)
+
+ def add_name(self):
+ name = self.name.text().strip()
+ self.name.clear()
+ self._change("phantom-add", [name] if name else [])
+
+ def add_ticked(self):
+ self._change("phantom-add", [
+ self.suggestions.item(i).data(Qt.ItemDataRole.UserRole) for i in range(self.suggestions.count())
+ if self.suggestions.item(i).checkState() == Qt.CheckState.Checked])
+
+ def remove_selected(self):
+ self._change("phantom-remove", [i.text() for i in self.deps.selectedItems()])
+
+ def apply(self):
+ self.apply_requested.emit()
+ self.accept()