|
| 1 | +# |
| 2 | +# Copyright (C) 2011-2013 Red Hat, Inc. |
| 3 | +# |
| 4 | +# This copyrighted material is made available to anyone wishing to use, |
| 5 | +# modify, copy, or redistribute it subject to the terms and conditions of |
| 6 | +# the GNU General Public License v.2, or (at your option) any later version. |
| 7 | +# This program is distributed in the hope that it will be useful, but WITHOUT |
| 8 | +# ANY WARRANTY expressed or implied, including the implied warranties of |
| 9 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
| 10 | +# Public License for more details. You should have received a copy of the |
| 11 | +# GNU General Public License along with this program; if not, write to the |
| 12 | +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 13 | +# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the |
| 14 | +# source code or documentation are not subject to the GNU General Public |
| 15 | +# License and may only be used or replicated with the express permission of |
| 16 | +# Red Hat, Inc. |
| 17 | +import gi |
| 18 | +gi.require_version('Gtk', '3.0') |
| 19 | +from gi.repository import Gtk |
| 20 | + |
| 21 | +from initial_setup import InitialSetupTask |
| 22 | +from initial_setup.gui.hubs import InitialSetupMainHub |
| 23 | +from pyanaconda.anaconda_loggers import get_module_logger |
| 24 | +from pyanaconda.core.i18n import _, C_ |
| 25 | +from pyanaconda.modules.common.constants.services import USERS |
| 26 | +from pyanaconda.product import productName |
| 27 | +from pyanaconda.flags import flags |
| 28 | +from pyanaconda.core import util |
| 29 | +from pyanaconda.core.configuration.anaconda import conf |
| 30 | +from pyanaconda.core.constants import IPMI_FINISHED |
| 31 | +from pyanaconda.ui.common import FirstbootOnlySpokeMixIn |
| 32 | +from pykickstart.constants import KS_SHUTDOWN, KS_REBOOT |
| 33 | +from pyanaconda.ui.gui.spokes import StandaloneSpoke |
| 34 | +from pyanaconda.ui.gui.utils import gtk_call_once |
| 35 | + |
| 36 | +log = get_module_logger(__name__) |
| 37 | + |
| 38 | +__all__ = ["ProgressSpoke"] |
| 39 | + |
| 40 | + |
| 41 | +class ProgressSpoke(FirstbootOnlySpokeMixIn, StandaloneSpoke): |
| 42 | + """ |
| 43 | + .. inheritance-diagram:: ProgressSpoke |
| 44 | + :parts: 3 |
| 45 | + """ |
| 46 | + |
| 47 | + builderObjects = ["progressWindow"] |
| 48 | + mainWidgetName = "progressWindow" |
| 49 | + uiFile = "setup_progress.glade" |
| 50 | + postForHub = InitialSetupMainHub |
| 51 | + |
| 52 | + @staticmethod |
| 53 | + def get_screen_id(): |
| 54 | + """Return a unique id of this UI screen.""" |
| 55 | + return "installation-progress" |
| 56 | + |
| 57 | + def __init__(self, data, storage, payload): |
| 58 | + super().__init__(data, storage, payload) |
| 59 | + self._progressBar = self.builder.get_object("progressBar") |
| 60 | + self._progressLabel = self.builder.get_object("progressLabel") |
| 61 | + self._progressNotebook = self.builder.get_object("progressNotebook") |
| 62 | + self._spinner = self.builder.get_object("progressSpinner") |
| 63 | + self._task = None |
| 64 | + |
| 65 | + # Record if groups, users or root password has been set before Initial Setup |
| 66 | + # has been started, so that we don't trample over existing configuration. |
| 67 | + log.info("collecting initial state") |
| 68 | + users_proxy = USERS.get_proxy() |
| 69 | + self._groups_already_configured = bool(users_proxy.Groups) |
| 70 | + self._users_already_configured = bool(users_proxy.Users) |
| 71 | + self._root_password_already_configured = users_proxy.IsRootPasswordSet |
| 72 | + |
| 73 | + @property |
| 74 | + def completed(self): |
| 75 | + """This spoke is never completed, initially.""" |
| 76 | + return False |
| 77 | + |
| 78 | + def apply(self): |
| 79 | + """There is nothing to apply.""" |
| 80 | + pass |
| 81 | + |
| 82 | + def _on_installation_done(self): |
| 83 | + log.debug("The initial setup has finished.") |
| 84 | + |
| 85 | + # Stop the spinner. |
| 86 | + gtk_call_once(self._spinner.stop) |
| 87 | + gtk_call_once(self._spinner.hide) |
| 88 | + |
| 89 | + # Finish the installation task. Re-raise tracebacks if any. |
| 90 | + try: |
| 91 | + self._task.finish() |
| 92 | + except Exception as e: |
| 93 | + log.exception("Initial setup failed") |
| 94 | + self.showErrorMessageHelper(str(e)) |
| 95 | + |
| 96 | + util.ipmi_report(IPMI_FINISHED) |
| 97 | + |
| 98 | + if conf.license.eula: |
| 99 | + self.set_warning(_("Use of this product is subject to the license agreement " |
| 100 | + "found at %s") % conf.license.eula) |
| 101 | + self.window.show_all() |
| 102 | + |
| 103 | + # Show the reboot message. |
| 104 | + self._progressNotebook.set_current_page(1) |
| 105 | + |
| 106 | + # Enable the continue button. |
| 107 | + self.window.set_may_continue(True) |
| 108 | + |
| 109 | + # Hide the quit button. |
| 110 | + quit_button = self.window.get_quit_button() |
| 111 | + quit_button.hide() |
| 112 | + |
| 113 | + # automatically close; if there was an error, showErrorMessageHelper |
| 114 | + # already waited for the user to click ok |
| 115 | + self.window.emit("continue-clicked") |
| 116 | + |
| 117 | + def initialize(self): |
| 118 | + super().initialize() |
| 119 | + # Disable the continue button. |
| 120 | + self.window.set_may_continue(False) |
| 121 | + |
| 122 | + # Set the label of the continue button. |
| 123 | + continue_label = C_("GUI|Progress", "_Finish Installation") |
| 124 | + |
| 125 | + continue_button = self.window.get_continue_button() |
| 126 | + continue_button.set_label(continue_label) |
| 127 | + |
| 128 | + # Set the reboot label. |
| 129 | + continue_text = _( |
| 130 | + "%s is now successfully installed and ready for you to use!\n" |
| 131 | + "Go ahead and quit the application to start using it!" |
| 132 | + ) % productName |
| 133 | + |
| 134 | + label = self.builder.get_object("rebootLabel") |
| 135 | + label.set_text(continue_text) |
| 136 | + |
| 137 | + # Don't show the reboot message. |
| 138 | + self._progressNotebook.set_current_page(0) |
| 139 | + |
| 140 | + def refresh(self): |
| 141 | + from pyanaconda.installation import RunInstallationTask |
| 142 | + super().refresh() |
| 143 | + |
| 144 | + # Initialize the progress bar. |
| 145 | + gtk_call_once(self._progressBar.set_fraction, 0.0) |
| 146 | + |
| 147 | + # Start the installation task. |
| 148 | + self._task = InitialSetupTask( |
| 149 | + groups_already_configured=self._groups_already_configured, |
| 150 | + users_already_configured=self._users_already_configured, |
| 151 | + root_password_already_configured=self._root_password_already_configured, |
| 152 | + ) |
| 153 | + self._task.progress_changed_signal.connect( |
| 154 | + self._on_progress_changed |
| 155 | + ) |
| 156 | + self._task.stopped_signal.connect( |
| 157 | + self._on_installation_done |
| 158 | + ) |
| 159 | + self._task.start() |
| 160 | + |
| 161 | + # Start the spinner. |
| 162 | + gtk_call_once(self._spinner.start) |
| 163 | + |
| 164 | + log.debug("The installation has started.") |
| 165 | + |
| 166 | + def showErrorMessageHelper(self, text): |
| 167 | + dlg = Gtk.MessageDialog(title="Error", message_type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK, text=text) |
| 168 | + dlg.set_position(Gtk.WindowPosition.CENTER) |
| 169 | + dlg.set_modal(True) |
| 170 | + dlg.set_transient_for(self.main_window) |
| 171 | + dlg.run() |
| 172 | + dlg.destroy() |
| 173 | + |
| 174 | + def _on_progress_changed(self, step, message): |
| 175 | + """Handle a new progress report.""" |
| 176 | + if message: |
| 177 | + gtk_call_once(self._progressLabel.set_text, message) |
| 178 | + |
| 179 | + if self._task.steps > 0: |
| 180 | + gtk_call_once(self._progressBar.set_fraction, step/self._task.steps) |
0 commit comments