1 #!/usr/bin/python2.4
   2 #
   3 # CDDL HEADER START
   4 #
   5 # The contents of this file are subject to the terms of the
   6 # Common Development and Distribution License (the "License").
   7 # You may not use this file except in compliance with the License.
   8 #
   9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10 # or http://www.opensolaris.org/os/licensing.
  11 # See the License for the specific language governing permissions
  12 # and limitations under the License.
  13 #
  14 # When distributing Covered Code, include this CDDL HEADER in each
  15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16 # If applicable, add the following below this CDDL HEADER, with the
  17 # fields enclosed by brackets "[]" replaced with your own identifying
  18 # information: Portions Copyright [yyyy] [name of copyright owner]
  19 #
  20 # CDDL HEADER END
  21 #
  22 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23 # Use is subject to license terms.
  24 #
  25 
  26 CLIENT_API_VERSION = 0
  27 PKG_CLIENT_NAME = "packagemanager"
  28 
  29 import gettext # XXX Temporary workaround
  30 import sys
  31 import time
  32 import datetime
  33 from threading import Thread
  34 from urllib2 import URLError
  35 try:
  36         import gobject
  37         import gtk
  38         import gtk.glade
  39         import pygtk
  40         pygtk.require("2.0")
  41 except ImportError:
  42         sys.exit(1)
  43 import pkg.client.progress as progress
  44 import pkg.misc
  45 import pkg.client.api as api
  46 import pkg.client.api_errors as api_errors
  47 from pkg.misc import TransferTimedOutException, TransportException
  48 import pkg.gui.enumerations as enumerations
  49 
  50 class InstallUpdate(progress.ProgressTracker):
  51         def __init__(self, install_list, parent, image_dir, \
  52             ips_update = False, action = -1):
  53                 if action == -1:
  54                         return
  55                 # XXX Workaround as BE is using msg(_("message")) 
  56                 # which bypasses the self._ mechanism the GUI is using
  57                 gettext.install("pkg","/usr/lib/locale")
  58                 progress.ProgressTracker.__init__(self)
  59                 self.update_list = []
  60                 self.parent = parent
  61                 self.ips_update = ips_update
  62                 self.ip = None
  63                 self.progress_stop_timer_thread = False
  64                 self.progress_stop_timer_running = False
  65                 self.prev_pkg = None
  66                 self.action = action
  67                 try:
  68                         self.api_o =  api.ImageInterface(image_dir, \
  69                                     CLIENT_API_VERSION, \
  70                                     self, None, PKG_CLIENT_NAME)
  71                 except api_errors.VersionException:
  72                         msg = self.parent._("The version of the API is not correct.\n" + \
  73                            "Package Manager can't continue this operation.\n")
  74                         self.parent.error_occured(msg)
  75                         return
  76                 except api_errors.ImageNotFoundException:
  77                         msg = self.parent._("The image was not found.")
  78                         self.parent.error_occured(msg)
  79                         return
  80                 w_tree_createplan = gtk.glade.XML(parent.gladefile, "createplandialog")
  81                 w_tree_installupdate = gtk.glade.XML(parent.gladefile, "installupdate")
  82                 w_tree_downloadingfiles = \
  83                     gtk.glade.XML(parent.gladefile, "downloadingfiles")
  84                 w_tree_installingdialog = \
  85                     gtk.glade.XML(parent.gladefile, "installingdialog") 
  86                 w_tree_networkdown = gtk.glade.XML(parent.gladefile, "networkdown")
  87                 self.w_createplan_dialog = \
  88                     w_tree_createplan.get_widget("createplandialog")     
  89                 self.w_next_button = \
  90                     w_tree_installupdate.get_widget("next")
  91                 self.w_cancel_button = \
  92                     w_tree_installupdate.get_widget("cancel")
  93                 self.w_createplan_progressbar = \
  94                     w_tree_createplan.get_widget("createplanprogress") 
  95                 self.w_createplan_textview = \
  96                     w_tree_createplan.get_widget("createplantextview")
  97                 self.w_createplan_label = \
  98                     w_tree_createplan.get_widget("packagedependencies")
  99                 self.w_createplancancel_button = \
 100                     w_tree_createplan.get_widget("cancelcreateplan")
 101                 self.w_canceldownload_button = \
 102                     w_tree_downloadingfiles.get_widget("canceldownload")
 103                 self.w_download_label = \
 104                     w_tree_downloadingfiles.get_widget("packagedependencies2")
 105                 self.w_installupdate_dialog = \
 106                     w_tree_installupdate.get_widget("installupdate")
 107                 self.w_summary_label = \
 108                     w_tree_installupdate.get_widget("packagenamelabel3")
 109                 self.w_review_treeview = w_tree_installupdate.get_widget("treeview1")
 110                 self.w_information_label = w_tree_installupdate.get_widget("label5")
 111                 self.w_downloadingfiles_dialog = \
 112                     w_tree_downloadingfiles.get_widget("downloadingfiles")
 113                 self.w_download_textview = \
 114                     w_tree_downloadingfiles.get_widget("downloadtextview")
 115                 self.w_download_progressbar = \
 116                     w_tree_downloadingfiles.get_widget("downloadprogress")
 117                 self.w_installing_dialog = \
 118                     w_tree_installingdialog.get_widget("installingdialog")
 119                 self.w_installingdialog_label = \
 120                     w_tree_installingdialog.get_widget("packagedependencies3")
 121                 self.w_installingdialog_expander = \
 122                     w_tree_installingdialog.get_widget("expander4")                     
 123                 self.w_installing_textview = \
 124                     w_tree_installingdialog.get_widget("installingtextview")
 125                 self.w_installing_progressbar = \
 126                     w_tree_installingdialog.get_widget("installingprogress")
 127                 self.w_networkdown_dialog = w_tree_networkdown.get_widget("networkdown")
 128                 self.w_createplan_progressbar.set_pulse_step(0.1)
 129                 installed_updated_column = gtk.TreeViewColumn('Installed/Updated')
 130                 self.w_review_treeview.append_column(installed_updated_column)
 131                 cell = gtk.CellRendererText()
 132                 installed_updated_column.pack_start(cell, True)
 133                 installed_updated_column.add_attribute(cell, 'text', 0)
 134                 self.w_review_treeview.expand_all()
 135 
 136                 if self.action == enumerations.REMOVE:
 137                         self.w_installupdate_dialog.set_title(self.parent._(\
 138                             "Remove Confirmation"))
 139                         self.w_information_label.set_text(\
 140                             self.parent._("This action affects other packages.\n" + \
 141                             "Review the packages to be removed.\n" + \
 142                             "Click Next to continue."))
 143                         self.w_installing_dialog.set_title(\
 144                             self.parent._("Removing Packages"))
 145                         self.w_createplan_dialog.set_title(\
 146                             self.parent._("Remove Check"))
 147                         self.w_installingdialog_label.set_text(\
 148                             self.parent._("Removing Packages..."))
 149 
 150                 try:
 151                         dic_createplan = \
 152                             {
 153                                 "on_cancelcreateplan_clicked": \
 154                                     self.__on_cancelcreateplan_clicked,
 155                             }
 156                         dic_installupdate = \
 157                             {
 158                                 "on_cancel_button_clicked": \
 159                                     self.__on_cancel_button_clicked,
 160                                 "on_next_button_clicked":self.__on_next_button_clicked,
 161                             }
 162                         dic_downloadingfiles = \
 163                             {
 164                                 "on_canceldownload_clicked": \
 165                                     self.__on_cancel_download_clicked,
 166                             }
 167                         dic_networkdown = \
 168                             {
 169                                 "on_networkdown_close_clicked": \
 170                                     self.__on_networkdown_close_clicked,
 171                             }
 172                         w_tree_createplan.signal_autoconnect(dic_createplan)
 173                         w_tree_installupdate.signal_autoconnect(dic_installupdate)
 174                         w_tree_downloadingfiles.signal_autoconnect(dic_downloadingfiles)
 175                         w_tree_networkdown.signal_autoconnect(dic_networkdown)
 176                 except AttributeError, error:
 177                         print self.parent._('GUI will not respond to any event! %s. \
 178                             Check installupdate.py signals') \
 179                             % error
 180                 # XXX Hidden until progress will give information about fmri 
 181                 self.w_installingdialog_expander.hide()
 182                 pulse_t = Thread(target = self.__progressdialog_progress_pulse)
 183                 thread = Thread(target = self.__plan_the_install_updateimage_ex, \
 184                     args = (install_list, ))
 185                 pulse_t.start()
 186                 thread.start()
 187                 self.w_createplan_label.set_text(\
 188                     self.parent._("Checking package dependencies..."))
 189                 self.w_createplancancel_button.set_sensitive(True)           
 190                 self.w_createplan_dialog.show()
 191 
 192         def __on_cancelcreateplan_clicked(self, widget):
 193                 '''Handler for signal send by cancel button, which user might press during
 194                 evaluation stage - while the dialog is creating plan'''
 195                 if self.api_o.can_be_canceled():
 196                         Thread(target = self.api_o.cancel, args = ()).start()
 197                         self.w_createplan_label.set_text(\
 198                             self.parent._("Canceling..."))
 199                         self.w_createplancancel_button.set_sensitive(False)
 200 
 201         def __on_cancel_button_clicked(self, widget):
 202                 '''Handler for signal send by cancel button, which is available for the 
 203                 user after evaluation stage on the dialog showing what will be installed
 204                 or updated'''
 205                 self.api_o.reset()
 206                 self.w_installupdate_dialog.destroy()
 207 
 208         def __on_next_button_clicked(self, widget):
 209                 '''Handler for signal send by next button, which is available for the 
 210                 user after evaluation stage on the dialog showing what will be installed
 211                 or updated'''
 212                 self.w_installupdate_dialog.hide()
 213                 download_thread = Thread(target = self.__prepare_stage_ex, \
 214                     args = (self.api_o, ))
 215                 download_thread.start()
 216 
 217         def __on_cancel_download_clicked(self, widget):
 218                 '''Handler for signal send by cancel button, which user might press during
 219                 download stage.'''
 220                 if self.api_o.can_be_canceled():
 221                         Thread(target = self.api_o.cancel, args = ()).start()
 222                         self.w_download_label.set_text(\
 223                             self.parent._("Canceling..."))
 224                         self.w_canceldownload_button.set_sensitive(False)
 225 
 226         def __on_networkdown_close_clicked(self, widget):
 227                 '''Handler for signal send by close button on the dialog showing that
 228                 there was some problem with the network connection.'''
 229                 self.w_networkdown_dialog.destroy()
 230 
 231         def __update_createplan_progress(self, action):
 232                 buf = self.w_createplan_textview.get_buffer()
 233                 textiter = buf.get_end_iter()
 234                 buf.insert(textiter, action)
 235                 
 236         def __progressdialog_progress_pulse(self):
 237                 while not self.progress_stop_timer_thread:
 238                         gobject.idle_add(self.w_createplan_progressbar.pulse)
 239                         time.sleep(0.1)
 240 
 241         def __update_download_progress(self, cur_bytes, total_bytes):
 242                 prog = float(cur_bytes)/total_bytes
 243                 self.w_download_progressbar.set_fraction(prog)
 244                 size_a_str = ""
 245                 size_b_str = ""
 246                 if cur_bytes > 0:
 247                         size_a_str = pkg.misc.bytes_to_str(cur_bytes)
 248                 if total_bytes > 0:
 249                         size_b_str = pkg.misc.bytes_to_str(total_bytes)
 250                 c = "Downloaded: " + size_a_str + " / " + size_b_str
 251                 self.w_download_progressbar.set_text(c)
 252 
 253         def __update_install_progress(self, current, total):
 254                 prog = float(current)/total
 255                 self.w_installing_progressbar.set_fraction(prog)
 256 
 257         def __update_install_pulse(self):
 258                 while not self.progress_stop_timer_thread:
 259                         self.progress_stop_timer_running = True
 260                         gobject.idle_add(self.w_installing_progressbar.pulse)
 261                         time.sleep(0.1)
 262                 self.progress_stop_timer_running = False
 263 
 264         def __plan_the_install_updateimage_ex(self, list_of_packages):
 265                 try:
 266                         self.__plan_the_install_updateimage(list_of_packages)
 267                 except:
 268                         self.progress_stop_timer_thread = True
 269                         gobject.idle_add(self.w_createplan_dialog.hide)
 270                         msg = self.parent._("An unknown error occured while " + \
 271                             "preparing the\nlist of packages\n\nPlease let the " + \
 272                             "developers know about this problem by filing\n" + \
 273                             "a bug at http://defect.opensolaris.org")
 274                         msg += "\n\nException value: " + "\n" + str(sys.exc_value)
 275                         gobject.idle_add(self.parent.error_occured, msg)
 276                         sys.exc_clear()
 277                         return
 278 
 279         def __plan_the_install_updateimage(self, list_of_packages):
 280                 '''Function which plans the image'''
 281                 gobject.idle_add(self.__update_createplan_progress, \
 282                     self.parent._("Evaluation started.\n" + \
 283                         "Gathering packages information, please wait...\n"))
 284                 stuff_to_do = False
 285                 if self.action == enumerations.INSTALL_UPDATE:
 286                         try:
 287                                 stuff_to_do = self.api_o.plan_install(list_of_packages, \
 288                                     filters = [])
 289                         except api_errors.InvalidCertException:
 290                                 self.progress_stop_timer_thread = True
 291                                 gobject.idle_add(self.w_createplan_dialog.hide)
 292                                 msg = self.parent._("Invalid repository certificate." + \
 293                                     "\nYou can not install packages from the" + \
 294                                     "\nrepopsitory, which doesn't have" + \
 295                                     "\nappropriate certificate.")
 296                                 gobject.idle_add(self.parent.error_occured, msg)
 297                                 return
 298                         except api_errors.PlanCreationException:
 299                                 self.progress_stop_timer_thread = True
 300                                 gobject.idle_add(self.w_createplan_dialog.hide)
 301                                 msg = self.parent._("Installation failed during\n" + \
 302                                    "creating plan, please check your network\n" + \
 303                                    "connection and you can try to re-run the operation.")
 304                                 gobject.idle_add(self.parent.error_occured, msg)
 305                                 return
 306                         except api_errors.InventoryException:
 307                                 self.progress_stop_timer_thread = True
 308                                 gobject.idle_add(self.w_createplan_dialog.hide)
 309                                 msg = self.parent._("Install failed.\n" + \
 310                                    "The inventory is not correct.")
 311                                 gobject.idle_add(self.parent.error_occured, msg)
 312                                 return
 313                         except api_errors.CanceledException:
 314                                 self.progress_stop_timer_thread = True
 315                                 gobject.idle_add(self.w_createplan_dialog.hide)
 316                                 return
 317                         except api_errors.CatalogRefreshException:
 318                                 # network problem
 319                                 self.progress_stop_timer_thread = True
 320                                 gobject.idle_add(self.w_createplan_dialog.hide)
 321                                 msg = self.parent._("Please check the network " + \
 322                                     "connection.\nIs the repository accessible?")
 323                                 gobject.idle_add(self.parent.error_occured, msg)
 324                                 return
 325 
 326                 elif self.action == enumerations.REMOVE:
 327                         try:
 328                                 plan_uninstall = self.api_o.plan_uninstall
 329                                 stuff_to_do = \
 330                                     plan_uninstall(list_of_packages, False, False)
 331                         except api_errors.PlanCreationException:
 332                                 self.progress_stop_timer_thread = True
 333                                 gobject.idle_add(self.w_createplan_dialog.hide)
 334                                 msg = self.parent._("Update All failed during\n" + \
 335                                    "creating plan, please check your network\n" + \
 336                                    "connection and you can try to re-run the update all.")
 337                                 gobject.idle_add(self.parent.error_occured, msg)
 338                                 return
 339                         except api_errors.CanceledException:
 340                                 self.progress_stop_timer_thread = True
 341                                 gobject.idle_add(self.w_createplan_dialog.hide)
 342                                 return
 343                         except api_errors.NonLeafPackageException, nlpe:
 344                                 self.progress_stop_timer_thread = True
 345                                 gobject.idle_add(self.__afterplan_nonleaf_dialog, nlpe)
 346                                 return
 347 
 348                 elif self.action == enumerations.IMAGE_UPDATE:  
 349                         try:
 350                                 # we are passing force, since we already checked if the
 351                                 # SUNWipkg and SUNWipkg-gui are up to date.
 352                                 stuff_to_do, opensolaris_image, cre = \
 353                                     self.api_o.plan_update_all(sys.argv[0], \
 354                                     refresh_catalogs = False, \
 355                                     noexecute = False, force = True)
 356                                 if cre and not cre.succeeded:
 357                                         self.progress_stop_timer_thread = True
 358                                         gobject.idle_add(self.w_createplan_dialog.hide)
 359                                         msg = self.parent._("Unexpected failure with" + \
 360                                             "\ncatalog refresh during image-update" + \
 361                                             " while \ndetermining what to update.")
 362                                         gobject.idle_add(self.parent.error_occured, msg)
 363                                         return
 364                         except api_errors.CatalogRefreshException:
 365                                 self.progress_stop_timer_thread = True
 366                                 gobject.idle_add(self.w_createplan_dialog.hide)
 367                                 msg = self.parent._("Update All failed during " + \
 368                                     "catalog refresh\n")
 369                                 gobject.idle_add(self.parent.error_occured, msg)
 370                                 return
 371                         except api_errors.IpkgOutOfDateException:
 372                                 self.progress_stop_timer_thread = True
 373                                 gobject.idle_add(self.w_createplan_dialog.hide)
 374                                 msg = self.parent._("pkg(5) appears to be out of " + \
 375                                     "date and should be\n updated before running " + \
 376                                     "Update All.\nPlease update SUNWipkg package")
 377                                 gobject.idle_add(self.parent.error_occured, msg)
 378                                 return
 379                         except api_errors.PlanCreationException:
 380                                 self.progress_stop_timer_thread = True
 381                                 gobject.idle_add(self.w_createplan_dialog.hide)
 382                                 msg = self.parent._("Update All failed during\n" + \
 383                                    "creating plan, please check your network\n" + \
 384                                    "connection and you can try to re-run the update all.")
 385                                 gobject.idle_add(self.parent.error_occured, msg)
 386                                 return
 387                         except api_errors.CanceledException:
 388                                 self.progress_stop_timer_thread = True
 389                                 gobject.idle_add(self.w_createplan_dialog.hide)
 390                                 return
 391                         except api_errors.NetworkUnavailableException:
 392                                 self.progress_stop_timer_thread = True
 393                                 gobject.idle_add(self.w_createplan_dialog.hide)
 394                                 msg = self.parent._("Please check the network " + \
 395                                     "connection.\nIs the repository accessible?")
 396                                 gobject.idle_add(self.parent.error_occured, msg)
 397                                 return
 398                 if stuff_to_do:
 399                         gobject.idle_add(self.__afterplan_confirmation_dialog, self.api_o)
 400 
 401         def __prepare_stage_ex(self, api_o):
 402                 try:
 403                         self.__prepare_stage(api_o)
 404                 except:
 405                         gobject.idle_add(self.w_downloadingfiles_dialog.hide)
 406                         msg = self.parent._("An unknown error occured while " + \
 407                             "downloading the files\n\nPlease let the developers know " + \
 408                             "about this problem by filing\na bug " + \
 409                             "at http://defect.opensolaris.org")
 410                         msg += "\n\nException value: " + "\n" + str(sys.exc_value)
 411                         gobject.idle_add(self.parent.error_occured, msg)
 412                         sys.exc_clear()
 413 
 414         def __prepare_stage(self, api_o):
 415                 gobject.idle_add(self.w_downloadingfiles_dialog.show)
 416                 text = self.parent._("Preparing to download packages, please wait...")
 417                 gobject.idle_add(self.__add_info_to_downloadtext, text)
 418                 try:
 419                         api_o.prepare()
 420                 except (api_errors.ProblematicPermissionsIndexException, \
 421                     api_errors.PlanMissingException):
 422                         gobject.idle_add(self.w_downloadingfiles_dialog.hide)
 423                         msg = self.parent._("An error occured while " + \
 424                             "downloading the files\nPlease check your permissions and" + \
 425                             "\nnetwork connection.")
 426                         gobject.idle_add(self.parent.error_occured, msg)
 427                         return
 428                 except api_errors.CanceledException:
 429                         gobject.idle_add(self.w_downloadingfiles_dialog.hide)
 430                         return
 431                 except (TransferTimedOutException, TransportException):
 432                         gobject.idle_add(self.w_downloadingfiles_dialog.hide)
 433                         gobject.idle_add(self.w_networkdown_dialog.show)
 434                         return
 435                 except URLError:
 436                         gobject.idle_add(self.w_downloadingfiles_dialog.hide)
 437                         gobject.idle_add(self.w_networkdown_dialog.show)
 438                         return
 439                 self.__execute_stage_ex(api_o)
 440                 
 441         def __execute_stage_ex(self, api_o):
 442                 try:
 443                         self.__execute_stage(api_o)
 444                 except:
 445                         gobject.idle_add(self.w_installing_dialog.hide)
 446                         msg = self.parent._("An unknown error occured while " + \
 447                             "installing\nupdating or removing packages" + \
 448                             "\n\nPlease let the developers know about this problem " + \
 449                             "by filing\na bug at http://defect.opensolaris.org")
 450                         msg += "\n\nException value: " + "\n" + str(sys.exc_value)
 451                         gobject.idle_add(self.parent.error_occured, msg)
 452                         sys.exc_clear()
 453                         return
 454 
 455         def __execute_stage(self, api_o):
 456                 text = self.parent._("Installing Packages...")
 457                 gobject.idle_add(self.w_downloadingfiles_dialog.hide)
 458                 gobject.idle_add(self.w_installingdialog_label.set_text, text)
 459                 gobject.idle_add(self.w_installing_dialog.show)
 460                 try:
 461                         api_o.execute_plan()
 462                 except api_errors.CorruptedIndexException:
 463                         gobject.idle_add(self.w_installing_dialog.hide)
 464                         msg = self.parent._("There was an error during installation." + \
 465                             "\nThe index is corrupted. You might wan't try to fix" + \
 466                             "\nthis problem by running command:" + \
 467                             "\npfexec pkg rebuild-index")
 468                         gobject.idle_add(self.parent.error_occured, msg)
 469                         return
 470                 except api_errors.ProblematicPermissionsIndexException:
 471                         gobject.idle_add(self.w_installing_dialog.hide)
 472                         msg = self.parent._("An error occured while " + \
 473                             "installing the files\nPlease check your permissions")
 474                         gobject.idle_add(self.parent.error_occured, msg)
 475                         return
 476                 except api_errors.ImageplanStateException:
 477                         gobject.idle_add(self.w_installing_dialog.hide)
 478                         msg = self.parent._("There was an error during installation." + \
 479                             "\nThe State of the image is incorrect and the operation" + \
 480                             "\ncan't be finished.")
 481                         gobject.idle_add(self.parent.error_occured, msg)
 482                         return
 483                 except api_errors.ImageUpdateOnLiveImageException:
 484                         gobject.idle_add(self.w_installing_dialog.hide)
 485                         msg = self.parent._("This is an Live Image. The install" + \
 486                             "\noperation can't be performed.")
 487                         gobject.idle_add(self.parent.error_occured, msg)
 488                         return
 489                 except api_errors.PlanMissingException:
 490                         gobject.idle_add(self.w_installing_dialog.hide)
 491                         msg = self.parent._("There was an error during installation." + \
 492                             "\nThe Plan of the operation is missing and the operation" + \
 493                             "\ncan't be finished.")
 494                         gobject.idle_add(self.parent.error_occured, msg)
 495                         return
 496                 gobject.idle_add(self.__operations_done)
 497 
 498         def __operations_done(self):
 499                 if self.parent != None:
 500                         if not self.ips_update and not self.action == \
 501                             enumerations.IMAGE_UPDATE:
 502                                 self.__update_package_list()
 503                 self.w_installing_dialog.hide()
 504 
 505                 if self.ips_update:
 506                         self.parent.shutdown_after_ips_update()
 507                 elif self.action == enumerations.IMAGE_UPDATE:
 508                         self.parent.shutdown_after_image_update()
 509 
 510         def __update_package_list(self):
 511                 self.parent.update_package_list(self.update_list)
 512 
 513         def __add_info_to_downloadtext(self, text):
 514                 '''Function which adds another line text in the "more details" download 
 515                 dialog'''
 516                 buf = self.w_download_textview.get_buffer()
 517                 textiter = buf.get_end_iter()
 518                 if text:
 519                         buf.insert(textiter, text + "\n")
 520 
 521         def __add_info_to_installtext(self, text):
 522                 '''Function which adds another line text in the "more details" install 
 523                 dialog'''
 524                 buf = self.w_installing_textview.get_buffer()
 525                 textiter = buf.get_end_iter()
 526                 buf.insert(textiter, text)
 527 
 528         def cat_output_start(self): 
 529                 return
 530 
 531         def cat_output_done(self): 
 532                 return
 533 
 534         def eval_output_start(self):
 535                 '''Called by progress tracker when the evaluation of the packages just 
 536                 started.'''
 537                 return
 538 
 539         def eval_output_progress(self):
 540                 '''Called by progress tracker each time some package was evaluated. The
 541                 call is being done by calling progress tracker evaluate_progress() 
 542                 function'''
 543                 cur_eval_fmri = self.eval_cur_fmri
 544                 gobject.idle_add(self.__update_createplan_progress, \
 545                     self.parent._("Evaluating: %s\n") % cur_eval_fmri)
 546 
 547         def eval_output_done(self):
 548                 ninst = self.eval_goal_install_npkgs
 549                 nupdt = self.eval_goal_update_npkgs
 550                 nremv = self.eval_goal_remove_npkgs
 551                 nbytes = self.dl_goal_nbytes
 552                 gobject.idle_add(self.__eval_output_done, \
 553                     ninst, nupdt, nremv, nbytes)
 554 
 555         def __eval_output_done(self, ninst, nupdt, nremv, nbytes):
 556                 label_text = ""
 557                 if nupdt > 0 and nupdt != 1:
 558                         label_text += \
 559                             self.parent._("%d packages will be updated\n") % nupdt
 560                 elif nupdt == 1:
 561                         label_text += \
 562                             self.parent._("%d package will be updated\n") % nupdt
 563                 if ninst > 0 and ninst != 1:
 564                         label_text += \
 565                             self.parent._("%d packages will be installed\n\n") % ninst
 566                 elif ninst == 1:
 567                         label_text += \
 568                             self.parent._("%d package will be installed\n\n") % ninst
 569                 if nremv > 0 and nremv != 1:
 570                         label_text += \
 571                             self.parent._("%d packages will be removed\n\n") % nremv
 572                 elif nremv == 1:
 573                         label_text += \
 574                             self.parent._("%d package will be removed\n\n") % nremv
 575                 if not nbytes:
 576                         nbytes = 0
 577                 if nbytes > 0:
 578                         size_str = pkg.misc.bytes_to_str(nbytes)
 579                         label_text += self.parent._("%s will be downloaded") % size_str
 580                 self.w_summary_label.set_text(label_text)
 581 
 582         def __afterplan_nonleaf_dialog(self, non_leaf_exception):
 583                 self.w_installupdate_dialog.set_title(self.parent._(\
 584                     "Remove Confirmation"))
 585                 self.w_information_label.set_text(\
 586                     self.parent._("This action couldn't be finished.\n" + \
 587                     "Some of the selected packages depends on other.\n" + \
 588                     "Please review the dependencies."))
 589                 self.w_next_button.hide()
 590                 self.w_cancel_button.set_label(self.parent._("Close"))
 591                 pkg_blocker = non_leaf_exception[0]
 592                 treestore = gtk.TreeStore(str)
 593                 pkg_iter = treestore.append(None, [pkg_blocker])
 594                 for pkg_a in non_leaf_exception[1]:
 595                         treestore.append(pkg_iter, [pkg_a])
 596                 self.w_review_treeview.set_model(treestore)
 597                 self.w_review_treeview.expand_all()
 598                 label_text = self.parent._("None of the packages will be removed")
 599                 self.w_summary_label.set_text(label_text)
 600                 self.progress_stop_timer_thread = True
 601                 self.w_createplan_dialog.hide()
 602                 self.w_installupdate_dialog.show()
 603 
 604 
 605         def __afterplan_confirmation_dialog(self, api_o):
 606                 updated_installed = \
 607                     [
 608                         ["Packages To Be Installed:"],
 609                         ["Packages To Be Updated:"],
 610                         ["Packages To Be Removed:"]
 611                     ]
 612                 treestore = gtk.TreeStore(str)
 613                 install_iter = None 
 614                 updated_iter = None
 615                 remove_iter = None
 616                 plan = api_o.describe().get_changes()
 617                 for pkg_plan in plan:
 618                         origin_fmri = pkg_plan[0]
 619                         destination_fmri = pkg_plan[1]
 620                         if origin_fmri and destination_fmri:
 621                                 if not updated_iter:
 622                                         updated_iter = treestore.append(None, \
 623                                             updated_installed[1])
 624                                 pkg_a = self.__get_pkgstr_from_pkginfo(destination_fmri)
 625                                 treestore.append(updated_iter, [pkg_a])
 626                         elif not origin_fmri and destination_fmri:
 627                                 if not install_iter:
 628                                         install_iter = treestore.append(None, \
 629                                             updated_installed[0])
 630                                 pkg_a = self.__get_pkgstr_from_pkginfo(destination_fmri)
 631                                 treestore.append(install_iter, [pkg_a])
 632                         elif origin_fmri and not destination_fmri:
 633                                 if not remove_iter:
 634                                         remove_iter = treestore.append(None, \
 635                                             updated_installed[2])
 636                                 pkg_a = self.__get_pkgstr_from_pkginfo(origin_fmri)
 637                                 treestore.append(remove_iter, [pkg_a])
 638 
 639                 self.w_review_treeview.set_model(treestore)
 640                 self.w_review_treeview.expand_all()
 641                 self.progress_stop_timer_thread = True
 642                 self.w_createplan_dialog.hide()
 643                 self.w_installupdate_dialog.show()
 644 
 645         def __get_pkgstr_from_pkginfo(self, pkginfo):
 646                 dt_str = self.get_datetime(pkginfo.packaging_date)
 647                 s_ver = pkginfo.version
 648                 s_bran = pkginfo.branch
 649                 pkg_name = pkginfo.pkg_stem
 650                 if not pkg_name in self.update_list:
 651                         self.update_list.append(pkg_name)
 652                 l_ver = 0
 653                 version_pref = ""
 654                 while l_ver < len(s_ver) -1:
 655                         version_pref += "%d%s" % (s_ver[l_ver],".")
 656                         l_ver += 1
 657                 version_pref += "%d%s" % (s_ver[l_ver],"-")
 658                 l_ver = 0
 659                 version_suf = ""
 660                 while l_ver < len(s_bran) -1:
 661                         version_suf += "%d%s" % (s_bran[l_ver],".")
 662                         l_ver += 1
 663                 version_suf += "%d" % s_bran[l_ver]
 664                 pkg_version = version_pref + version_suf + dt_str
 665                 return pkg_name + "@" + pkg_version  
 666 
 667         def ver_output(self): 
 668                 return
 669 
 670         def ver_output_error(self, actname, errors): 
 671                 return
 672 
 673         def dl_output(self):
 674                 gobject.idle_add(self.__update_download_progress, \
 675                     self.dl_cur_nbytes, self.dl_goal_nbytes)
 676                 if self.prev_pkg != self.dl_cur_pkg:
 677                         self.prev_pkg = self.dl_cur_pkg
 678                         text = self.parent._("Downloading: ") + self.dl_cur_pkg
 679                         gobject.idle_add(self.__add_info_to_downloadtext, text)
 680                 return
 681 
 682         def dl_output_done(self):
 683                 return
 684 
 685         def act_output(self):
 686                 gobject.idle_add(self.__update_install_progress, \
 687                     self.act_cur_nactions, self.act_goal_nactions)
 688                 return
 689 
 690         def act_output_done(self):
 691                 return
 692 
 693         def ind_output(self):
 694                 self.progress_stop_timer_thread = False
 695                 gobject.idle_add(self.__indexing_progress)
 696                 return
 697 
 698         def __indexing_progress(self):
 699                 if not self.progress_stop_timer_running:
 700                         self.w_installingdialog_label.set_text(\
 701                             self.parent._("Creating packages index..."))
 702                         Thread(target = self.__update_install_pulse).start()
 703                         
 704         def ind_output_done(self):
 705                 self.progress_stop_timer_thread = True
 706                 return
 707 
 708         @staticmethod
 709         def get_datetime(date_time):
 710                 '''Support function for getting date from the API.'''
 711                 date_tmp = time.strptime(date_time, "%a %b %d %H:%M:%S %Y")
 712                 date_tmp2 = datetime.datetime(*date_tmp[0:5])
 713                 return date_tmp2.strftime(":%m%d")