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 2009 Sun Microsystems, Inc.  All rights reserved.
  23 # Use is subject to license terms.
  24 #
  25 
  26 import sys
  27 import os
  28 import pango
  29 import time
  30 import datetime
  31 import locale
  32 import pkg.pkgsubprocess as subprocess
  33 from threading import Thread
  34 
  35 try:
  36         import gobject
  37         gobject.threads_init()
  38         import gnome
  39         import gtk
  40         import gtk.glade
  41         import pygtk
  42         pygtk.require("2.0")
  43 except ImportError:
  44         sys.exit(1)
  45 import pkg.gui.misc as gui_misc
  46 
  47 nobe = False
  48 
  49 try:
  50         import libbe as be
  51 except ImportError:
  52         # All actions are disabled when libbe can't be imported. 
  53         nobe = True
  54 import pkg.misc
  55 
  56 #BE_LIST
  57 (
  58 BE_ID,
  59 BE_MARKED,
  60 BE_NAME,
  61 BE_ORIG_NAME,
  62 BE_DATE_TIME,
  63 BE_CURRENT_PIXBUF,
  64 BE_ACTIVE_DEFAULT,
  65 BE_SIZE,
  66 BE_EDITABLE
  67 ) = range(9)
  68 
  69 class Beadmin:
  70         def __init__(self, parent):
  71                 self.parent = parent
  72 
  73                 if nobe:
  74                         msg = _("The <b>libbe</b> library was not "
  75                             "found on your system."
  76                             "\nAll functions for managing Boot Environments are disabled")
  77                         msgbox = gtk.MessageDialog(
  78                             buttons = gtk.BUTTONS_CLOSE,
  79                             flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_INFO,
  80                             message_format = None)
  81                         msgbox.set_markup(msg)
  82                         msgbox.set_title(_("BE management"))
  83                         msgbox.run()
  84                         msgbox.destroy()
  85                         return
  86 
  87                 self.be_list = \
  88                     gtk.ListStore(
  89                         gobject.TYPE_INT,         # BE_ID
  90                         gobject.TYPE_BOOLEAN,     # BE_MARKED
  91                         gobject.TYPE_STRING,      # BE_NAME
  92                         gobject.TYPE_STRING,      # BE_ORIG_NAME
  93                         gobject.TYPE_STRING,      # BE_DATE_TIME
  94                         gtk.gdk.Pixbuf,           # BE_CURRENT_PIXBUF
  95                         gobject.TYPE_BOOLEAN,     # BE_ACTIVE_DEFAULT
  96                         gobject.TYPE_STRING,      # BE_SIZE
  97                         gobject.TYPE_BOOLEAN,     # BE_EDITABLE
  98                         )
  99                 self.progress_stop_thread = False
 100                 self.initial_active = 0
 101                 self.initial_default = 0
 102                 gladefile = os.path.join(self.parent.application_dir,
 103                     "usr/share/package-manager/packagemanager.glade")
 104                 w_tree_beadmin = gtk.glade.XML(gladefile, "beadmin")
 105                 w_tree_progress = gtk.glade.XML(gladefile, "progressdialog")
 106                 w_tree_beconfirmation = gtk.glade.XML(gladefile,
 107                     "beconfirmationdialog")
 108                 self.w_beadmin_dialog = w_tree_beadmin.get_widget("beadmin")
 109                 self.w_be_treeview = w_tree_beadmin.get_widget("betreeview")
 110                 self.w_cancel_button = w_tree_beadmin.get_widget("cancelbebutton")
 111                 self.w_ok_button = w_tree_beadmin.get_widget("okbebutton")
 112                 w_active_gtkimage = w_tree_beadmin.get_widget("activebeimage")
 113                 self.w_progress_dialog = w_tree_progress.get_widget("progressdialog")
 114                 self.w_progress_dialog.connect('delete-event', lambda stub1, stub2: True)
 115                 self.w_progressinfo_label = w_tree_progress.get_widget("progressinfo")
 116                 progress_button = w_tree_progress.get_widget("progresscancel")
 117                 self.w_progressbar = w_tree_progress.get_widget("progressbar")
 118                 self.w_beconfirmation_dialog =  \
 119                     w_tree_beconfirmation.get_widget("beconfirmationdialog")
 120                 self.w_beconfirmation_textview = \
 121                     w_tree_beconfirmation.get_widget("beconfirmtext")
 122                 self.w_cancelbe_button = w_tree_beconfirmation.get_widget("cancel_be")
 123                 self.w_ok_button.set_sensitive(False)
 124                 progress_button.hide()
 125                 self.w_progressbar.set_pulse_step(0.1)
 126                 self.list_filter = self.be_list.filter_new()
 127                 self.w_be_treeview.set_model(self.list_filter)
 128                 self.__init_tree_views()
 129                 self.active_image = gui_misc.get_icon(
 130                     self.parent.icon_theme, "status_checkmark")
 131                 w_active_gtkimage.set_from_pixbuf(self.active_image)
 132 
 133                 bebuffer = self.w_beconfirmation_textview.get_buffer()
 134                 bebuffer.create_tag("bold", weight=pango.WEIGHT_BOLD)
 135 
 136                 try:
 137                         dic = \
 138                             {
 139                                 "on_cancel_be_clicked": \
 140                                     self.__on_cancel_be_clicked,
 141                                 "on_ok_be_clicked": \
 142                                     self.__on_ok_be_clicked,
 143                                 "on_help_bebutton_clicked": \
 144                                     self.__on_help_bebutton_clicked,
 145                             }
 146                         dic_conf = \
 147                             {
 148                                 "on_cancel_be_conf_clicked": \
 149                                     self.__on_cancel_be_conf_clicked,
 150                                 "on_ok_be_conf_clicked": \
 151                                     self.__on_ok_be_conf_clicked,
 152                                 "on_beconfirmationdialog_delete_event": \
 153                                     self.__on_beconfirmationdialog_delete_event,
 154                             }            
 155                         w_tree_beadmin.signal_autoconnect(dic)
 156                         w_tree_beconfirmation.signal_autoconnect(dic_conf)
 157                 except AttributeError, error:
 158                         print _("GUI will not respond to any event! %s. "
 159                             "Check beadmin.py signals") \
 160                             % error
 161                 Thread(target = self.__progress_pulse).start()
 162                 Thread(target = self.__prepare_beadmin_list).start()
 163                 sel = self.w_be_treeview.get_selection()
 164                 self.w_cancel_button.grab_focus()
 165                 sel.set_mode(gtk.SELECTION_SINGLE)
 166                 self.w_beadmin_dialog.show_all()
 167                 self.w_progress_dialog.set_title(
 168                     _("Loading Boot Environment Information"))
 169                 self.w_progressinfo_label.set_text(
 170                     _("Fetching BE entries..."))
 171                 self.w_progress_dialog.show()
 172 
 173         def __progress_pulse(self):
 174                 while not self.progress_stop_thread:
 175                         gobject.idle_add(self.w_progressbar.pulse)
 176                         time.sleep(0.1)
 177                 gobject.idle_add(self.w_progress_dialog.hide)
 178 
 179         def __prepare_beadmin_list(self):
 180                 be_list = be.beList()
 181                 gobject.idle_add(self.__create_view_with_be, be_list)
 182                 self.progress_stop_thread = True
 183                 return
 184 
 185         def __init_tree_views(self):
 186                 model = self.w_be_treeview.get_model()
 187 
 188                 column = gtk.TreeViewColumn()
 189                 column.set_title("")
 190                 render_pixbuf = gtk.CellRendererPixbuf()
 191                 column.pack_start(render_pixbuf, expand = True)
 192                 column.add_attribute(render_pixbuf, "pixbuf", BE_CURRENT_PIXBUF)
 193                 self.w_be_treeview.append_column(column)
 194 
 195                 name_renderer = gtk.CellRendererText()
 196                 name_renderer.connect('edited', self.__be_name_edited, model)
 197                 column = gtk.TreeViewColumn(_("Boot Environment"),
 198                     name_renderer, text = BE_NAME)
 199                 column.set_cell_data_func(name_renderer, self.__cell_data_function, None)
 200                 column.set_expand(True)
 201                 if "beVerifyBEName" in be.__dict__:
 202                         column.add_attribute(name_renderer, "editable", 
 203                             BE_EDITABLE)
 204                 self.w_be_treeview.append_column(column)
 205                 
 206                 datetime_renderer = gtk.CellRendererText()
 207                 datetime_renderer.set_property('xalign', 0.0)
 208                 column = gtk.TreeViewColumn(_("Created"), datetime_renderer,
 209                     text = BE_DATE_TIME)
 210                 column.set_cell_data_func(datetime_renderer,
 211                     self.__cell_data_function, None)
 212                 column.set_expand(True)
 213                 self.w_be_treeview.append_column(column)
 214 
 215                 size_renderer = gtk.CellRendererText()
 216                 size_renderer.set_property('xalign', 1.0)
 217                 column = gtk.TreeViewColumn(_("Size"), size_renderer,
 218                     text = BE_SIZE)
 219                 column.set_cell_data_func(size_renderer, self.__cell_data_function, None)
 220                 column.set_expand(False)
 221                 self.w_be_treeview.append_column(column)
 222               
 223                 radio_renderer = gtk.CellRendererToggle()
 224                 radio_renderer.connect('toggled', self.__active_pane_default, model)
 225                 column = gtk.TreeViewColumn(_("Active on Reboot"),
 226                     radio_renderer, active = BE_ACTIVE_DEFAULT)
 227                 radio_renderer.set_property("activatable", True)
 228                 radio_renderer.set_property("radio", True)
 229                 column.set_cell_data_func(radio_renderer,
 230                     self.__cell_data_default_function, None)
 231                 column.set_expand(False)
 232                 self.w_be_treeview.append_column(column)
 233 
 234                 toggle_renderer = gtk.CellRendererToggle()
 235                 toggle_renderer.connect('toggled', self.__active_pane_toggle, model)
 236                 column = gtk.TreeViewColumn(_("Delete"), toggle_renderer,
 237                     active = BE_MARKED)
 238                 toggle_renderer.set_property("activatable", True)
 239                 column.set_cell_data_func(toggle_renderer,
 240                     self.__cell_data_delete_function, None)
 241                 column.set_expand(False)
 242                 self.w_be_treeview.append_column(column)
 243 
 244         def __on_help_bebutton_clicked(self, widget):
 245                 if self.parent != None:
 246                         gui_misc.display_help(self.parent.application_dir, "manage_be")
 247                 else:
 248                         gui_misc.display_help()
 249                 
 250         def __on_ok_be_clicked(self, widget):
 251                 self.w_progress_dialog.set_title(_("Applying changes"))
 252                 self.w_progressinfo_label.set_text(
 253                     _("Applying changes, please wait ..."))
 254                 if self.w_ok_button.get_property('sensitive') == 0:
 255                         self.progress_stop_thread = True
 256                         self.__on_beadmin_delete_event(None, None)
 257                         return
 258                 Thread(target = self.__activate).start()
 259                 
 260         def __on_cancel_be_clicked(self, widget):
 261                 self.__on_beadmin_delete_event(None, None)
 262                 return False
 263 
 264         def __on_beconfirmationdialog_delete_event(self, widget, event):
 265                 self.__on_cancel_be_conf_clicked(widget)
 266                 return True
 267 
 268         def __on_cancel_be_conf_clicked(self, widget):
 269                 self.w_beconfirmation_dialog.hide()
 270 
 271         def __on_ok_be_conf_clicked(self, widget):
 272                 self.w_beconfirmation_dialog.hide()
 273                 self.progress_stop_thread = False
 274                 Thread(target = self.__on_progressdialog_progress).start()
 275                 Thread(target = self.__delete_activate_be).start()
 276                 
 277         def __on_beadmin_delete_event(self, widget, event, stub=None):
 278                 self.w_beadmin_dialog.destroy()
 279                 return True
 280 
 281         def __activate(self):
 282                 active_text = _("Active on reboot:\n")
 283                 delete_text = _("Delete boot environments:\n")
 284                 rename_text = _("Rename boot environments:\n")
 285                 active = ""
 286                 delete = ""
 287                 rename = {}
 288                 for row in self.be_list:
 289 
 290                         if row[BE_MARKED]:
 291                                 delete += row[BE_NAME] + "\n"
 292                         if row[BE_ACTIVE_DEFAULT] == True and row[BE_ID] != \
 293                             self.initial_default:
 294                                 active += row[BE_NAME] + "\n"
 295                         if row[BE_NAME] != row[BE_ORIG_NAME]:
 296                                 rename[row[BE_ORIG_NAME]] = row[BE_NAME]
 297                 textbuf = self.w_beconfirmation_textview.get_buffer()
 298                 textbuf.set_text("")
 299                 textiter = textbuf.get_end_iter()
 300                 if len(active) > 0:
 301                         textbuf.insert_with_tags_by_name(textiter,
 302                             active_text, "bold")
 303                         textbuf.insert_with_tags_by_name(textiter,
 304                             active)
 305                 if len(delete) > 0:
 306                         if len(active) > 0:
 307                                 textbuf.insert_with_tags_by_name(textiter,
 308                                     "\n")                                
 309                         textbuf.insert_with_tags_by_name(textiter,
 310                             delete_text, "bold")
 311                         textbuf.insert_with_tags_by_name(textiter,
 312                             delete)
 313                 if len(rename) > 0:
 314                         if len(delete) > 0 or len(active) > 0:
 315                                 textbuf.insert_with_tags_by_name(textiter,
 316                                     "\n")                                
 317                         textbuf.insert_with_tags_by_name(textiter,
 318                             rename_text, "bold")
 319                         for orig in rename:
 320                                 textbuf.insert_with_tags_by_name(textiter,
 321                                     orig)
 322                                 textbuf.insert_with_tags_by_name(textiter,
 323                                     _(" to "), "bold")
 324                                 textbuf.insert_with_tags_by_name(textiter,
 325                                     rename.get(orig) + "\n")
 326                 self.w_cancelbe_button.grab_focus()
 327                 gobject.idle_add(self.w_beconfirmation_dialog.show)
 328                 self.progress_stop_thread = True                
 329 
 330         def __on_progressdialog_progress(self):
 331                 # This needs to be run in gobject.idle_add, otherwise we will get
 332                 # Xlib: unexpected async reply (sequence 0x2db0)!
 333                 gobject.idle_add(self.w_progress_dialog.show)
 334                 while not self.progress_stop_thread:
 335                         gobject.idle_add(self.w_progressbar.pulse)
 336                         time.sleep(0.1)
 337                 gobject.idle_add(self.w_progress_dialog.hide)
 338 
 339         def __delete_activate_be(self):
 340                 not_deleted = []
 341                 not_default = None
 342                 not_renamed = {}
 343                 # The while gtk.events_pending():
 344                 #        gtk.main_iteration(False)
 345                 # Is not working if we are calling libbe, so it is required
 346                 # To have sleep in few places in this function
 347                 # Remove
 348                 for row in self.be_list:
 349                         if row[BE_MARKED]:
 350                                 time.sleep(0.1)
 351                                 result = self.__destroy_be(row[BE_NAME])
 352                                 if result != 0:
 353                                         not_deleted.append(row[BE_NAME])
 354                 # Rename
 355                 for row in self.be_list:
 356                         if row[BE_NAME] != row[BE_ORIG_NAME]:
 357                                 time.sleep(0.1)
 358                                 result = self.__rename_be(row[BE_ORIG_NAME],
 359                                     row[BE_NAME])
 360                                 if result !=0:
 361                                         not_renamed[row[BE_ORIG_NAME]] = row[BE_NAME]
 362                 # Set active
 363                 for row in self.be_list:
 364                         if row[BE_ACTIVE_DEFAULT] == True and row[BE_ID] != \
 365                             self.initial_default:
 366                                 time.sleep(0.1)
 367                                 result = self.__set_default_be(row[BE_NAME])
 368                                 if result != 0:
 369                                         not_default = row[BE_NAME]
 370                 if len(not_deleted) == 0 and not_default == None \
 371                     and len(not_renamed) == 0:
 372                         self.progress_stop_thread = True
 373                 else:
 374                         self.progress_stop_thread = True
 375                         msg = ""
 376                         if not_default:
 377                                 msg += _("<b>Couldn't change Active "
 378                                     "Boot Environment to:</b>\n") + not_default
 379                         if len(not_deleted) > 0:
 380                                 if not_default:
 381                                         msg += "\n\n"
 382                                 msg += _("<b>Couldn't delete Boot "
 383                                     "Environments:</b>\n")
 384                                 for row in not_deleted:
 385                                         msg += row + "\n"
 386                         if len(not_renamed) > 0:
 387                                 if not_default or len(not_deleted):
 388                                         msg += "\n"
 389                                 msg += _("<b>Couldn't rename Boot "
 390                                     "Environments:</b>\n")
 391                                 for orig in not_renamed:
 392                                         msg += _("%s <b>to</b> %s\n") % (orig, 
 393                                             not_renamed.get(orig))                                
 394                         gobject.idle_add(self.__error_occurred, msg)
 395                         return
 396                 gobject.idle_add(self.__on_cancel_be_clicked, None)
 397                                 
 398         def __rename_cell(self, model, itr, new_name):
 399                 model.set_value(itr, BE_NAME, new_name)
 400 
 401         def __rename_be(self, orig_name, new_name):
 402                 return be.beRename(orig_name, new_name)
 403 
 404         def __error_occurred(self, error_msg, reset=True):
 405                 gui_misc.error_occurred(self.w_beadmin_dialog,
 406                     error_msg,
 407                     _("BE error"),
 408                     gtk.MESSAGE_ERROR,
 409                     True)
 410                 if reset:
 411                         self.__on_reset_be()
 412 
 413         def __on_reset_be(self):
 414                 self.be_list.clear()
 415                 self.w_progress_dialog.show()
 416                 self.progress_stop_thread = False
 417                 Thread(target = self.__progress_pulse).start()
 418                 Thread(target = self.__prepare_beadmin_list).start()
 419                 self.w_ok_button.set_sensitive(False)
 420 
 421         def __active_pane_toggle(self, cell, filtered_path, filtered_model):
 422                 model = filtered_model.get_model()
 423                 path = filtered_model.convert_path_to_child_path(filtered_path)
 424                 itr = model.get_iter(path)
 425                 if itr:
 426                         modified = model.get_value(itr, BE_MARKED)
 427                         # Do not allow to set active if selected for removal
 428                         model.set_value(itr, BE_MARKED, not modified)
 429                         # Do not allow to rename if we are removing be.
 430                         model.set_value(itr, BE_EDITABLE, modified)
 431                 self.__enable_disable_ok()
 432                 
 433         def __enable_disable_ok(self):
 434                 for row in self.be_list:
 435                         if row[BE_MARKED] == True:
 436                                 self.w_ok_button.set_sensitive(True)
 437                                 return
 438                         if row[BE_ID] == self.initial_default:
 439                                 if row[BE_ACTIVE_DEFAULT] == False:
 440                                         self.w_ok_button.set_sensitive(True)
 441                                         return
 442                         if row[BE_NAME] != row[BE_ORIG_NAME]:
 443                                 self.w_ok_button.set_sensitive(True)
 444                                 return
 445                 self.w_ok_button.set_sensitive(False)
 446                 return
 447 
 448         def __be_name_edited(self, cell, filtered_path, new_name, filtered_model):
 449                 model = filtered_model.get_model()
 450                 path = filtered_model.convert_path_to_child_path(filtered_path)
 451                 itr = model.get_iter(path)
 452                 if itr:
 453                         if model.get_value(itr, BE_NAME) == new_name:
 454                                 return
 455                         if self.__verify_be_name(new_name) != 0:
 456                                 return
 457                         self.__rename_cell(model, itr, new_name)
 458                         self.__enable_disable_ok()                
 459                         return
 460 
 461         #TBD: Notify user if name clash using same logic as Repo Add and warning text
 462         def __verify_be_name(self, new_name):
 463                 if be.beVerifyBEName(new_name) != 0:
 464                         return -1
 465                 for row in self.be_list:
 466                         if new_name == row[BE_NAME]:
 467                                 return -1
 468                 return 0
 469 
 470         def __active_pane_default(self, cell, filtered_path, filtered_model):
 471                 model = filtered_model.get_model()
 472                 path = filtered_model.convert_path_to_child_path(filtered_path)
 473                 for row in model:
 474                         row[BE_ACTIVE_DEFAULT] = False
 475                 itr = model.get_iter(path)
 476                 if itr:
 477                         modified = model.get_value(itr, BE_ACTIVE_DEFAULT)
 478                         model.set_value(itr, BE_ACTIVE_DEFAULT, not modified)
 479                         self.__enable_disable_ok()
 480 
 481         def __create_view_with_be(self, be_list):
 482                 dates = None
 483                 i = 0
 484                 j = 0
 485                 error_code = None
 486                 be_list_loop = None
 487                 if len(be_list) > 1 and type(be_list[0]) == type(-1):
 488                         error_code = be_list[0]
 489                 if error_code != None and error_code == 0:
 490                         be_list_loop = be_list[1]
 491                 elif error_code != None and error_code != 0:
 492                         msg = _("The <b>libbe</b> library couldn't  "
 493                             "prepare list of Boot Environments."
 494                             "\nAll functions for managing Boot Environments are disabled")
 495                         self.__error_occurred(msg, False)
 496                         return
 497                 else:
 498                         be_list_loop = be_list
 499 
 500                 for bee in be_list_loop:
 501                         if bee.get("orig_be_name"):
 502                                 name = bee.get("orig_be_name")
 503                                 active = bee.get("active")
 504                                 active_boot = bee.get("active_boot")
 505                                 be_size = bee.get("space_used")
 506                                 be_date = bee.get("date")
 507                                 converted_size = \
 508                                     self.__convert_size_of_be_to_string(be_size)
 509                                 active_img = None
 510                                 if not be_date and j == 0:
 511                                         dates = self.__get_dates_of_creation(be_list_loop)
 512                                 if dates:
 513                                         try:
 514                                                 date_time = repr(dates[i])[1:-3]
 515                                                 date_tmp = time.strptime(date_time, \
 516                                                     "%a %b %d %H:%M %Y")
 517                                                 date_tmp2 = \
 518                                                         datetime.datetime(*date_tmp[0:5])
 519                                                 try:
 520                                                         date_format = \
 521                                                         unicode(
 522                                                             _("%m/%d/%y %H:%M"),
 523                                                             "utf-8").encode(
 524                                                             locale.getpreferredencoding())
 525                                                 except (UnicodeError, LookupError,
 526                                                     locale.Error):
 527                                                         date_format = "%F %H:%M"
 528                                                 date_time = \
 529                                                     date_tmp2.strftime(date_format)
 530                                                 i += 1
 531                                         except (NameError, ValueError, TypeError):
 532                                                 date_time = None
 533                                 else:
 534                                         date_tmp = time.localtime(be_date)
 535                                         try:
 536                                                 date_format = \
 537                                                     unicode(
 538                                                         _("%m/%d/%y %H:%M"),
 539                                                         "utf-8").encode(
 540                                                         locale.getpreferredencoding())
 541                                         except (UnicodeError, LookupError, locale.Error):
 542                                                 date_format = "%F %H:%M"
 543                                         date_time = \
 544                                             time.strftime(date_format, date_tmp)
 545                                 if active:
 546                                         active_img = self.active_image
 547                                         self.initial_active = j
 548                                 if active_boot:
 549                                         self.initial_default = j
 550                                 if date_time != None:
 551                                         try:
 552                                                 date_time = unicode(date_time,
 553                                                 locale.getpreferredencoding()).encode(
 554                                                         "utf-8")
 555                                         except (UnicodeError, LookupError, locale.Error):
 556                                                 pass 
 557                                 self.be_list.insert(j, [j, False,
 558                                     name, name,
 559                                     date_time, active_img,
 560                                     active_boot, converted_size, active_img == None])
 561                                 j += 1
 562                 self.w_be_treeview.set_cursor(self.initial_active, None,
 563                     start_editing=True)
 564                 self.w_be_treeview.scroll_to_cell(self.initial_active)
 565 
 566         def __destroy_be(self, be_name):
 567                 return be.beDestroy(be_name, 1, True)
 568 
 569         def __set_default_be(self, be_name):
 570                 return be.beActivate(be_name)
 571 
 572         def __cell_data_default_function(self, column, renderer, model, itr, data):
 573                 if itr:
 574                         if model.get_value(itr, BE_MARKED):
 575                                 self.__set_renderer_active(renderer, False)
 576                         else:
 577                                 self.__set_renderer_active(renderer, True)
 578                                 
 579         def __cell_data_delete_function(self, column, renderer, model, itr, data):
 580                 if itr:
 581                         if model.get_value(itr, BE_ACTIVE_DEFAULT) or \
 582                             (self.initial_active == model.get_value(itr, BE_ID)) or \
 583                             (model.get_value(itr, BE_NAME) !=
 584                             model.get_value(itr, BE_ORIG_NAME)):
 585                                 self.__set_renderer_active(renderer, False)
 586                         else:
 587                                 self.__set_renderer_active(renderer, True)
 588 
 589         @staticmethod
 590         def __set_renderer_active(renderer, active):
 591                 if active:
 592                         renderer.set_property("sensitive", True)
 593                         renderer.set_property("mode", gtk.CELL_RENDERER_MODE_ACTIVATABLE)
 594                 else:
 595                         renderer.set_property("sensitive", False)
 596                         renderer.set_property("mode", gtk.CELL_RENDERER_MODE_INERT)
 597 
 598         @staticmethod
 599         def __get_dates_of_creation(be_list):
 600                 #zfs list -H -o creation rpool/ROOT/opensolaris-1
 601                 cmd = [ "/sbin/zfs", "list", "-H", "-o","creation" ]
 602                 for bee in be_list:
 603                         if bee.get("orig_be_name"):
 604                                 name = bee.get("orig_be_name")
 605                                 pool = bee.get("orig_be_pool")
 606                                 cmd += [pool+"/ROOT/"+name]
 607                 if len(cmd) <= 5:
 608                         return None
 609                 list_of_dates = []
 610                 try:
 611                         proc = subprocess.Popen(cmd, stdout = subprocess.PIPE,
 612                             stderr = subprocess.PIPE,)
 613                         line_out = proc.stdout.readline()
 614                         while line_out:
 615                                 list_of_dates.append(line_out)
 616                                 line_out =  proc.stdout.readline()
 617                 except OSError:
 618                         return list_of_dates
 619                 return list_of_dates
 620 
 621         @staticmethod
 622         def __convert_size_of_be_to_string(be_size):
 623                 if not be_size:
 624                         be_size = 0
 625                 return pkg.misc.bytes_to_str(be_size)
 626 
 627         @staticmethod
 628         def __cell_data_function(column, renderer, model, itr, data):
 629                 if itr:
 630                         if model.get_value(itr, BE_CURRENT_PIXBUF):
 631                                 renderer.set_property("weight", pango.WEIGHT_BOLD)
 632                         else:
 633                                 renderer.set_property("weight", pango.WEIGHT_NORMAL)