summaryrefslogtreecommitdiffstats
path: root/pyanaconda/ui/gui
diff options
context:
space:
mode:
authorMartin Sivak <msivak@redhat.com>2012-08-06 13:43:32 +0200
committerMartin Sivak <msivak@redhat.com>2012-08-06 13:43:32 +0200
commita518f8919488710842dc50d6e28f1d9bea5a186d (patch)
treeef1d8e64aef6cf133d4f92177eea3ed6644b49f1 /pyanaconda/ui/gui
parent72c797294e5d70a221cab91d3d97ce805ad4b851 (diff)
parent86dd8ff76ba9a6fd10a7325df2c0691339d7fb76 (diff)
downloadanaconda-a518f8919488710842dc50d6e28f1d9bea5a186d.tar.gz
anaconda-a518f8919488710842dc50d6e28f1d9bea5a186d.tar.xz
anaconda-a518f8919488710842dc50d6e28f1d9bea5a186d.zip
Merge master into newtui
Diffstat (limited to 'pyanaconda/ui/gui')
-rw-r--r--pyanaconda/ui/gui/Makefile.am2
-rw-r--r--pyanaconda/ui/gui/TODO4
-rw-r--r--pyanaconda/ui/gui/__init__.py18
-rw-r--r--pyanaconda/ui/gui/hubs/Makefile.am2
-rw-r--r--pyanaconda/ui/gui/hubs/__init__.py6
-rw-r--r--pyanaconda/ui/gui/hubs/progress.glade (renamed from pyanaconda/ui/gui/hubs/progress.ui)0
-rw-r--r--pyanaconda/ui/gui/hubs/progress.py11
-rw-r--r--pyanaconda/ui/gui/hubs/summary.glade (renamed from pyanaconda/ui/gui/hubs/summary.ui)0
-rw-r--r--pyanaconda/ui/gui/hubs/summary.py2
-rw-r--r--pyanaconda/ui/gui/main.glade (renamed from pyanaconda/ui/gui/main.ui)0
-rw-r--r--pyanaconda/ui/gui/spokes/Makefile.am2
-rw-r--r--pyanaconda/ui/gui/spokes/__init__.py27
-rw-r--r--pyanaconda/ui/gui/spokes/custom.glade (renamed from pyanaconda/ui/gui/spokes/custom.ui)0
-rw-r--r--pyanaconda/ui/gui/spokes/custom.py6
-rw-r--r--pyanaconda/ui/gui/spokes/datetime_spoke.glade (renamed from pyanaconda/ui/gui/spokes/datetime_spoke.ui)0
-rw-r--r--pyanaconda/ui/gui/spokes/datetime_spoke.py4
-rw-r--r--pyanaconda/ui/gui/spokes/keyboard.glade (renamed from pyanaconda/ui/gui/spokes/keyboard.ui)0
-rw-r--r--pyanaconda/ui/gui/spokes/keyboard.py4
-rw-r--r--pyanaconda/ui/gui/spokes/lib/Makefile.am2
-rw-r--r--pyanaconda/ui/gui/spokes/lib/cart.glade (renamed from pyanaconda/ui/gui/spokes/lib/cart.ui)0
-rw-r--r--pyanaconda/ui/gui/spokes/lib/cart.py2
-rw-r--r--pyanaconda/ui/gui/spokes/lib/detailederror.glade90
-rw-r--r--pyanaconda/ui/gui/spokes/lib/detailederror.py58
-rw-r--r--pyanaconda/ui/gui/spokes/network.glade (renamed from pyanaconda/ui/gui/spokes/network.ui)0
-rw-r--r--pyanaconda/ui/gui/spokes/network.py6
-rw-r--r--pyanaconda/ui/gui/spokes/software.glade (renamed from pyanaconda/ui/gui/spokes/software.ui)4
-rw-r--r--pyanaconda/ui/gui/spokes/software.py50
-rw-r--r--pyanaconda/ui/gui/spokes/source.glade (renamed from pyanaconda/ui/gui/spokes/source.ui)0
-rw-r--r--pyanaconda/ui/gui/spokes/source.py10
-rw-r--r--pyanaconda/ui/gui/spokes/storage.glade (renamed from pyanaconda/ui/gui/spokes/storage.ui)0
-rw-r--r--pyanaconda/ui/gui/spokes/storage.py24
-rw-r--r--pyanaconda/ui/gui/spokes/welcome.glade (renamed from pyanaconda/ui/gui/spokes/welcome.ui)0
-rw-r--r--pyanaconda/ui/gui/spokes/welcome.py4
-rwxr-xr-xpyanaconda/ui/gui/tools/run-spoke.py1
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"):