aboutsummaryrefslogtreecommitdiffstats
path: root/sb_builder/hints_tab.py
diff options
context:
space:
mode:
Diffstat (limited to 'sb_builder/hints_tab.py')
-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()