4018 Package Manager - Window width bug
authorMichal Pryc <Michal.Pryc@Sun.Com>
Sat, 18 Oct 2008 07:18:21 +0100
changeset 647 be0aec1c0910
parent 646 bce54cb11bfa
child 648 9f1f457e78b2
4018 Package Manager - Window width bug 3202 Add dialog for setting name for Boot Environment 3203 Add dialog for update error - Not enought free space 1579 Details text field should be anchored to bottom 2121 Install/Upgrade Check dialog needs to be more informative
src/gui/data/packagemanager.glade
src/gui/modules/installupdate.py
src/updatemanager.py
--- a/src/gui/data/packagemanager.glade	Thu Oct 30 14:04:09 2008 +0000
+++ b/src/gui/data/packagemanager.glade	Sat Oct 18 07:18:21 2008 +0100
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.5 on Fri Oct 17 10:49:14 2008 -->
+<!--Generated with glade3 3.4.5 on Sat Oct 18 05:39:30 2008 -->
 <glade-interface>
   <widget class="GtkWindow" id="mainwindow">
     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
@@ -806,8 +806,8 @@
     </child>
   </widget>
   <widget class="GtkDialog" id="installupdate">
-    <property name="width_request">385</property>
-    <property name="height_request">365</property>
+    <property name="width_request">400</property>
+    <property name="height_request">375</property>
     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Install / Update Confirmation</property>
@@ -989,7 +989,7 @@
     </child>
   </widget>
   <widget class="GtkDialog" id="downloadingfiles">
-    <property name="width_request">350</property>
+    <property name="width_request">400</property>
     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Downloading Packages</property>
@@ -1114,7 +1114,7 @@
     </child>
   </widget>
   <widget class="GtkDialog" id="createplandialog">
-    <property name="width_request">350</property>
+    <property name="width_request">400</property>
     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Install/Upgrade Check</property>
@@ -1144,6 +1144,7 @@
                 <property name="yalign">0</property>
                 <property name="label" translatable="yes">Checking package dependencies...</property>
                 <property name="use_markup">True</property>
+                <property name="wrap">True</property>
               </widget>
               <packing>
                 <property name="expand">False</property>
@@ -1239,7 +1240,7 @@
     </child>
   </widget>
   <widget class="GtkDialog" id="installingdialog">
-    <property name="width_request">350</property>
+    <property name="width_request">400</property>
     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Installing Packages</property>
@@ -1832,7 +1833,7 @@
     </child>
   </widget>
   <widget class="GtkDialog" id="progressdialog">
-    <property name="width_request">350</property>
+    <property name="width_request">400</property>
     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Processing</property>
@@ -1984,8 +1985,10 @@
                 <property name="xalign">0</property>
                 <property name="yalign">0</property>
                 <property name="xpad">20</property>
-                <property name="label" translatable="yes">Note: The current active BE cannot be deleted. To delete this BE, boot into another BE, then return here.</property>
+                <property name="label" translatable="yes">Note: The current active BE cannot be deleted. 
+To delete this BE, boot into another BE, then return here.</property>
                 <property name="use_markup">True</property>
+                <property name="wrap">True</property>
               </widget>
               <packing>
                 <property name="expand">False</property>
@@ -2911,4 +2914,121 @@
       </widget>
     </child>
   </widget>
+  <widget class="GtkDialog" id="ua_confirm_dialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Update All</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="icon">PM_app_48x.png</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="transient_for">mainwindow</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox15">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkVBox" id="vbox12">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+            <property name="spacing">4</property>
+            <child>
+              <widget class="GtkLabel" id="label6">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;b&gt;Create New Boot Environment&lt;/b&gt;
+
+Update All will create a new boot environment (BE) as a means
+of archiving older software and sets it to be the default BE when
+rebooting.
+
+An updated clone of the active BE is about to be created.</property>
+                <property name="use_markup">True</property>
+                <property name="wrap_mode">PANGO_WRAP_WORD_CHAR</property>
+              </widget>
+              <packing>
+                <property name="padding">5</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkHBox" id="hbox7">
+                <property name="visible">True</property>
+                <child>
+                  <widget class="GtkLabel" id="label11">
+                    <property name="label" translatable="yes">&lt;b&gt;Boot Environment Name: &lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                    <property name="justify">GTK_JUSTIFY_RIGHT</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkEntry" id="ua_be_name_entry">
+                    <property name="can_focus">True</property>
+                  </widget>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkHSeparator" id="hseparator7">
+                <property name="visible">True</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="padding">4</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="padding">2</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area15">
+            <property name="visible">True</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="ua_cancel_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="label" translatable="yes">_Cancel</property>
+                <property name="use_underline">True</property>
+                <property name="response_id">0</property>
+                <signal name="clicked" handler="on_ua_cancel_button_clicked"/>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="ua_proceed_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="label" translatable="yes">_Proceed</property>
+                <property name="use_underline">True</property>
+                <property name="response_id">0</property>
+                <signal name="clicked" handler="on_ua_proceed_button_clicked"/>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
 </glade-interface>
--- a/src/gui/modules/installupdate.py	Thu Oct 30 14:04:09 2008 +0000
+++ b/src/gui/modules/installupdate.py	Sat Oct 18 07:18:21 2008 +0100
@@ -23,6 +23,7 @@
 # Use is subject to license terms.
 #
 
+import errno
 import gettext # XXX Temporary workaround
 import sys
 import time
@@ -42,6 +43,7 @@
 import pkg.client.api as api
 import pkg.client.api_errors as api_errors
 from pkg.misc import TransferTimedOutException, TransportException
+import pkg.gui.beadmin as beadm
 import pkg.gui.enumerations as enumerations
 
 class InstallUpdate(progress.ProgressTracker):
@@ -55,6 +57,7 @@
                 progress.ProgressTracker.__init__(self)
                 api_o.progresstracker = self
                 self.update_list = []
+                self.install_list = install_list
                 self.parent = parent
                 self.ips_update = ips_update
                 self.ip = None
@@ -70,7 +73,12 @@
                     gtk.glade.XML(parent.gladefile, "downloadingfiles")
                 w_tree_installingdialog = \
                     gtk.glade.XML(parent.gladefile, "installingdialog") 
+                w_tree_uaconfirm = gtk.glade.XML(parent.gladefile, "ua_confirm_dialog")
                 w_tree_networkdown = gtk.glade.XML(parent.gladefile, "networkdown")
+                self.w_ua_confirm_dialog = \
+                        w_tree_uaconfirm.get_widget("ua_confirm_dialog")
+                self.w_ua_proceed_button = \
+                        w_tree_uaconfirm.get_widget("ua_proceed_button")
                 self.w_createplan_dialog = \
                     w_tree_createplan.get_widget("createplandialog")
                 self.w_error_dialog = \
@@ -142,6 +150,8 @@
                             self.parent._("Remove Check"))
                         self.w_installingdialog_label.set_text(\
                             self.parent._("Removing Packages..."))
+                        self.w_next_button.set_label(\
+                            self.parent._("Proceed"))
                         remove_warning_triange.show()
 
                 try:
@@ -171,26 +181,33 @@
                                 "on_error_close_clicked": \
                                     self.__on_error_close_clicked,
                             }
+                        dic_uaconfirm = \
+                            {
+                                "on_ua_cancel_button_clicked": \
+                                    self.__on_ua_cancel_button_clicked,
+                                "on_ua_proceed_button_clicked": \
+                                    self.__on_ua_proceed_button_clicked,
+                            }
                         w_tree_createplan.signal_autoconnect(dic_createplan)
                         w_tree_installupdate.signal_autoconnect(dic_installupdate)
                         w_tree_downloadingfiles.signal_autoconnect(dic_downloadingfiles)
                         w_tree_networkdown.signal_autoconnect(dic_networkdown)
                         w_tree_errordialog.signal_autoconnect(dic_error)
+                        w_tree_uaconfirm.signal_autoconnect(dic_uaconfirm)
                 except AttributeError, error:
                         print self.parent._('GUI will not respond to any event! %s. \
                             Check installupdate.py signals') \
                             % error
                 # XXX Hidden until progress will give information about fmri 
                 self.w_installingdialog_expander.hide()
-                pulse_t = Thread(target = self.__progressdialog_progress_pulse)
-                thread = Thread(target = self.__plan_the_install_updateimage_ex, \
-                    args = (install_list, ))
-                pulse_t.start()
-                thread.start()
                 self.w_createplan_label.set_text(\
                     self.parent._("Checking package dependencies..."))
                 self.w_createplancancel_button.set_sensitive(True)           
-                self.w_createplan_dialog.show()
+                if self.action == enumerations.IMAGE_UPDATE:
+                        self.w_ua_proceed_button.grab_focus()
+                        self.w_ua_confirm_dialog.show()
+                else:
+                        self.__on_ua_proceed_button_clicked(None)
 
         def __on_cancelcreateplan_clicked(self, widget):
                 '''Handler for signal send by cancel button, which user might press during
@@ -234,10 +251,23 @@
         def __on_error_close_clicked(self, widget):
                 self.w_error_dialog.destroy()
 
+        def __on_ua_cancel_button_clicked(self, widget):
+                self.w_ua_confirm_dialog.hide()
+
+        def __on_ua_proceed_button_clicked(self, widget):
+                pulse_t = Thread(target = self.__progressdialog_progress_pulse)
+                thread = Thread(target = self.__plan_the_install_updateimage_ex, \
+                    args = (self.install_list, ))
+                pulse_t.start()
+                thread.start()
+                self.w_ua_confirm_dialog.hide()
+                self.w_createplan_dialog.show()
+
         def __update_createplan_progress(self, action):
                 buf = self.w_createplan_textview.get_buffer()
                 textiter = buf.get_end_iter()
                 buf.insert(textiter, action)
+                self.w_createplan_textview.scroll_to_iter(textiter, 0.0)
                 
         def __progressdialog_progress_pulse(self):
                 while not self.progress_stop_timer_thread:
@@ -433,15 +463,21 @@
         def __prepare_stage_ex(self, api_o):
                 try:
                         self.__prepare_stage(api_o)
-                except Exception:
+                except (Exception), uex:
                         gobject.idle_add(self.w_downloadingfiles_dialog.hide)
-                        msg = self.parent._("An unknown error occured while " + \
-                            "downloading the files\n\nPlease let the developers know " + \
-                            "about this problem by filing\na bug " + \
-                            "at http://defect.opensolaris.org")
-                        msg += "\n\nException value: " + "\n" + str(sys.exc_value)
-                        gobject.idle_add(self.parent.error_occured, msg)
-                        sys.exc_clear()
+                        if uex.args[0] == errno.EDQUOT or uex.args[0] == errno.ENOSPC:
+                                gobject.idle_add(self.__prompt_to_load_beadm)
+                                return
+                        else:
+                                msg = self.parent._("An unknown error occured while " + \
+                                    "downloading the files\n\nPlease let the " + \
+                                    "developers know about this problem by filing\n" + \
+                                    "a bug at http://defect.opensolaris.org")
+                                msg += \
+                                    "\n\nException value: " + "\n" + str(sys.exc_value)
+                                gobject.idle_add(self.parent.error_occured, msg)
+                                sys.exc_clear()
+                                return
 
         def __prepare_stage(self, api_o):
                 gobject.idle_add(self.w_downloadingfiles_dialog.show)
@@ -473,16 +509,22 @@
         def __execute_stage_ex(self, api_o):
                 try:
                         self.__execute_stage(api_o)
-                except Exception:
+                except (Exception), uex:
                         gobject.idle_add(self.w_installing_dialog.hide)
-                        msg = self.parent._("An unknown error occured while " + \
-                            "installing\nupdating or removing packages" + \
-                            "\n\nPlease let the developers know about this problem " + \
-                            "by filing\na bug at http://defect.opensolaris.org")
-                        msg += "\n\nException value: " + "\n" + str(sys.exc_value)
-                        gobject.idle_add(self.parent.error_occured, msg)
-                        sys.exc_clear()
-                        return
+                        if uex.args[0] == errno.EDQUOT or uex.args[0] == errno.ENOSPC:
+                                gobject.idle_add(self.__prompt_to_load_beadm)
+                                return
+                        else:
+                                msg = self.parent._("An unknown error occured while " + \
+                                    "installing\nupdating or removing packages" + \
+                                    "\n\nPlease let the developers know about this " + \
+                                    "problem by filing\na bug at " + \
+                                    "http://defect.opensolaris.org")
+                                msg += \
+                                    "\n\nException value: " + "\n" + str(sys.exc_value)
+                                gobject.idle_add(self.parent.error_occured, msg)
+                                sys.exc_clear()
+                                return
 
         def __execute_stage(self, api_o):
                 text = self.parent._("Installing Packages...")
@@ -549,6 +591,7 @@
                 textiter = buf.get_end_iter()
                 if text:
                         buf.insert(textiter, text + "\n")
+                        self.w_download_textview.scroll_to_iter(textiter, 0.0)
 
         def __error_with_details(self, err_msg, err_text):
                 self.w_errortext_label.set_text(err_msg)
@@ -558,12 +601,28 @@
                 self.w_error_dialog.run()
                 self.w_error_dialog.destroy()
 
+        def __prompt_to_load_beadm(self):
+                msgbox = gtk.MessageDialog(parent = self.parent.w_main_window, \
+                        buttons = gtk.BUTTONS_OK_CANCEL, flags = gtk.DIALOG_MODAL, \
+                        type = gtk.MESSAGE_ERROR, \
+                        message_format = self.parent._(\
+                            "Not enough disc space: selected action cannot " + \
+                            "be performed.\n\n" +\
+                            "You may click OK to launch BE Management to manage your " + \
+                            "existing BE's and free up disc space."))
+                msgbox.set_title(self.parent._("Not Enough Disc Space"))
+                result = msgbox.run()
+                msgbox.destroy()
+                if result == gtk.RESPONSE_OK:
+                        beadm.Beadmin(self.parent)
+
         def __add_info_to_installtext(self, text):
                 '''Function which adds another line text in the "more details" install 
                 dialog'''
                 buf = self.w_installing_textview.get_buffer()
                 textiter = buf.get_end_iter()
                 buf.insert(textiter, text)
+                self.w_installing_textview.scroll_to_iter(textiter, 0.0)
 
         def cat_output_start(self): 
                 return
@@ -581,8 +640,12 @@
                 call is being done by calling progress tracker evaluate_progress() 
                 function'''
                 cur_eval_fmri = self.eval_cur_fmri
-                gobject.idle_add(self.__update_createplan_progress, \
-                    self.parent._("Evaluating: %s\n") % cur_eval_fmri)
+                if cur_eval_fmri:
+                        gobject.idle_add(self.__update_createplan_progress, \
+                            self.parent._("Evaluating: %s\n") % cur_eval_fmri)
+                        text = self.parent._("Evaluating package " + \
+                            "%s") % cur_eval_fmri.get_name()
+                        gobject.idle_add(self.w_createplan_label.set_text, text)
 
         def eval_output_done(self):
                 ninst = self.eval_goal_install_npkgs
@@ -684,6 +747,8 @@
 
         def __get_pkgstr_from_pkginfo(self, pkginfo):
                 dt_str = self.get_datetime(pkginfo.packaging_date)
+                if not dt_str:
+                        dt_str = ""
                 s_ver = pkginfo.version
                 s_bran = pkginfo.branch
                 pkg_name = pkginfo.pkg_stem
@@ -723,6 +788,11 @@
                 return
 
         def act_output(self):
+                if self.act_phase != self.act_phase_last:
+                        self.act_phase_last = self.act_phase
+                        gobject.idle_add(\
+                            self.w_installingdialog_label.set_text, \
+                            self.act_phase)
                 gobject.idle_add(self.__update_install_progress, \
                     self.act_cur_nactions, self.act_goal_nactions)
                 return
@@ -748,6 +818,12 @@
         @staticmethod
         def get_datetime(date_time):
                 '''Support function for getting date from the API.'''
-                date_tmp = time.strptime(date_time, "%a %b %d %H:%M:%S %Y")
-                date_tmp2 = datetime.datetime(*date_tmp[0:5])
-                return date_tmp2.strftime(":%m%d")
+                date_tmp = None
+                try:
+                        date_tmp = time.strptime(date_time, "%a %b %d %H:%M:%S %Y")
+                except ValueError:
+                        return None
+                if date_tmp:
+                        date_tmp2 = datetime.datetime(*date_tmp[0:5])        
+                        return date_tmp2.strftime(":%m%d")
+                return None
--- a/src/updatemanager.py	Thu Oct 30 14:04:09 2008 +0000
+++ b/src/updatemanager.py	Sat Oct 18 07:18:21 2008 +0100
@@ -31,6 +31,7 @@
 import locale
 import gettext
 import pango
+import errno
 from threading import Thread
 from threading import Timer
 
@@ -58,8 +59,6 @@
 IND_DELAY = 0.05                # Time delay for printing index progress
 UPDATES_FETCH_DELAY = 200       # Time to wait before fetching updates, allows gtk main
                                 # loop time to start and display main UI
-EX_DISC_QUOTA_EXCEEDED = 49     # Disc quota exceeded exception
-
 #UM Row Model
 (
 UM_ID,
@@ -1205,17 +1204,16 @@
                         self.__cleanup()                
                         return 1
                 except (Exception), uex:
-                        if uex.args[0] == EX_DISC_QUOTA_EXCEEDED:
+                        if uex.args[0] == errno.EDQUOT or uex.args[0] == errno.ENOSPC:
                                 self.__handle_update_progress_error(\
                                         self._(\
-                                        "%s exceded available disc quota" % what_msg), \
+                                        "%s exceded available disc space" % what_msg), \
                                         stage = self.update_stage)
                                 gobject.idle_add(self.__prompt_to_load_beadm)
                         else:
                                 self.__handle_update_progress_error(\
                                         self._("%s unexpected error:" % (what_msg)), \
                                         uex, stage = self.update_stage)
-                                
                         return 1
 
                 # Install
@@ -1236,9 +1234,16 @@
                         self.__cleanup()                
                         return 1
                 except (Exception), uex:
-                        self.__handle_update_progress_error(\
-                                self._("%s unexpected error:" % (what_msg)), uex, \
-                                stage = self.update_stage)
+                        if uex.args[0] == errno.EDQUOT or uex.args[0] == errno.ENOSPC:
+                                self.__handle_update_progress_error(\
+                                        self._(\
+                                        "%s exceded available disc space" % what_msg), \
+                                        stage = self.update_stage)
+                                gobject.idle_add(self.__prompt_to_load_beadm)
+                        else:
+                                self.__handle_update_progress_error(\
+                                        self._("%s unexpected error:" % (what_msg)), \
+                                        uex, stage = self.update_stage)
                         return 1
                         
                 self.__cleanup()