From d6ec13eb78eac2673b3ff707af18928b0c962db6 Mon Sep 17 00:00:00 2001 From: Mike Hendricks Date: Wed, 3 Jul 2024 11:34:19 -0700 Subject: [PATCH] WIP: DistroPicker now updates aliases on distro check --- hab_gui/widgets/distro_picker.py | 62 +++++++++++++++++++++++++++++--- hab_gui/widgets/name_picker.py | 23 ++++++------ 2 files changed, 69 insertions(+), 16 deletions(-) diff --git a/hab_gui/widgets/distro_picker.py b/hab_gui/widgets/distro_picker.py index 1f14e8f..3a2373e 100644 --- a/hab_gui/widgets/distro_picker.py +++ b/hab_gui/widgets/distro_picker.py @@ -1,21 +1,73 @@ +from hab.solvers import Solver from hab.utils import NotSet +from Qt.QtCore import QTimer +from .. import utils from .name_picker import NamePicker class DistroPicker(NamePicker): - """A widget for picking from a list of optional distros.""" + """A widget for picking from a list of optional distros. + + This displays the `optional_distros` config setting. Any distros checked use + `hab.Resolver.forced_requirements` to load those distros. See the cli argument + `--requirement` for more info. + """ pref_name = "distro_picker" def __init__(self, settings, title="Options", label="Distro", parent=None): super().__init__(settings, title=title, label=label, parent=parent) - self.settings.uri_changed.connect(self.refresh) + # This widget needs to update the hab resolver before other widgets + # are updated. This signal is used to update forced_requirements. + self.settings.uri_changing.connect(self.refresh) + + def item_changed(self, item, column): + """Called when a item is modified, saves the user prefs when a checked + state is updated and updates the displayed aliases.""" + super().item_changed(item, column) + # Ensure the UI is updated with the new forced_requirements + self.update_requirements() + QTimer.singleShot(0, self.uri_changed) + + def reset_to_default(self): + """Reset the checked state of names to the default values, clearing + saved user_prefs for the current URI. + """ + super().reset_to_default() + # Refresh the alias button widget + self.update_requirements() + self.uri_changed() + + def update_requirements(self): + # Ensure the UI is updated with the new forced_requirements + selected = self.selected() + forced_requirements = Solver.simplify_requirements(list(selected)) + + # Preserve any requirements passed via the cli. + cli_reqs = self.settings.resolver.__forced_requirements__ + if cli_reqs: + # If the same distro is specified, the GUI's requirement should win. + forced_requirements = dict(cli_reqs, **forced_requirements) - def refresh(self): + self.settings.resolver.forced_requirements = forced_requirements + + def uri_changed(self): + """Work function that forces the gui to update its aliases.""" + + # The refresh method is called when this signal is emitted, don't + # double process it by blocking signals. + with utils.block_signals([self.name_tree]): + self.settings.uri_changed.emit(self.settings.uri) + + def refresh(self, uri): resolver = self.settings.resolver - cfg = resolver.resolve(self.settings.uri) + cfg = resolver.resolve(uri) optional = cfg.optional_distros if optional is NotSet: optional = {} - self.set_names(optional) + self.set_names(optional, uri=uri) + + # Ensure the alias_buttons widget has the updated requirements before + # it refreshes from the `uri_changed` signal emited later. + self.update_requirements() diff --git a/hab_gui/widgets/name_picker.py b/hab_gui/widgets/name_picker.py index dd58801..aacbe66 100644 --- a/hab_gui/widgets/name_picker.py +++ b/hab_gui/widgets/name_picker.py @@ -1,7 +1,7 @@ from hab.parsers import HabBase from Qt import QtCore, QtWidgets -import hab_gui.utils +from .. import utils class NamePicker(QtWidgets.QGroupBox): @@ -22,12 +22,10 @@ def __init__(self, settings, title="Options", label="Distro", parent=None): super().__init__(parent=parent) self.settings = settings self.default_selection = set() - hab_gui.utils.load_ui(__file__, self) + utils.load_ui(__file__, self) self.setTitle(title) self.name_tree.setHeaderLabel(label) - self.reset_to_default_btn.setIcon( - hab_gui.utils.Paths.icon("arrow-left-top-bold") - ) + self.reset_to_default_btn.setIcon(utils.Paths.icon("arrow-left-top-bold")) self.name_tree.itemChanged.connect(self.item_changed) self.reset_to_default_btn.released.connect(self.reset_to_default) @@ -52,11 +50,11 @@ def names(self): ret[item.text(0)] = [item.text(1), checked] return ret - def set_names(self, names): + def set_names(self, names, uri=None): self.name_tree.clear() # Reset the default selection self.default_selection = set() - with hab_gui.utils.block_signals([self.name_tree]): + with utils.block_signals([self.name_tree]): for name, settings in names.items(): item = QtWidgets.QTreeWidgetItem(self.name_tree, [name, settings[0]]) item.setToolTip(1, settings[0]) @@ -66,7 +64,7 @@ def set_names(self, names): item.setCheckState(0, QtCore.Qt.Unchecked) self.name_tree.resizeColumnToContents(0) - user_selection = self.user_selection() + user_selection = self.user_selection(uri) if user_selection is None: self.set_selected(self.default_selection) self.reset_to_default_btn.setDisabled(True) @@ -92,7 +90,7 @@ def selected(self): def set_selected(self, selected): """Update the checked state to just these names.""" - with hab_gui.utils.block_signals([self.name_tree]): + with utils.block_signals([self.name_tree]): for index in range(self.name_tree.topLevelItemCount()): item = self.name_tree.topLevelItem(index) name = item.text(0) @@ -108,14 +106,17 @@ def standardize_uri(self, uri): all but the top level item.""" return uri.split(HabBase.separator)[0] - def user_selection(self): + def user_selection(self, uri): """Returns the names selected for the current URI saved in user_prefs as a dict or None if user_prefs are disabled. """ if not self.pref_name: return None - uri = self.standardize_uri(self.settings.uri) + if uri is None: + uri = self.settings.uri + + uri = self.standardize_uri(uri) return self.settings.user_pref(self.pref_name, {}).get(uri, None) def save_user_selection(self, reset=False):