Print this page
*** NO COMMENTS ***


   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 
  27 import gettext
  28 import sys

  29 from threading import Thread
  30 try:
  31         import gobject
  32         import gtk
  33         import gtk.glade
  34         import pygtk
  35         pygtk.require("2.0")
  36 except ImportError:
  37         sys.exit(1)
  38 import pkg.client.bootenv as bootenv
  39 import pkg.client.imageplan as imageplan


  40 import pkg.client.progress as progress
  41 import pkg.gui.enumerations as enumerations
  42 import pkg.gui.thread as guithread
  43 
  44 class Remove(progress.ProgressTracker):
  45         def __init__(self, remove_list, parent):
  46                 # XXX Workaround as BE is using msg(_("message")) 
  47                 # which bypasses the self._ mechanism the GUI is using
  48                 gettext.install("pkg","/usr/lib/locale")
  49                 progress.ProgressTracker.__init__(self)
  50                 self.gui_thread = guithread.ThreadRun()
  51                 self.remove_list = remove_list
  52                 self.parent = parent
  53                 #This is hack since we should show proper dialog.
  54                 self.error = None
  55                 self.ip = None


  56                 w_tree_createplan = gtk.glade.XML(parent.gladefile, "createplandialog2")
  57                 w_tree_removedialog = gtk.glade.XML(parent.gladefile, "removedialog")
  58                 w_tree_removingdialog = gtk.glade.XML(parent.gladefile, "removingdialog") 
  59                 self.w_createplan_dialog = \
  60                     w_tree_createplan.get_widget("createplandialog2")
  61                 self.w_createplan_textview = \
  62                     w_tree_createplan.get_widget("createplantextview2")
  63                 self.w_createplan_progressbar = \
  64                     w_tree_createplan.get_widget("createplanprogress2")






  65                 self.w_remove_dialog = w_tree_removedialog.get_widget("removedialog")
  66                 self.w_summary_label = w_tree_removedialog.get_widget("removelabel")
  67                 self.w_review_treeview = w_tree_removedialog.get_widget("treeview3")
  68                 self.w_next_button = w_tree_removedialog.get_widget("next_remove")
  69                 self.w_removing_dialog = \
  70                     w_tree_removingdialog.get_widget("removingdialog")
  71                 self.w_removing_progressbar = \
  72                     w_tree_removingdialog.get_widget("removingprogress")




  73                 self.w_createplan_progressbar.set_pulse_step(0.1)
  74                 remove_column = gtk.TreeViewColumn('Removed')
  75                 self.w_review_treeview.append_column(remove_column)
  76                 cell = gtk.CellRendererText()
  77                 remove_column.pack_start(cell, True)
  78                 remove_column.add_attribute(cell, 'text', 0)
  79                 self.w_review_treeview.expand_all()
  80                 try:
  81                         dic_createplan = \
  82                             {
  83                                 "on_cancelcreateplan2_clicked": \
  84                                     self.__on_cancelcreateplan_clicked,
  85                             }
  86                         dic_removedialog = \
  87                             {
  88                                 "on_cancel_remove_clicked": \
  89                                     self.__on_cancel_button_clicked,
  90                                 "on_next_remove_clicked":self.__on_next_button_clicked,
  91                             }
  92                         w_tree_createplan.signal_autoconnect(dic_createplan)
  93                         w_tree_removedialog.signal_autoconnect(dic_removedialog)
  94                 except AttributeError, error:
  95                         print self.parent._('GUI will not respond to any event! %s. \
  96                             Check remove.py signals') \
  97                             % error
  98                 list_of_packages = self.__prepare_list_of_packages()




  99                 thread = Thread(target = self.__plan_the_removeimage, \
 100                     args = (list_of_packages, ))

 101                 thread.start()



 102                 self.w_createplan_dialog.run()
 103                 return
 104 
 105         def __on_cancelcreateplan_clicked(self, widget):



 106                 self.gui_thread.cancel()
 107                 self.w_createplan_dialog.destroy()
 108 
 109         def __on_next_button_clicked(self, widget):


 110                 remove_thread = Thread(target = self.__remove_stage, args = ())
 111                 remove_thread.start()
 112 
 113         def __on_cancel_button_clicked(self, widget):
 114                 self.gui_thread.cancel()
 115                 self.w_remove_dialog.destroy()
 116 

 117         def __update_createplan_progress(self, action):
 118                 buf = self.w_createplan_textview.get_buffer()
 119                 textiter = buf.get_end_iter()
 120                 buf.insert(textiter, action)
 121                 self.w_createplan_progressbar.pulse()
 122 
 123         def __update_remove_progress(self, current, total):
 124                 prog = float(current)/total
 125                 self.w_removing_progressbar.set_fraction(prog)
 126 
 127         def __prepare_list_of_packages(self):
 128                 ''' This method return the dictionary of images for removal'''
 129                 fmri_to_remove = {}
 130                 for row in self.remove_list:
 131                         if row[enumerations.MARK_COLUMN]:
 132                                 image = row[enumerations.IMAGE_OBJECT_COLUMN]
 133                                 package = row[enumerations.INSTALLED_OBJECT_COLUMN]
 134                                 im = fmri_to_remove.get(image)
 135                                 if im:
 136                                         if package:
 137                                                 im.append(package)
 138                                 else:
 139                                         if package:
 140                                                 fmri_to_remove[image] = [package, ]
 141                 return fmri_to_remove
 142 
 143         def __plan_the_removeimage(self, list_of_packages):
 144                 '''Function which plans the image'''
 145                 self.gui_thread.run()
 146                 filters = []
 147                 for image in list_of_packages:
 148                         self.ip = imageplan.ImagePlan(image, self, filters = filters)
 149                         fmris = list_of_packages.get(image)
 150                         for fmri in fmris:
 151                                 if self.gui_thread.is_cancelled():


 152                                         return
 153                                 self.ip.propose_fmri_removal(fmri)
 154                         self.ip.state = imageplan.UNEVALUATED
 155                         self.ip.progtrack.evaluate_start()
 156                         for f in self.ip.target_rem_fmris[:]:
 157                                 gobject.idle_add(self.__update_createplan_progress, \
 158                                     self.parent._("Evaluating: %s\n") % f.get_fmri())
 159                                 try:
 160                                         self.ip.evaluate_fmri_removal(f)





 161                                 except imageplan.NonLeafPackageException, e:
 162                                         self.error = e[1]
 163                                         gobject.idle_add(self.ip.progtrack.evaluate_done)
 164                                         return   
 165                         self.ip.state = imageplan.EVALUATED_OK
 166                         image.imageplan = self.ip
 167                         gobject.idle_add(self.ip.progtrack.evaluate_done)
 168                 return
 169 
 170         def __remove_stage(self):
 171                 self.w_remove_dialog.hide()
 172                 self.w_removing_dialog.show()
 173                 self.ip.preexecute()
 174                 try:
 175                         be = bootenv.BootEnv(self.ip.image.get_root())
 176                 except RuntimeError:
 177                         be = bootenv.BootEnvNull(self.ip.image.get_root())
 178                 try:

 179                         self.ip.execute()
 180                 except RuntimeError:
 181                         be.restore_install_uninstall()










 182                 except Exception:
 183                         be.restore_install_uninstall()

 184                         raise
 185 







 186                 if self.ip.state == imageplan.EXECUTED_OK:
 187                         be.activate_install_uninstall()
 188                 else:
 189                         be.restore_install_uninstall()


























 190 
 191         def cat_output_start(self): 
 192                 return
 193 
 194         def cat_output_done(self): 
 195                 return
 196 
 197         def eval_output_start(self):
 198                 return
 199 
 200         def eval_output_progress(self): 
 201                 return
 202 
 203         def eval_output_done(self):
 204                 self.w_createplan_dialog.hide()


 205                 if self.gui_thread.is_cancelled():


 206                         return
 207                 self.w_remove_dialog.show()
 208                 packaged_removed = \
 209                     [
 210                         ["Packages To Be Removed:"],
 211                     ]
 212                 if self.ip.state != imageplan.EVALUATED_OK:
 213                         packaged_removed = \
 214                             [
 215                                 ["Cannot remove, due to the following dependencies:"],
 216                             ]
 217                 treestore = gtk.TreeStore(str)
 218                 remove_iter = None 
 219                 remove_count = 0
 220                 if self.ip.state == imageplan.EVALUATED_OK:
 221                         self.w_next_button.set_sensitive(True)
 222                         for package_plan in self.ip.pkg_plans:
 223                                 if package_plan.origin_fmri and not \
 224                                     package_plan.destination_fmri:
 225                                         if not remove_iter:
 226                                                 remove_iter = \
 227                                                     treestore.append(None, \


 231                                             pkg_fmri.version.get_short_version()
 232                                         pkg = package_plan.origin_fmri.get_name() + \
 233                                             "@" + pkg_version
 234                                         remove_count = remove_count + 1
 235                                         treestore.append(remove_iter, [pkg])
 236                 else:
 237                         self.w_next_button.set_sensitive(False)
 238                         if self.error:
 239                                 for package in self.error:
 240                                         if not remove_iter:
 241                                                 remove_iter = \
 242                                                     treestore.append(None, \
 243                                                     packaged_removed[0])
 244                                         treestore.append(remove_iter, [package])
 245 
 246                 self.w_review_treeview.set_model(treestore)
 247                 self.w_review_treeview.expand_all()
 248                 remove_str = self.parent._("%d packages will be removed\n\n")
 249                 if remove_count == 1:
 250                         remove_str = self.parent._("%d package will be removed\n\n")
 251                 self.w_summary_label.set_text(remove_str % remove_count)
 252                 return True



 253 
 254         def ver_output(self): 
 255                 return
 256 
 257         def ver_output_error(self, actname, errors): 
 258                 return
 259 
 260         def dl_output(self): 
 261                 return
 262 
 263         def dl_output_done(self): 
 264                 return
 265 
 266         def act_output(self):


 267                 gobject.idle_add(self.__update_remove_progress, \
 268                     self.ip.progtrack.act_cur_nactions, \
 269                     self.ip.progtrack.act_goal_nactions)
 270                 return
 271 
 272         def act_output_done(self):
 273                 if self.parent != None:
 274                         self.parent.update_package_list()
 275                 self.w_removing_dialog.hide()
 276                 return
 277 
 278         def ind_output(self):


 279                 return
 280 






 281         def ind_output_done(self):

 282                 return


   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 
  27 import gettext
  28 import sys
  29 import time
  30 from threading import Thread
  31 try:
  32         import gobject
  33         import gtk
  34         import gtk.glade
  35         import pygtk
  36         pygtk.require("2.0")
  37 except ImportError:
  38         sys.exit(1)
  39 import pkg.client.bootenv as bootenv
  40 import pkg.client.imageplan as imageplan
  41 import pkg.search_errors as search_errors
  42 import pkg.indexer as indexer
  43 import pkg.client.progress as progress
  44 import pkg.gui.enumerations as enumerations
  45 import pkg.gui.thread as guithread
  46 
  47 class Remove(progress.ProgressTracker):
  48         def __init__(self, remove_list, parent):
  49                 # XXX Workaround as BE is using msg(_("message")) 
  50                 # which bypasses the self._ mechanism the GUI is using
  51                 gettext.install("pkg","/usr/lib/locale")
  52                 progress.ProgressTracker.__init__(self)
  53                 self.gui_thread = guithread.ThreadRun()
  54                 self.remove_list = remove_list
  55                 self.parent = parent
  56                 #This is hack since we should show proper dialog.
  57                 self.error = None
  58                 self.ip = None
  59                 self.progress_stop_timer_thread = False
  60                 self.progress_stop_timer_running = False
  61                 w_tree_createplan = gtk.glade.XML(parent.gladefile, "createplandialog2")
  62                 w_tree_removedialog = gtk.glade.XML(parent.gladefile, "removedialog")
  63                 w_tree_removingdialog = gtk.glade.XML(parent.gladefile, "removingdialog") 
  64                 self.w_createplan_dialog = \
  65                     w_tree_createplan.get_widget("createplandialog2")
  66                 self.w_createplan_textview = \
  67                     w_tree_createplan.get_widget("createplantextview2")
  68                 self.w_createplan_progressbar = \
  69                     w_tree_createplan.get_widget("createplanprogress2")
  70                 self.w_createplan_expander = \
  71                     w_tree_createplan.get_widget("expander7")      
  72                 self.w_createplan_label = \
  73                     w_tree_createplan.get_widget("packagedependencies5")  
  74                 self.w_createplancancel_button = \
  75                     w_tree_createplan.get_widget("cancelcreateplan2")                      
  76                 self.w_remove_dialog = w_tree_removedialog.get_widget("removedialog")
  77                 self.w_summary_label = w_tree_removedialog.get_widget("removelabel")
  78                 self.w_review_treeview = w_tree_removedialog.get_widget("treeview3")
  79                 self.w_next_button = w_tree_removedialog.get_widget("next_remove")
  80                 self.w_removing_dialog = \
  81                     w_tree_removingdialog.get_widget("removingdialog")
  82                 self.w_removing_progressbar = \
  83                     w_tree_removingdialog.get_widget("removingprogress")
  84                 self.w_removingdialog_label = \
  85                     w_tree_removingdialog.get_widget("packagedependencies4")
  86                 self.w_removingdialog_expander = \
  87                     w_tree_removingdialog.get_widget("expander6") 
  88                 self.w_createplan_progressbar.set_pulse_step(0.1)
  89                 remove_column = gtk.TreeViewColumn('Removed')
  90                 self.w_review_treeview.append_column(remove_column)
  91                 cell = gtk.CellRendererText()
  92                 remove_column.pack_start(cell, True)
  93                 remove_column.add_attribute(cell, 'text', 0)
  94                 self.w_review_treeview.expand_all()
  95                 try:
  96                         dic_createplan = \
  97                             {
  98                                 "on_cancelcreateplan2_clicked": \
  99                                     self.__on_cancelcreateplan_clicked,
 100                             }
 101                         dic_removedialog = \
 102                             {
 103                                 "on_cancel_remove_clicked": \
 104                                     self.__on_cancel_button_clicked,
 105                                 "on_next_remove_clicked":self.__on_next_button_clicked,
 106                             }
 107                         w_tree_createplan.signal_autoconnect(dic_createplan)
 108                         w_tree_removedialog.signal_autoconnect(dic_removedialog)
 109                 except AttributeError, error:
 110                         print self.parent._('GUI will not respond to any event! %s. \
 111                             Check remove.py signals') \
 112                             % error
 113                 list_of_packages = self.__prepare_list_of_packages()
 114                 # XXX Hidden until progress will give information about fmri
 115                 self.w_createplan_expander.hide()
 116                 self.w_removingdialog_expander.hide()
 117                 pulse_t = Thread(target = self.__progressdialog_progress_pulse)
 118                 thread = Thread(target = self.__plan_the_removeimage, \
 119                     args = (list_of_packages, ))
 120                 pulse_t.start()
 121                 thread.start()
 122                 self.w_createplan_label.set_text(\
 123                     self.parent._("Checking package dependencies..."))
 124                 self.w_createplancancel_button.set_sensitive(True)
 125                 self.w_createplan_dialog.run()
 126                 return
 127 
 128         def __on_cancelcreateplan_clicked(self, widget):         
 129                 self.w_createplan_label.set_text(\
 130                     self.parent._("Canceling..."))
 131                 self.w_createplancancel_button.set_sensitive(False)                    
 132                 self.gui_thread.cancel()

 133 
 134         def __on_next_button_clicked(self, widget):
 135                 self.w_remove_dialog.hide()
 136                 self.w_removing_dialog.show()
 137                 remove_thread = Thread(target = self.__remove_stage, args = ())
 138                 remove_thread.start()
 139 
 140         def __on_cancel_button_clicked(self, widget):
 141                 self.gui_thread.cancel()
 142                 self.w_remove_dialog.hide()
 143 
 144         # XXX Not used until progress will give information about fmri
 145         def __update_createplan_progress(self, action):
 146                 buf = self.w_createplan_textview.get_buffer()
 147                 textiter = buf.get_end_iter()
 148                 buf.insert(textiter, action)
 149                 self.w_createplan_progressbar.pulse()
 150 
 151         def __update_remove_progress(self, current, total):
 152                 prog = float(current)/total
 153                 self.w_removing_progressbar.set_fraction(prog)
 154 
 155         def __prepare_list_of_packages(self):
 156                 ''' This method return the dictionary of images for removal'''
 157                 fmri_to_remove = {}
 158                 for row in self.remove_list:
 159                         if row[enumerations.MARK_COLUMN]:
 160                                 image = row[enumerations.IMAGE_OBJECT_COLUMN]
 161                                 package = row[enumerations.INSTALLED_OBJECT_COLUMN]
 162                                 im = fmri_to_remove.get(image)
 163                                 if im:
 164                                         if package:
 165                                                 im.append(package)
 166                                 else:
 167                                         if package:
 168                                                 fmri_to_remove[image] = [package, ]
 169                 return fmri_to_remove
 170 
 171         def __plan_the_removeimage(self, list_of_packages):
 172                 '''Function which plans the image'''
 173                 self.gui_thread.run()
 174                 filters = []
 175                 for image in list_of_packages:
 176                         self.ip = imageplan.ImagePlan(image, self, filters = filters)
 177                         fmris = list_of_packages.get(image)
 178                         for fmri in fmris:
 179                                 if self.gui_thread.is_cancelled():
 180                                         self.progress_stop_timer_thread = True
 181                                         gobject.idle_add(self.w_createplan_dialog.hide)
 182                                         return
 183                                 self.ip.propose_fmri_removal(fmri)





 184                         try:
 185                                 self.ip.evaluate()
 186                                 if self.gui_thread.is_cancelled():
 187                                         self.progress_stop_timer_thread = True
 188                                         gobject.idle_add(self.w_createplan_dialog.hide)
 189                                         return
 190                                 image.imageplan = self.ip
 191                         except imageplan.NonLeafPackageException, e:
 192                                         self.error = e[1]
 193                                         self.ip.progtrack.evaluate_done()
 194                                         return



 195                 return
 196 
 197         def __remove_stage(self):


 198                 self.ip.preexecute()
 199                 try:
 200                         be = bootenv.BootEnv(self.ip.image.get_root())
 201                 except RuntimeError:
 202                         be = bootenv.BootEnvNull(self.ip.image.get_root())
 203                 try:
 204                         ret_code = 0
 205                         self.ip.execute()
 206                 except RuntimeError:
 207                         be.restore_install_uninstall()
 208                 except search_errors.InconsistentIndexException, e:
 209                         ret_code = 2
 210                 except search_errors.PartialIndexingException, e:
 211                         ret_code = 2
 212                 except search_errors.ProblematicPermissionsIndexException, e:
 213                         ret_code = 2
 214                 except KeyError, e:
 215                         # XXX KeyError was seen while problem with
 216                         # creating index
 217                         ret_code = 2
 218                 except Exception:
 219                         be.restore_install_uninstall()
 220                         gobject.idle_add(self.w_removing_dialog.hide)
 221                         raise
 222 
 223                 if ret_code == 2:
 224                         return_code = 0
 225                         return_code = self.__rebuild_index()
 226                         if return_code == 1:
 227                                 gobject.idle_add(self.w_removing_dialog.hide)
 228                                 return
 229 
 230                 if self.ip.state == imageplan.EXECUTED_OK:
 231                         be.activate_install_uninstall()
 232                 else:
 233                         be.restore_install_uninstall()
 234                 gobject.idle_add(self.w_removing_dialog.hide)
 235 
 236         def __rebuild_index(self):
 237                 '''Code duplication from pkg(1):
 238                        Forcibly rebuild the search indexes. Will remove existing indexes
 239                        and build new ones from scratch.'''
 240                 quiet = False
 241                 
 242                 try:
 243                         self.ip.image.rebuild_search_index(self.ip.progtrack)
 244                 except search_errors.InconsistentIndexException, iie:
 245                         return 1
 246                 except search_errors.ProblematicPermissionsIndexException, ppie:
 247                         return 1
 248                         
 249         def __progressdialog_progress_pulse(self):
 250                 while not self.progress_stop_timer_thread:
 251                         gobject.idle_add(self.w_createplan_progressbar.pulse)
 252                         time.sleep(0.1)
 253 
 254         def __removedialog_progress_pulse(self):
 255                 while not self.progress_stop_timer_thread:
 256                         self.progress_stop_timer_running = True
 257                         gobject.idle_add(self.w_removing_progressbar.pulse)
 258                         time.sleep(0.1)
 259                 self.progress_stop_timer_running = False
 260                 
 261         def cat_output_start(self): 
 262                 return
 263 
 264         def cat_output_done(self): 
 265                 return
 266 
 267         def eval_output_start(self):
 268                 return
 269 
 270         def eval_output_progress(self): 
 271                 return
 272 
 273         def eval_output_done(self):
 274             gobject.idle_add(self.__eval_output_done)
 275             
 276         def __eval_output_done(self):
 277                 if self.gui_thread.is_cancelled():
 278                         self.progress_stop_timer_thread = True
 279                         self.w_createplan_dialog.hide()
 280                         return

 281                 packaged_removed = \
 282                     [
 283                         ["Packages To Be Removed:"],
 284                     ]
 285                 if self.ip.state != imageplan.EVALUATED_OK:
 286                         packaged_removed = \
 287                             [
 288                                 ["Cannot remove, due to the following dependencies:"],
 289                             ]
 290                 treestore = gtk.TreeStore(str)
 291                 remove_iter = None 
 292                 remove_count = 0
 293                 if self.ip.state == imageplan.EVALUATED_OK:
 294                         self.w_next_button.set_sensitive(True)
 295                         for package_plan in self.ip.pkg_plans:
 296                                 if package_plan.origin_fmri and not \
 297                                     package_plan.destination_fmri:
 298                                         if not remove_iter:
 299                                                 remove_iter = \
 300                                                     treestore.append(None, \


 304                                             pkg_fmri.version.get_short_version()
 305                                         pkg = package_plan.origin_fmri.get_name() + \
 306                                             "@" + pkg_version
 307                                         remove_count = remove_count + 1
 308                                         treestore.append(remove_iter, [pkg])
 309                 else:
 310                         self.w_next_button.set_sensitive(False)
 311                         if self.error:
 312                                 for package in self.error:
 313                                         if not remove_iter:
 314                                                 remove_iter = \
 315                                                     treestore.append(None, \
 316                                                     packaged_removed[0])
 317                                         treestore.append(remove_iter, [package])
 318 
 319                 self.w_review_treeview.set_model(treestore)
 320                 self.w_review_treeview.expand_all()
 321                 remove_str = self.parent._("%d packages will be removed\n\n")
 322                 if remove_count == 1:
 323                         remove_str = self.parent._("%d package will be removed\n\n")
 324                 text = remove_str % remove_count
 325                 self.w_summary_label.set_text(text)
 326                 self.progress_stop_timer_thread = True
 327                 self.w_createplan_dialog.hide()
 328                 self.w_remove_dialog.show()
 329 
 330         def ver_output(self): 
 331                 return
 332 
 333         def ver_output_error(self, actname, errors): 
 334                 return
 335 
 336         def dl_output(self): 
 337                 return
 338 
 339         def dl_output_done(self): 
 340                 return
 341 
 342         def act_output(self):
 343                 text = self.parent._("Removing Packages...")
 344                 gobject.idle_add(self.w_removingdialog_label.set_text, text)
 345                 gobject.idle_add(self.__update_remove_progress, \
 346                     self.ip.progtrack.act_cur_nactions, \
 347                     self.ip.progtrack.act_goal_nactions)
 348                 return
 349 
 350         def act_output_done(self):
 351                 if self.parent != None:
 352                         gobject.idle_add(self.parent.update_package_list)
 353                         time.sleep(0.1)
 354                 return
 355 
 356         def ind_output(self):
 357                 self.progress_stop_timer_thread = False
 358                 gobject.idle_add(self.__indexing_progress)
 359                 return
 360 
 361         def __indexing_progress(self):
 362                 if not self.progress_stop_timer_running:
 363                         self.w_removingdialog_label.set_text(\
 364                             self.parent._("Creating packages index..."))
 365                         Thread(target = self.__removedialog_progress_pulse).start()
 366 
 367         def ind_output_done(self):
 368                 self.progress_stop_timer_thread = True
 369                 return