[PATCH 2/2] Rework actions in the resize dialog to avoid shortcomings (#866209, #867770).

Chris Lumens clumens at redhat.com
Tue Nov 20 20:48:56 UTC 2012


There are three problems with the current resize action UI:

(1) You can't discover that there's a drop down in the action column because
there's no down arrow.  GTK simply doesn't do that.

(2) We can't filter out shrink from the drop down on a per-filesystem basis
without layering on all the usual filter store crud.

(3) Something about interacting with a GtkCellRendererCombo causes the layering
of dialogs to get screwed up such that coming back to the storage spoke after
visiting the resize dialog appears locked up, because the dialog is displayed
under the spoke.

This commit fixes all these problems by getting rid of the drop downs in the
action column and adding a communal set of tool buttons for setting the action
you want.
---
 pyanaconda/ui/gui/spokes/lib/resize.glade | 95 +++++++++++++++++++++----------
 pyanaconda/ui/gui/spokes/lib/resize.py    | 79 +++++++++++++++++++++----
 2 files changed, 135 insertions(+), 39 deletions(-)

diff --git a/pyanaconda/ui/gui/spokes/lib/resize.glade b/pyanaconda/ui/gui/spokes/lib/resize.glade
index e3aa001..86e8ee1 100644
--- a/pyanaconda/ui/gui/spokes/lib/resize.glade
+++ b/pyanaconda/ui/gui/spokes/lib/resize.glade
@@ -1,23 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkListStore" id="actionStore">
-    <columns>
-      <!-- column-name actionName -->
-      <column type="gchararray"/>
-    </columns>
-    <data>
-      <row>
-        <col id="0" translatable="yes">Preserve</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Shrink</col>
-      </row>
-      <row>
-        <col id="0" translatable="yes">Delete</col>
-      </row>
-    </data>
-  </object>
   <object class="GtkTreeStore" id="diskStore">
     <columns>
       <!-- column-name diskID -->
@@ -37,7 +20,7 @@
     </columns>
   </object>
   <object class="GtkDialog" id="resizeDialog">
-    <property name="height_request">450</property>
+    <property name="height_request">550</property>
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
     <property name="resizable">False</property>
@@ -98,11 +81,11 @@
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="orientation">vertical</property>
-            <property name="spacing">6</property>
             <child>
               <object class="GtkLabel" id="label1">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
+                <property name="margin_bottom">6</property>
                 <property name="xalign">0</property>
                 <property name="label" translatable="yes">RECLAIM DISK SPACE</property>
                 <attributes>
@@ -119,6 +102,7 @@
               <object class="GtkLabel" id="reclaimDescLabel">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
+                <property name="margin_bottom">6</property>
                 <property name="xalign">0</property>
                 <property name="label" translatable="yes">Description goes here.</property>
                 <property name="wrap">True</property>
@@ -142,8 +126,11 @@
                     <property name="model">diskStore</property>
                     <property name="enable_search">False</property>
                     <property name="enable_tree_lines">True</property>
+                    <signal name="row-activated" handler="on_row_clicked" swapped="no"/>
                     <child internal-child="selection">
-                      <object class="GtkTreeSelection" id="diskView-selection"/>
+                      <object class="GtkTreeSelection" id="diskView-selection">
+                        <signal name="changed" handler="on_selection_changed" swapped="no"/>
+                      </object>
                     </child>
                     <child>
                       <object class="GtkTreeViewColumn" id="diskColumn">
@@ -193,12 +180,7 @@
                       <object class="GtkTreeViewColumn" id="actionColumn">
                         <property name="title" translatable="yes">Action</property>
                         <child>
-                          <object class="GtkCellRendererCombo" id="actionRenderer">
-                            <property name="has_entry">False</property>
-                            <property name="model">actionStore</property>
-                            <property name="text_column">0</property>
-                            <signal name="changed" handler="on_action_changed" swapped="no"/>
-                          </object>
+                          <object class="GtkCellRendererText" id="actionRenderer"/>
                           <attributes>
                             <attribute name="visible">6</attribute>
                             <attribute name="text">5</attribute>
@@ -216,17 +198,70 @@
               </packing>
             </child>
             <child>
+              <object class="GtkToolbar" id="toolbar1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_bottom">6</property>
+                <property name="toolbar_style">text</property>
+                <style>
+                  <class name="inline-toolbar"/>
+                </style>
+                <child>
+                  <object class="GtkToolButton" id="preserveButton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Preserve</property>
+                    <signal name="clicked" handler="on_preserve_clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="homogeneous">True</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToolButton" id="shrinkButton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Shrink</property>
+                    <signal name="clicked" handler="on_shrink_clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="homogeneous">True</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToolButton" id="deleteButton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Delete</property>
+                    <signal name="clicked" handler="on_delete_clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="homogeneous">True</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkLabel" id="reclaimableSpaceLabel">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="halign">start</property>
+                <property name="margin_bottom">6</property>
                 <property name="label" translatable="yes">&lt;b&gt;%s disks; %s reclaimable space&lt;/b&gt; (in filesystems)</property>
                 <property name="use_markup">True</property>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">True</property>
-                <property name="position">3</property>
+                <property name="position">4</property>
               </packing>
             </child>
             <child>
@@ -234,13 +269,14 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="halign">end</property>
+                <property name="margin_bottom">6</property>
                 <property name="label" translatable="yes">Total selected space to reclaim:  &lt;b&gt;%s&lt;/b&gt;</property>
                 <property name="use_markup">True</property>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">True</property>
-                <property name="position">4</property>
+                <property name="position">5</property>
               </packing>
             </child>
             <child>
@@ -248,13 +284,14 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="halign">end</property>
+                <property name="margin_bottom">6</property>
                 <property name="label" translatable="yes">Installation requires a total of &lt;b&gt;%s&lt;/b&gt; for system data.</property>
                 <property name="use_markup">True</property>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">True</property>
-                <property name="position">5</property>
+                <property name="position">6</property>
               </packing>
             </child>
           </object>
diff --git a/pyanaconda/ui/gui/spokes/lib/resize.py b/pyanaconda/ui/gui/spokes/lib/resize.py
index a1aa0cd..1d82c16 100644
--- a/pyanaconda/ui/gui/spokes/lib/resize.py
+++ b/pyanaconda/ui/gui/spokes/lib/resize.py
@@ -80,6 +80,10 @@ class ResizeDialog(GUIObject):
 
         self._resizeButton = self.builder.get_object("resizeButton")
 
+        self._preserveButton = self.builder.get_object("preserveButton")
+        self._shrinkButton = self.builder.get_object("shrinkButton")
+        self._deleteButton = self.builder.get_object("deleteButton")
+
     def _description(self, part):
         # First, try to find the partition in some known Root.  If we find
         # it, return the mountpoint as the description.
@@ -106,11 +110,6 @@ class ResizeDialog(GUIObject):
 
         canShrinkSomething = False
 
-        # Shouldn't have to do this outside of glade, but see:
-        # https://bugzilla.gnome.org/show_bug.cgi?id=685003
-        renderer = self.builder.get_object("actionRenderer")
-        renderer.set_property("editable", True)
-
         for disk in disks:
             # First add the disk itself.
             if disk.partitioned:
@@ -189,6 +188,31 @@ class ResizeDialog(GUIObject):
             text = _("Total selected space to reclaim: <b>%s</b>") % size_str(selectedReclaimable)
             self._selected_label.set_markup(text)
 
+    def _update_buttons(self, row):
+        # If this is a disk header, it's not editable, so make all the
+        # buttons insensitive.
+        self._preserveButton.set_sensitive(row[EDITABLE_COL])
+        self._shrinkButton.set_sensitive(row[EDITABLE_COL])
+        self._deleteButton.set_sensitive(row[EDITABLE_COL])
+
+        if not row[EDITABLE_COL]:
+            return
+
+        # If the selected filesystem does not support shrinking, make that
+        # button insensitive.
+        if row[EDITABLE_COL]:
+            device = self.storage.devicetree.getDeviceByID(row[DEVICE_ID_COL])
+            self._shrinkButton.set_sensitive(device.resizable)
+
+        # Then, disable the button for whatever action is currently selected.
+        # It doesn't make a lot of sense to allow clicking that.
+        if row[ACTION_COL] == _(PRESERVE):
+            self._preserveButton.set_sensitive(False)
+        elif row[ACTION_COL] == _(SHRINK):
+            self._shrinkButton.set_sensitive(False)
+        elif row[ACTION_COL] == _(DELETE):
+            self._deleteButton.set_sensitive(False)
+
     def refresh(self, disks):
         super(ResizeDialog, self).refresh()
 
@@ -223,14 +247,26 @@ class ResizeDialog(GUIObject):
 
         return False
 
-    def on_action_changed(self, combo, path, itr, *args):
-        diskItr = self._diskStore.get_iter_from_string(path)
-        selectedRow = self._diskStore[diskItr]
+    def on_preserve_clicked(self, button):
+        self._actionChanged(PRESERVE)
+
+    def on_shrink_clicked(self, button):
+        self._actionChanged(SHRINK)
+
+    def on_delete_clicked(self, button):
+        self._actionChanged(DELETE)
+
+    def _actionChanged(self, newAction):
+        selection = self.builder.get_object("diskView-selection")
+        (model, itr) = selection.get_selected()
+
+        if not itr:
+            return
 
-        selectedAction = self._actionStore[itr][0]
+        selectedRow = self._diskStore[itr]
 
         # Put the selected action into the store as well.
-        selectedRow[ACTION_COL] = selectedAction
+        selectedRow[ACTION_COL] = _(newAction)
 
         # And then we're keeping a running tally of how much space the user
         # has selected to reclaim, so reflect that in the UI.
@@ -242,6 +278,8 @@ class ResizeDialog(GUIObject):
         need = self.payload.spaceRequired
         self._resizeButton.set_sensitive(got >= need)
 
+        self._update_buttons(selectedRow)
+
     def _scheduleActions(self, model, path, itr, *args):
         (editable, action, ident) = model.get(itr, EDITABLE_COL, ACTION_COL, DEVICE_ID_COL)
 
@@ -264,3 +302,24 @@ class ResizeDialog(GUIObject):
 
     def on_resize_clicked(self, *args):
         self._diskStore.foreach(self._scheduleActions, None)
+
+    def on_row_clicked(self, view, path, column):
+        # This handles when the user clicks on a row in the view.  We use it
+        # only for expanding/collapsing disk headers.
+        if view.row_expanded(path):
+            view.collapse_row(path)
+        else:
+            view.expand_row(path, True)
+
+    def on_selection_changed(self, selection):
+        # This handles when the selection changes.  It's very similar to what
+        # on_row_clicked above does, but this handler only deals with changes in
+        # selection.  Thus, clicking on a disk header to collapse it and then
+        # immediately clicking on it again to expand it would not work when
+        # dealt with here.
+        (model, itr) = selection.get_selected()
+
+        if not itr:
+            return
+
+        self._update_buttons(self._diskStore[itr])
-- 
1.7.11.2



More information about the anaconda-patches mailing list