# Base classes for Spokes # # Copyright (C) 2011 Red Hat, Inc. # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions of # the GNU General Public License v.2, or (at your option) any later version. # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY expressed or implied, including the implied warranties of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. You should have received a copy of the # GNU General Public License along with this program; if not, write to the # Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. Any Red Hat trademarks that are incorporated in the # source code or documentation are not subject to the GNU General Public # License and may only be used or replicated with the express permission of # Red Hat, Inc. # # Red Hat Author(s): Chris Lumens # Martin Sivak from pyanaconda.ui import common from pyanaconda.ui.common import collect from pyanaconda.ui.gui import GUIObject import os.path __all__ = ["StandaloneSpoke", "NormalSpoke", "PersonalizationSpoke", "collect_spokes"] class Spoke(GUIObject): def __init__(self, data): GUIObject.__init__(self, data) def apply(self): """Apply the selections made on this Spoke to the object's preset data object. This method must be provided by every subclass. """ raise NotImplementedError @property def completed(self): """Has this spoke been visited and completed? If not, a special warning icon will be shown on the Hub beside the spoke, and a highlighted message will be shown at the bottom of the Hub. Installation will not be allowed to proceed until all spokes are complete. """ return False def execute(self): """Cause the data object to take effect on the target system. This will usually be as simple as calling one or more of the execute methods on the data object. This method does not need to be provided by all subclasses. This method will be called in two different places: (1) Immediately after initialize on kickstart installs. (2) Immediately after apply in all cases. """ pass class StandaloneSpoke(Spoke, common.StandaloneSpoke): def __init__(self, data, storage, payload, instclass): Spoke.__init__(self, data) common.StandaloneSpoke.__init__(self, data, storage, payload, instclass) def _on_continue_clicked(self, cb): self.apply() cb() def register_event_cb(self, event, cb): if event == "continue": self.window.connect("continue-clicked", lambda *args: self._on_continue_clicked(cb)) elif event == "quit": self.window.connect("quit-clicked", lambda *args: cb()) class NormalSpoke(Spoke, common.NormalSpoke): def __init__(self, data, storage, payload, instclass): Spoke.__init__(self, data) common.NormalSpoke.__init__(self, data, storage, payload, instclass) def on_back_clicked(self, window): from gi.repository import Gtk # Look for failed checks failed_check = next(self.failed_checks, None) if failed_check: # Set the focus to the first failed check and stay in the spoke failed_check.editable.grab_focus() return self.window.hide() Gtk.main_quit() class PersonalizationSpoke(Spoke, common.PersonalizationSpoke): def __init__(self, data, storage, payload, instclass): Spoke.__init__(self, data) common.PersonalizationSpoke.__init__(self, data, storage, payload, instclass) def collect_spokes(mask_paths, category): """Return a list of all spoke subclasses that should appear for a given category. Look for them in files imported as module_path % basename(f) :param mask_paths: list of mask, path tuples to search for classes :type mask_paths: list of (mask, path) :return: list of Spoke classes belonging to category :rtype: list of Spoke classes """ spokes = [] for mask, path in mask_paths: spokes.extend(collect(mask, path, lambda obj: hasattr(obj, "category") and obj.category != None and obj.category.__name__ == category)) return spokes