diff options
author | Martin Sivak <msivak@redhat.com> | 2012-08-06 13:43:32 +0200 |
---|---|---|
committer | Martin Sivak <msivak@redhat.com> | 2012-08-06 13:43:32 +0200 |
commit | a518f8919488710842dc50d6e28f1d9bea5a186d (patch) | |
tree | ef1d8e64aef6cf133d4f92177eea3ed6644b49f1 /pyanaconda/ui/gui | |
parent | 72c797294e5d70a221cab91d3d97ce805ad4b851 (diff) | |
parent | 86dd8ff76ba9a6fd10a7325df2c0691339d7fb76 (diff) | |
download | anaconda-a518f8919488710842dc50d6e28f1d9bea5a186d.tar.gz anaconda-a518f8919488710842dc50d6e28f1d9bea5a186d.tar.xz anaconda-a518f8919488710842dc50d6e28f1d9bea5a186d.zip |
Merge master into newtui
Diffstat (limited to 'pyanaconda/ui/gui')
34 files changed, 287 insertions, 52 deletions
diff --git a/pyanaconda/ui/gui/Makefile.am b/pyanaconda/ui/gui/Makefile.am index 7a3958cc3..51d43a8da 100644 --- a/pyanaconda/ui/gui/Makefile.am +++ b/pyanaconda/ui/gui/Makefile.am @@ -24,4 +24,4 @@ guidir = $(pkgpyexecdir)/ui/gui gui_PYTHON = *.py uidir = $(datadir)/$(PACKAGE_NAME)/ui/ -dist_ui_DATA = *.ui +dist_ui_DATA = *.glade diff --git a/pyanaconda/ui/gui/TODO b/pyanaconda/ui/gui/TODO index 1eccc6b07..f4170bf24 100644 --- a/pyanaconda/ui/gui/TODO +++ b/pyanaconda/ui/gui/TODO @@ -20,14 +20,14 @@ Fedora 18 s-c-ks into an anaconda wrapper first, though. - Wall of anaconda needs to be taken into account. - Why does the first hub jump left a little bit the first time you use the keyboard to navigate? -- We need a way for users to look at the list of problems resulting from the - software dependency check and the storage sanity check - In custom storage, it'd be nice to be able to say something like "Use this previous installation as the starting storage configuration for the system I'm installing now" - In custom storage, it'd be really nice to be able to drag entries from old roots into the "New Fedora" root as a way of saying "Use this device with the same mountpoint in the new system." +- We're probably going to need to update the auto-generated names of container + devices any time the user updates the hostname. Beyond ====== diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py index dbd0a28b6..5ebb53d15 100644 --- a/pyanaconda/ui/gui/__init__.py +++ b/pyanaconda/ui/gui/__init__.py @@ -19,6 +19,7 @@ # Red Hat Author(s): Chris Lumens <clumens@redhat.com> # import importlib, inspect, os, sys +import meh.ui.gui from pyanaconda.ui import UserInterface, common, collect from pyanaconda.ui.gui.utils import enlightbox @@ -124,13 +125,23 @@ class GraphicalUserInterface(UserInterface): return bool(rc) + def mainExceptionWindow(self, text, exn_file, *args, **kwargs): + meh_intf = meh.ui.gui.GraphicalIntf() + + return meh_intf.mainExceptionWindow(text, exn_file) + + + def saveExceptionWindow(self, account_manager, signature, *args, **kwargs): + meh_intf = meh.ui.gui.GraphicalIntf() + meh_intf.saveExceptionWindow(account_manager, signature) + ### ### SIGNAL HANDLING METHODS ### def _on_continue_clicked(self): - # If we're on the last screen, clicking Continue is the same as clicking Quit. + # If we're on the last screen, clicking Continue quits. if len(self._actions) == 1: - self._on_quit_clicked() + sys.exit(0) return # If the current action wants us to jump to an arbitrary point ahead, @@ -246,6 +257,7 @@ class GUIObject(common.UIObject): self._origStrings = {} self.skipTo = None + self.applyOnSkip = False from gi.repository import Gtk @@ -341,7 +353,7 @@ class GUIObject(common.UIObject): class QuitDialog(GUIObject): builderObjects = ["quitDialog"] mainWidgetName = "quitDialog" - uiFile = "main.ui" + uiFile = "main.glade" def run(self): rc = self.window.run() diff --git a/pyanaconda/ui/gui/hubs/Makefile.am b/pyanaconda/ui/gui/hubs/Makefile.am index d1dad0a50..ae520a6e3 100644 --- a/pyanaconda/ui/gui/hubs/Makefile.am +++ b/pyanaconda/ui/gui/hubs/Makefile.am @@ -22,4 +22,4 @@ hubsdir = $(pkgpyexecdir)/ui/gui/hubs hubs_PYTHON = *.py uidir = $(datadir)/$(PACKAGE_NAME)/ui/hubs -dist_ui_DATA = *.ui +dist_ui_DATA = *.glade diff --git a/pyanaconda/ui/gui/hubs/__init__.py b/pyanaconda/ui/gui/hubs/__init__.py index 8b8ee099a..f5e211f3c 100644 --- a/pyanaconda/ui/gui/hubs/__init__.py +++ b/pyanaconda/ui/gui/hubs/__init__.py @@ -101,8 +101,10 @@ class Hub(GUIObject, common.Hub): # prevent the user from switching away. It's up to the spoke's back # button handler to kill its own layer of main loop. Gtk.main() - action.apply() - action.execute() + + if not action.skipTo or (action.skipTo and action.applyOnSkip): + action.apply() + action.execute() def _createBox(self): from gi.repository import Gtk, AnacondaWidgets diff --git a/pyanaconda/ui/gui/hubs/progress.ui b/pyanaconda/ui/gui/hubs/progress.glade index 1eb32c97e..1eb32c97e 100644 --- a/pyanaconda/ui/gui/hubs/progress.ui +++ b/pyanaconda/ui/gui/hubs/progress.glade diff --git a/pyanaconda/ui/gui/hubs/progress.py b/pyanaconda/ui/gui/hubs/progress.py index 2eb1b75de..b1c1e9314 100644 --- a/pyanaconda/ui/gui/hubs/progress.py +++ b/pyanaconda/ui/gui/hubs/progress.py @@ -31,6 +31,8 @@ import os from pyanaconda.localeinfo import expandLangs from pyanaconda.product import productName +from pyanaconda.flags import flags +from pykickstart.constants import KS_WAIT, KS_SHUTDOWN, KS_REBOOT from pyanaconda.ui.gui.hubs import Hub from pyanaconda.ui.gui.utils import gdk_threaded @@ -40,7 +42,7 @@ __all__ = ["ProgressHub"] class ProgressHub(Hub): builderObjects = ["progressWindow"] mainWidgetName = "progressWindow" - uiFile = "hubs/progress.ui" + uiFile = "hubs/progress.glade" def __init__(self, data, storage, payload, instclass): Hub.__init__(self, data, storage, payload, instclass) @@ -81,6 +83,11 @@ class ProgressHub(Hub): GLib.source_remove(self._rnotes_id) self._progressNotebook.next_page() + + # kickstart install, continue automatically if reboot or shutdown selected + if flags.automatedInstall and self.data.reboot.action in [KS_REBOOT, KS_SHUTDOWN]: + self.continueButton.emit("clicked") + return False q.task_done() @@ -145,7 +152,7 @@ class ProgressHub(Hub): args=(self.storage, self.payload, self.data, self.instclass))) @property - def quitButton(self): + def continueButton(self): return self.builder.get_object("rebootButton") def _init_progress_bar(self, steps): diff --git a/pyanaconda/ui/gui/hubs/summary.ui b/pyanaconda/ui/gui/hubs/summary.glade index 25aa16564..25aa16564 100644 --- a/pyanaconda/ui/gui/hubs/summary.ui +++ b/pyanaconda/ui/gui/hubs/summary.glade diff --git a/pyanaconda/ui/gui/hubs/summary.py b/pyanaconda/ui/gui/hubs/summary.py index 4973ebe87..c867e496a 100644 --- a/pyanaconda/ui/gui/hubs/summary.py +++ b/pyanaconda/ui/gui/hubs/summary.py @@ -26,7 +26,7 @@ __all__ = ["SummaryHub"] class SummaryHub(Hub): builderObjects = ["summaryWindow"] mainWidgetName = "summaryWindow" - uiFile = "hubs/summary.ui" + uiFile = "hubs/summary.glade" # FIXME: I really hate this. diff --git a/pyanaconda/ui/gui/main.ui b/pyanaconda/ui/gui/main.glade index 2f773a48f..2f773a48f 100644 --- a/pyanaconda/ui/gui/main.ui +++ b/pyanaconda/ui/gui/main.glade diff --git a/pyanaconda/ui/gui/spokes/Makefile.am b/pyanaconda/ui/gui/spokes/Makefile.am index 4968a897d..352f4e4fb 100644 --- a/pyanaconda/ui/gui/spokes/Makefile.am +++ b/pyanaconda/ui/gui/spokes/Makefile.am @@ -24,4 +24,4 @@ spokesdir = $(pkgpyexecdir)/ui/gui/spokes spokes_PYTHON = *.py uidir = $(datadir)/$(PACKAGE_NAME)/ui/spokes -dist_ui_DATA = *.ui +dist_ui_DATA = *.glade diff --git a/pyanaconda/ui/gui/spokes/__init__.py b/pyanaconda/ui/gui/spokes/__init__.py index 192022ffa..61aea5cad 100644 --- a/pyanaconda/ui/gui/spokes/__init__.py +++ b/pyanaconda/ui/gui/spokes/__init__.py @@ -31,6 +31,33 @@ class Spoke(GUIObject, common.Spoke): GUIObject.__init__(self, data) common.Spoke.__init__(self, data, storage, payload, instclass) + 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 + def initialize(self): GUIObject.initialize(self) diff --git a/pyanaconda/ui/gui/spokes/custom.ui b/pyanaconda/ui/gui/spokes/custom.glade index 5f97efad1..5f97efad1 100644 --- a/pyanaconda/ui/gui/spokes/custom.ui +++ b/pyanaconda/ui/gui/spokes/custom.glade diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py index 5a44d4ae7..c76146a72 100644 --- a/pyanaconda/ui/gui/spokes/custom.py +++ b/pyanaconda/ui/gui/spokes/custom.py @@ -58,7 +58,7 @@ new_install_name = _("New %s %s Installation") % (productName, productVersion) class AddDialog(GUIObject): builderObjects = ["addDialog"] mainWidgetName = "addDialog" - uiFile = "spokes/custom.ui" + uiFile = "spokes/custom.glade" def __init__(self, *args, **kwargs): GUIObject.__init__(self, *args, **kwargs) @@ -88,7 +88,7 @@ class AddDialog(GUIObject): class ConfirmDeleteDialog(GUIObject): builderObjects = ["confirmDeleteDialog"] mainWidgetName = "confirmDeleteDialog" - uiFile = "spokes/custom.ui" + uiFile = "spokes/custom.glade" def on_delete_cancel_clicked(self, button, *args): self.window.destroy() @@ -115,7 +115,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker): "partitionStore", "addImage", "removeImage", "settingsImage"] mainWidgetName = "customStorageWindow" - uiFile = "spokes/custom.ui" + uiFile = "spokes/custom.glade" category = StorageCategory title = N_("MANUAL PARTITIONING") diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.ui b/pyanaconda/ui/gui/spokes/datetime_spoke.glade index cdf1cf5b5..cdf1cf5b5 100644 --- a/pyanaconda/ui/gui/spokes/datetime_spoke.ui +++ b/pyanaconda/ui/gui/spokes/datetime_spoke.glade diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.py b/pyanaconda/ui/gui/spokes/datetime_spoke.py index 944cdfc4b..0e2ca77a6 100644 --- a/pyanaconda/ui/gui/spokes/datetime_spoke.py +++ b/pyanaconda/ui/gui/spokes/datetime_spoke.py @@ -46,7 +46,7 @@ POOL_SERVERS_NOTE = _("Note: pool servers may not be available all the time") class NTPconfigDialog(GUIObject): builderObjects = ["ntpConfigDialog", "addImage", "serversStore"] mainWidgetName = "ntpConfigDialog" - uiFile = "spokes/datetime_spoke.ui" + uiFile = "spokes/datetime_spoke.glade" def __init__(self, *args): GUIObject.__init__(self, *args) @@ -244,7 +244,7 @@ class DatetimeSpoke(NormalSpoke): ] mainWidgetName = "datetimeWindow" - uiFile = "spokes/datetime_spoke.ui" + uiFile = "spokes/datetime_spoke.glade" category = LocalizationCategory diff --git a/pyanaconda/ui/gui/spokes/keyboard.ui b/pyanaconda/ui/gui/spokes/keyboard.glade index 1243e22fb..1243e22fb 100644 --- a/pyanaconda/ui/gui/spokes/keyboard.ui +++ b/pyanaconda/ui/gui/spokes/keyboard.glade diff --git a/pyanaconda/ui/gui/spokes/keyboard.py b/pyanaconda/ui/gui/spokes/keyboard.py index f0084b398..cbf340b91 100644 --- a/pyanaconda/ui/gui/spokes/keyboard.py +++ b/pyanaconda/ui/gui/spokes/keyboard.py @@ -42,7 +42,7 @@ class AddLayoutDialog(GUIObject): builderObjects = ["addLayoutDialog", "newLayoutStore", "newLayoutStoreFilter", "newLayoutStoreSort"] mainWidgetName = "addLayoutDialog" - uiFile = "spokes/keyboard.ui" + uiFile = "spokes/keyboard.glade" def __init__(self, *args): GUIObject.__init__(self, *args) @@ -140,7 +140,7 @@ class KeyboardSpoke(NormalSpoke): builderObjects = ["addedLayoutStore", "keyboardWindow", "addImage", "removeImage", "upImage", "downImage", "previewImage"] mainWidgetName = "keyboardWindow" - uiFile = "spokes/keyboard.ui" + uiFile = "spokes/keyboard.glade" category = LocalizationCategory diff --git a/pyanaconda/ui/gui/spokes/lib/Makefile.am b/pyanaconda/ui/gui/spokes/lib/Makefile.am index edf1be594..ecd597cbc 100644 --- a/pyanaconda/ui/gui/spokes/lib/Makefile.am +++ b/pyanaconda/ui/gui/spokes/lib/Makefile.am @@ -22,4 +22,4 @@ spokesdir = $(pkgpyexecdir)/ui/gui/spokes/lib spokes_PYTHON = *.py uidir = $(datadir)/$(PACKAGE_NAME)/ui/spokes/lib -dist_ui_DATA = *.ui +dist_ui_DATA = *.glade diff --git a/pyanaconda/ui/gui/spokes/lib/cart.ui b/pyanaconda/ui/gui/spokes/lib/cart.glade index 92fdfe53a..92fdfe53a 100644 --- a/pyanaconda/ui/gui/spokes/lib/cart.ui +++ b/pyanaconda/ui/gui/spokes/lib/cart.glade diff --git a/pyanaconda/ui/gui/spokes/lib/cart.py b/pyanaconda/ui/gui/spokes/lib/cart.py index dbbfc1d04..3e77a36f0 100644 --- a/pyanaconda/ui/gui/spokes/lib/cart.py +++ b/pyanaconda/ui/gui/spokes/lib/cart.py @@ -42,7 +42,7 @@ def size_str(mb): class SelectedDisksDialog(GUIObject): builderObjects = ["selected_disks_dialog", "disk_store"] mainWidgetName = "selected_disks_dialog" - uiFile = "spokes/lib/cart.ui" + uiFile = "spokes/lib/cart.glade" def initialize(self, disks, free, showRemove=True): for disk in disks: diff --git a/pyanaconda/ui/gui/spokes/lib/detailederror.glade b/pyanaconda/ui/gui/spokes/lib/detailederror.glade new file mode 100644 index 000000000..db9daf262 --- /dev/null +++ b/pyanaconda/ui/gui/spokes/lib/detailederror.glade @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <object class="GtkTextBuffer" id="detailedTextBuffer"/> + <object class="GtkDialog" id="detailedErrorDialog"> + <property name="can_focus">False</property> + <property name="border_width">5</property> + <property name="modal">True</property> + <property name="window_position">center</property> + <property name="type_hint">dialog</property> + <property name="decorated">False</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox2"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_bottom">18</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">The following software marked for installation has errors. This is likely caused by an error with +your installation source. You can attempt to remove these packages from your installation, +change your installation source, or quit the installer.</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="scrolledwindow1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTextView" id="detailedTextView"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="cursor_visible">False</property> + <property name="buffer">detailedTextBuffer</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area2"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="detailedCancelButton"> + <property name="label">gtk-cancel</property> + <property name="use_action_appearance">False</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="halign">start</property> + <property name="use_action_appearance">False</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + <property name="secondary">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">detailedCancelButton</action-widget> + </action-widgets> + </object> +</interface> diff --git a/pyanaconda/ui/gui/spokes/lib/detailederror.py b/pyanaconda/ui/gui/spokes/lib/detailederror.py new file mode 100644 index 000000000..997d58502 --- /dev/null +++ b/pyanaconda/ui/gui/spokes/lib/detailederror.py @@ -0,0 +1,58 @@ +# Detailed error dialog class +# +# Copyright (C) 2011-2012 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 <clumens@redhat.com> +# + +from gi.repository import Gtk + +from pyanaconda.ui.gui import UIObject + +__all__ = ["DetailedErrorDialog"] + +class DetailedErrorDialog(UIObject): + """This class provides a lightboxable dialog to display a very detailed + set of error messages, like might be required to display the results + of package dependency solving or storage sanity checking. + + By default, this dialog has only a single button - cancel, displayed + on the far left hand side of the dialog, with a response ID of 0. + For all other buttons, provide a kwarg named "buttons" as a list of + translated labels. Each will have an incrementing response ID + starting with 1. It is up to the caller of the "run" method to do + something with the returned response ID. + """ + builderObjects = ["detailedErrorDialog", "detailedTextBuffer"] + mainWidgetName = "detailedErrorDialog" + uiFile = "spokes/lib/detailederror.glade" + + def __init__(self, *args, **kwargs): + buttons = kwargs.pop("buttons", []) + UIObject.__init__(self, *args, **kwargs) + + i = 1 + for button in buttons: + self.window.add_button(button, i) + i += 1 + + def refresh(self, msg): + buf = self.builder.get_object("detailedTextBuffer") + buf.set_text(msg, -1) + + def run(self): + return self.window.run() diff --git a/pyanaconda/ui/gui/spokes/network.ui b/pyanaconda/ui/gui/spokes/network.glade index 49c75c289..49c75c289 100644 --- a/pyanaconda/ui/gui/spokes/network.ui +++ b/pyanaconda/ui/gui/spokes/network.glade diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py index fb68c3fc3..9142ad0e1 100644 --- a/pyanaconda/ui/gui/spokes/network.py +++ b/pyanaconda/ui/gui/spokes/network.py @@ -902,7 +902,7 @@ class NetworkControlBox(): class NetworkSpoke(NormalSpoke): builderObjects = ["networkWindow", "liststore_wireless_network", "liststore_devices"] mainWidgetName = "networkWindow" - uiFile = "spokes/network.ui" + uiFile = "spokes/network.glade" title = N_("NETWORK CONFIGURATION") icon = "network-transmit-receive-symbolic" @@ -962,7 +962,7 @@ class NetworkSpoke(NormalSpoke): class NetworkStandaloneSpoke(StandaloneSpoke): builderObjects = ["networkStandaloneWindow", "networkControlBox_vbox", "liststore_wireless_network", "liststore_devices"] mainWidgetName = "networkStandaloneWindow" - uiFile = "spokes/network.ui" + uiFile = "spokes/network.glade" preForHub = SummaryHub priority = 10 @@ -1040,7 +1040,7 @@ if __name__ == "__main__": builder = Gtk.Builder() import os - ui_file_path = os.environ.get('UIPATH')+'spokes/network.ui' + ui_file_path = os.environ.get('UIPATH')+'spokes/network.glade' builder.add_from_file(ui_file_path) n = NetworkControlBox(builder) diff --git a/pyanaconda/ui/gui/spokes/software.ui b/pyanaconda/ui/gui/spokes/software.glade index 20bbaa32e..d0d91325e 100644 --- a/pyanaconda/ui/gui/spokes/software.ui +++ b/pyanaconda/ui/gui/spokes/software.glade @@ -28,6 +28,7 @@ <property name="startup_id">filler</property> <property name="window_name">SOFTWARE SELECTION</property> <signal name="back-clicked" handler="on_back_clicked" swapped="no"/> + <signal name="info-bar-clicked" handler="on_info_bar_clicked" swapped="no"/> <child internal-child="main_box"> <object class="GtkBox" id="AnacondaSpokeWindow-main_box1"> <property name="can_focus">False</property> @@ -181,6 +182,9 @@ <property name="headers_visible">False</property> <property name="headers_clickable">False</property> <property name="search_column">0</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection2"/> + </child> <child> <object class="GtkTreeViewColumn" id="addonSelectedCol"> <property name="title" translatable="yes">column</property> diff --git a/pyanaconda/ui/gui/spokes/software.py b/pyanaconda/ui/gui/spokes/software.py index 9e56a4bab..cf047ab2d 100644 --- a/pyanaconda/ui/gui/spokes/software.py +++ b/pyanaconda/ui/gui/spokes/software.py @@ -25,19 +25,21 @@ N_ = lambda x: x from pyanaconda.flags import flags -from pyanaconda.ui.gui import communication +from pyanaconda.ui.gui import UIObject, communication from pyanaconda.ui.gui.spokes import NormalSpoke -from pyanaconda.ui.gui.utils import gdk_threaded +from pyanaconda.ui.gui.spokes.lib.detailederror import DetailedErrorDialog +from pyanaconda.ui.gui.utils import enlightbox, gdk_threaded from pyanaconda.ui.gui.categories.software import SoftwareCategory -from pyanaconda.ui.gui.utils import enlightbox from .source import AdditionalReposDialog +import sys + __all__ = ["SoftwareSelectionSpoke"] class SoftwareSelectionSpoke(NormalSpoke): builderObjects = ["addonStore", "desktopStore", "softwareWindow"] mainWidgetName = "softwareWindow" - uiFile = "spokes/software.ui" + uiFile = "spokes/software.glade" category = SoftwareCategory @@ -46,7 +48,7 @@ class SoftwareSelectionSpoke(NormalSpoke): def __init__(self, *args, **kwargs): NormalSpoke.__init__(self, *args, **kwargs) - self._error = False + self._errorMsgs = None self._tx_id = None self.selectedGroups = [] @@ -89,12 +91,12 @@ class SoftwareSelectionSpoke(NormalSpoke): try: self.payload.checkSoftwareSelection() except DependencyError as e: - self._error = True + self._errorMsgs = "\n".join(sorted(e.message)) communication.send_message(self.__class__.__name__, _("Error checking software dependencies")) self._tx_id = None else: - self._error = False + self._errorMsgs = None self._tx_id = self.payload.txID finally: communication.send_ready(self.__class__.__name__) @@ -105,7 +107,7 @@ class SoftwareSelectionSpoke(NormalSpoke): from pyanaconda.kickstart import packagesSeen processingDone = not threadMgr.get("AnaCheckSoftwareThread") and \ - not self._error and \ + not self._errorMsgs and \ self._tx_id == self.payload.txID if flags.automatedInstall: @@ -130,7 +132,7 @@ class SoftwareSelectionSpoke(NormalSpoke): from pyanaconda.kickstart import packagesSeen from pyanaconda.threads import threadMgr - if self._error: + if self._errorMsgs: return _("Error checking software selection") if threadMgr.get("AnaPayloadMDThread") or self.payload.baseRepo is None: @@ -187,6 +189,8 @@ class SoftwareSelectionSpoke(NormalSpoke): self.apply() def refresh(self): + from gi.repository import Gtk + from pyanaconda.threads import threadMgr NormalSpoke.refresh(self) @@ -229,6 +233,9 @@ class SoftwareSelectionSpoke(NormalSpoke): self.excludedGroups = [g.name for g in self.data.packages.excludedGroupList] + if self._errorMsgs: + self.window.set_info(Gtk.MessageType.WARNING, _("Error checking software dependencies. Click for details.")) + # Returns the row in the store corresponding to what's selected on the # left hand panel, or None if nothing's selected. def _get_selected_desktop(self): @@ -258,3 +265,28 @@ class SoftwareSelectionSpoke(NormalSpoke): with enlightbox(self.window, self._addRepoDialog.window): response = self._addRepoDialog.run() + def on_info_bar_clicked(self, *args): + if not self._errorMsgs: + return + + dialog = DetailedErrorDialog(self.data, buttons=[_("_Quit"), _("_Remove Packages"), + _("_Modify Software Source")]) + with enlightbox(self.window, dialog.window): + dialog.refresh(self._errorMsgs) + rc = dialog.run() + + dialog.window.destroy() + + if rc == 0: + # Close the dialog so the user can change selections. + pass + elif rc == 1: + # Quit. + sys.exit(0) + elif rc == 2: + # TODO: Attempt to remove the affected packages. + pass + elif rc == 3: + # Send the user to the installation source spoke. + self.skipTo = "SourceSpoke" + self.window.emit("back-clicked") diff --git a/pyanaconda/ui/gui/spokes/source.ui b/pyanaconda/ui/gui/spokes/source.glade index 5259431bc..5259431bc 100644 --- a/pyanaconda/ui/gui/spokes/source.ui +++ b/pyanaconda/ui/gui/spokes/source.glade diff --git a/pyanaconda/ui/gui/spokes/source.py b/pyanaconda/ui/gui/spokes/source.py index c8c708dc9..fd40b5cb3 100644 --- a/pyanaconda/ui/gui/spokes/source.py +++ b/pyanaconda/ui/gui/spokes/source.py @@ -48,7 +48,7 @@ METADATA_ERROR_MESSAGE = _("Error downloading package metadata...") class ProxyDialog(GUIObject): builderObjects = ["proxyDialog"] mainWidgetName = "proxyDialog" - uiFile = "spokes/source.ui" + uiFile = "spokes/source.glade" def on_proxy_cancel_clicked(self, *args): self.window.destroy() @@ -129,7 +129,7 @@ class ProxyDialog(GUIObject): class MediaCheckDialog(GUIObject): builderObjects = ["mediaCheckDialog"] mainWidgetName = "mediaCheckDialog" - uiFile = "spokes/source.ui" + uiFile = "spokes/source.glade" def _checkisoEndsCB(self, pid, status): doneButton = self.builder.get_object("doneButton") @@ -196,7 +196,7 @@ class MediaCheckDialog(GUIObject): class IsoChooser(GUIObject): builderObjects = ["isoChooserDialog", "isoFilter"] mainWidgetName = "isoChooserDialog" - uiFile = "spokes/source.ui" + uiFile = "spokes/source.glade" def refresh(self, currentFile=""): GUIObject.refresh(self) @@ -238,7 +238,7 @@ class IsoChooser(GUIObject): class AdditionalReposDialog(GUIObject): builderObjects = ["additionalReposDialog", "peopleRepositories", "peopleRepositoriesFilter"] mainWidgetName = "additionalReposDialog" - uiFile = "spokes/source.ui" + uiFile = "spokes/source.glade" typingTimeout = 1 @@ -409,7 +409,7 @@ class AdditionalReposDialog(GUIObject): class SourceSpoke(NormalSpoke): builderObjects = ["isoChooser", "isoFilter", "partitionStore", "sourceWindow", "dirImage"] mainWidgetName = "sourceWindow" - uiFile = "spokes/source.ui" + uiFile = "spokes/source.glade" category = SoftwareCategory diff --git a/pyanaconda/ui/gui/spokes/storage.ui b/pyanaconda/ui/gui/spokes/storage.glade index 16fa40271..16fa40271 100644 --- a/pyanaconda/ui/gui/spokes/storage.ui +++ b/pyanaconda/ui/gui/spokes/storage.glade diff --git a/pyanaconda/ui/gui/spokes/storage.py b/pyanaconda/ui/gui/spokes/storage.py index ec26f7615..d8cccd8c0 100644 --- a/pyanaconda/ui/gui/spokes/storage.py +++ b/pyanaconda/ui/gui/spokes/storage.py @@ -47,7 +47,7 @@ from pyanaconda.ui.gui.spokes.lib.cart import SelectedDisksDialog from pyanaconda.ui.gui.categories.storage import StorageCategory from pyanaconda.ui.gui.utils import enlightbox, gdk_threaded -from pyanaconda.storage import doKickstartStorage +from pyanaconda.kickstart import doKickstartStorage from pyanaconda.storage.size import Size from pyanaconda.product import productName from pyanaconda.flags import flags @@ -60,6 +60,9 @@ _ = lambda x: gettext.ldgettext("anaconda", x) N_ = lambda x: x P_ = lambda x, y, z: gettext.ldngettext("anaconda", x, y, z) +import logging +log = logging.getLogger("anaconda") + __all__ = ["StorageSpoke"] class FakeDiskLabel(object): @@ -110,7 +113,7 @@ def size_str(mb): class InstallOptions1Dialog(GUIObject): builderObjects = ["options1_dialog"] mainWidgetName = "options1_dialog" - uiFile = "spokes/storage.ui" + uiFile = "spokes/storage.glade" RESPONSE_CANCEL = 0 RESPONSE_CONTINUE = 1 @@ -246,11 +249,15 @@ class StorageChecker(object): (StorageChecker.errors, StorageChecker.warnings) = self.storage.sanityCheck() communication.send_ready(self._mainSpokeClass, justUpdate=True) + for e in StorageChecker.errors: + log.error(e) + for w in StorageChecker.warnings: + log.warn(w) class StorageSpoke(NormalSpoke, StorageChecker): builderObjects = ["storageWindow"] mainWidgetName = "storageWindow" - uiFile = "spokes/storage.ui" + uiFile = "spokes/storage.glade" category = StorageCategory @@ -260,6 +267,8 @@ class StorageSpoke(NormalSpoke, StorageChecker): def __init__(self, *args, **kwargs): NormalSpoke.__init__(self, *args, **kwargs) + self.applyOnSkip = True + self._ready = False self.selected_disks = self.data.ignoredisk.onlyuse[:] @@ -310,14 +319,9 @@ class StorageSpoke(NormalSpoke, StorageChecker): # user may have set up before now. self.storage.config.clearNonExistent = self.data.autopart.autopart - # Pick the first disk to be the destination device for the bootloader. - # This appears to be the minimum amount of configuration required to - # make autopart happy with the bootloader settings. - if not self.data.bootloader.bootDrive: - self.data.bootloader.bootDrive = self.storage.bootloader.disks[0].name - def execute(self): - doKickstartStorage(self.storage, self.data, self.instclass, self) + doKickstartStorage(self.storage, self.data, self.instclass) + self.run() @property def completed(self): diff --git a/pyanaconda/ui/gui/spokes/welcome.ui b/pyanaconda/ui/gui/spokes/welcome.glade index e5bcc0f7d..e5bcc0f7d 100644 --- a/pyanaconda/ui/gui/spokes/welcome.ui +++ b/pyanaconda/ui/gui/spokes/welcome.glade diff --git a/pyanaconda/ui/gui/spokes/welcome.py b/pyanaconda/ui/gui/spokes/welcome.py index 9c899eb4a..dc4c733ce 100644 --- a/pyanaconda/ui/gui/spokes/welcome.py +++ b/pyanaconda/ui/gui/spokes/welcome.py @@ -190,7 +190,7 @@ class LanguageMixIn(object): class WelcomeLanguageSpoke(LanguageMixIn, StandaloneSpoke): mainWidgetName = "welcomeWindow" - uiFile = "spokes/welcome.ui" + uiFile = "spokes/welcome.glade" builderObjects = LanguageMixIn.builderObjects + [mainWidgetName, "betaWarnDialog"] preForHub = SummaryHub @@ -234,7 +234,7 @@ class WelcomeLanguageSpoke(LanguageMixIn, StandaloneSpoke): class LanguageSpoke(LanguageMixIn, NormalSpoke): mainWidgetName = "languageSpokeWindow" - uiFile = "spokes/welcome.ui" + uiFile = "spokes/welcome.glade" builderObjects = LanguageMixIn.builderObjects + [mainWidgetName, WelcomeLanguageSpoke.mainWidgetName] category = LocalizationCategory diff --git a/pyanaconda/ui/gui/tools/run-spoke.py b/pyanaconda/ui/gui/tools/run-spoke.py index afb6b0193..afddbd1ff 100755 --- a/pyanaconda/ui/gui/tools/run-spoke.py +++ b/pyanaconda/ui/gui/tools/run-spoke.py @@ -97,7 +97,6 @@ instclass = DefaultInstall() payload = YumPayload(ksdata) payload.setup(storage) -payload.install_log = sys.stdout spoke = spokeClass(ksdata, storage, payload, instclass) if hasattr(spoke, "register_event_cb"): |