--- old/src/gui/Makefile 2008-09-17 01:13:54.975314692 +0100 +++ new/src/gui/Makefile 2008-09-17 01:13:54.781143783 +0100 @@ -52,10 +52,12 @@ modules/remove.py \ modules/enumerations.py \ modules/filelist.py \ + modules/beadmin.py \ modules/thread.py PYCMODS = $(PYMODS:%.py=%.pyc) ICONS = \ + data/icons/status_checkmark.png \ data/icons/new_update.png GLADEICONS = \ Binary files /dev/null and new/src/gui/data/icons/status_checkmark.png differ --- old/src/gui/data/packagemanager.glade 2008-09-17 01:13:56.799839742 +0100 +++ new/src/gui/data/packagemanager.glade 2008-09-17 01:13:56.595646729 +0100 @@ -1,6 +1,6 @@ - + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -29,6 +29,20 @@ True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + True + BE management + BE management + True + + + + + + True + + + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -901,29 +915,35 @@ 20 12 - + True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Debug - 0 - True - debug_2 + 0 + Build type: - 1 - 2 1 2 GTK_FILL - + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Architecture (CPU): + + + GTK_FILL + + + + True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Non-Debug + X86 0 True True @@ -931,8 +951,6 @@ 2 3 - 1 - 2 @@ -952,11 +970,11 @@ - + True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - X86 + Non-Debug 0 True True @@ -964,27 +982,23 @@ 2 3 + 1 + 2 - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Architecture (CPU): - - - GTK_FILL - - - - + True + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Build type: + Debug + 0 + True + debug_2 + 1 + 2 1 2 GTK_FILL @@ -2403,4 +2417,814 @@ + + 600 + 500 + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Boot Environment Management + True + GTK_WIN_POS_CENTER_ON_PARENT + GDK_WINDOW_TYPE_HINT_DIALOG + mainwindow + False + + + + True + 2 + + + True + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + 10 + 2 + <b>Manage Your Boot Environments</b> + True + + + False + + + + + 575 + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + 10 + 4 + In some cases, when Update action is performed, a new Boot Environment is created. + True + True + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + 10 + 4 + By managing Boot Environments you may: + True + + + False + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + 20 + - Delete old Boot Environments to free up disk space. +- Set the Active BE for next reboot. + True + + + False + 3 + + + + + True + + + + + + False + 5 + 4 + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + True + True + False + + + + + 5 + + + + + True + + + True + 5 + gtk-missing-image + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + 10 + 4 + Currently Active Boot Environment + True + + + False + 1 + + + + + False + 2 + 6 + + + + + True + + + False + 7 + + + + + 1 + + + + + True + GTK_BUTTONBOX_END + + + True + True + True + Cancel + 0 + + + + + + True + False + True + True + Reset + 0 + + + + 1 + + + + + True + True + True + Ok + 0 + + + + 2 + + + + + False + GTK_PACK_END + + + + + + + 5 + Edit Repository + True + GTK_WIN_POS_CENTER_ON_PARENT + GDK_WINDOW_TYPE_HINT_DIALOG + mainwindow + 0.99999999977648257 + False + + + True + 2 + + + True + + + True + + + True + 0 + 0 + 10 + 2 + <b>Edit Repositories</b> + True + + + + + True + 0 + 0 + 10 + 4 + Enter the complete PKG line of the repository you want to add as a source +and give it a name. + + + 1 + + + + + True + + + True + 0 + 0 + 10 + 4 + Name: + + + False + 3 + + + + + True + True + + + 3 + 1 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 75 + + + + + + + + True + True + + + label_item + + + + + False + False + 45 + 2 + + + + + 2 + + + + + True + + + True + 0 + 0 + 9 + 4 + URL: + + + False + 5 + + + + + True + True + + + 4 + 1 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 0 + + + True + + + True + True + True + Add + 0 + + + False + False + + + + + + + + + + label_item + + + + + False + False + 5 + 2 + + + + + 3 + + + + + False + False + + + + + True + + + False + 4 + 1 + + + + + True + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + True + + + + + + + True + + + True + 0 + GTK_SHADOW_NONE + + + True + 0 + 6 + + + True + + + True + True + True + Remove + 0 + + + False + False + + + + + + + + + + + + + label_item + + + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 12 + + + + + + + + + label_item + + + + + 1 + + + + + True + 0 + GTK_SHADOW_NONE + + + True + 12 + + + True + + + + + + + + + + + + + True + True + + + label_item + + + + + 2 + + + + + False + False + 1 + + + + + 2 + + + + + True + + + False + 4 + 3 + + + + + 1 + + + + + True + GTK_BUTTONBOX_END + + + True + True + True + Cancel + 0 + + + + + True + True + True + Reset + 0 + + + 1 + + + + + True + True + True + OK + 0 + + + 2 + + + + + False + GTK_PACK_END + + + + + + + 400 + 400 + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + BE Management Changes Confirmation + True + GTK_WIN_POS_CENTER_ON_PARENT + GDK_WINDOW_TYPE_HINT_DIALOG + False + beadmin + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-warning + 5 + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + Review the Boot Environments to change +Click OK to proceed + True + True + + + 1 + + + + + False + 15 + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + <b>Boot Environments to be deleted:</b> + True + + + False + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + False + + + + + 6 + 3 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + <b>Active Boot Environment changed to:</b> + True + + + False + 4 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + + + True + + + False + 5 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + <b>Summary</b> + True + + + False + 6 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + True + + + False + 7 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + False + 5 + 8 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Cancel + 0 + + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + OK + 0 + + + + 1 + + + + + False + GTK_PACK_END + + + + + --- old/src/gui/modules/__init__.py 2008-09-17 01:13:58.410045507 +0100 +++ new/src/gui/modules/__init__.py 2008-09-17 01:13:58.209799312 +0100 @@ -23,4 +23,4 @@ # Use is subject to license terms. # -__all__ = ['installupdate', 'enumerations', 'filelist', 'thread', 'remove', 'imageinfo'] +__all__ = ['installupdate', 'enumerations', 'filelist', 'thread', 'remove', 'imageinfo', 'beadmin'] --- /dev/null 2008-09-17 01:13:59.000000000 +0100 +++ new/src/gui/modules/beadmin.py 2008-09-17 01:13:59.349325110 +0100 @@ -0,0 +1,546 @@ +#!/usr/bin/python2.4 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +import sys +import subprocess +import pango +import time +import datetime +from threading import Thread + +try: + import gobject + gobject.threads_init() + import gtk + import gtk.glade + import pygtk + pygtk.require("2.0") +except ImportError: + sys.exit(1) + +nobe = False + +try: + import libbe as be +except ImportError: + # All actions are disabled when libbe can't be imported. + nobe = True +import pkg.misc + +class Beadmin: + def __init__(self, parent): + if nobe: + msg = self.parent._("The libbe library was not " + \ + "found on your system." + \ + "\nAll functions for managing Boot Environments are disabled") + msgbox = gtk.MessageDialog( + buttons = gtk.BUTTONS_CLOSE, \ + flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_INFO, \ + message_format = None) + msgbox.set_markup(msg) + msgbox.set_title(self.parent._("BE management")) + result = msgbox.run() + msgbox.destroy() + return + + self.parent = parent + + self.be_list = \ + gtk.ListStore( + gobject.TYPE_INT, # BE_ID + gobject.TYPE_BOOLEAN, # BE_MARK + gobject.TYPE_STRING, # BE_NAME + gobject.TYPE_STRING, # BE_DATE_TIME + gtk.gdk.Pixbuf, # BE_CURRENT + gobject.TYPE_BOOLEAN, # BE_DEFAULT + gobject.TYPE_STRING, # BE_SIZE + ) + self.progress_stop_thread = False + self.initial_active = 0 + self.initial_default = 0 + w_tree_beadmin = gtk.glade.XML(parent.gladefile, "beadmin") + w_tree_progress = gtk.glade.XML(parent.gladefile, "progressdialog") + w_tree_beconfirmation = gtk.glade.XML(parent.gladefile, \ + "beconfirmationdialog") + self.w_beadmin_dialog = w_tree_beadmin.get_widget("beadmin") + self.w_be_treeview = w_tree_beadmin.get_widget("betreeview") + self.w_cancel_button = w_tree_beadmin.get_widget("cancelbebutton") + self.w_reset_button = w_tree_beadmin.get_widget("resetbebutton") + w_active_gtkimage = w_tree_beadmin.get_widget("activebeimage") + self.w_progress_dialog = w_tree_progress.get_widget("progressdialog") + self.w_progressinfo_label = w_tree_progress.get_widget("progressinfo") + progress_button = w_tree_progress.get_widget("progresscancel") + self.w_progressbar = w_tree_progress.get_widget("progressbar") + self.w_beconfirmation_dialog = \ + w_tree_beconfirmation.get_widget("beconfirmationdialog") + self.w_beconfirmation_treeview = \ + w_tree_beconfirmation.get_widget("beconfirmtreeview") + self.w_beconfirmationdefault_label = \ + w_tree_beconfirmation.get_widget("beconfirmationdefault") + self.w_beconfirmationsummary_label = \ + w_tree_beconfirmation.get_widget("beconfirmationsummary") + self.w_cancelbe_button = w_tree_beconfirmation.get_widget("cancel_be") + progress_button.hide() + self.w_progressbar.set_pulse_step(0.1) + self.list_filter = self.be_list.filter_new() + self.w_be_treeview.set_model(self.list_filter) + self.__init_tree_views() + treestore = gtk.ListStore(gobject.TYPE_STRING) + self.w_beconfirmation_treeview.set_model(treestore) + cell = gtk.CellRendererText() + be_column = gtk.TreeViewColumn('BE', cell, text = 0) + self.w_beconfirmation_treeview.append_column(be_column) + self.active_image = self.parent.get_icon_pixbuf("status_checkmark") + w_active_gtkimage.set_from_pixbuf(self.active_image) + + try: + dic = \ + { + "on_cancel_be_clicked": \ + self.__on_cancel_be_clicked, + "on_reset_be_clicked": \ + self.__on_reset_be_clicked, + "on_ok_be_clicked": \ + self.__on_ok_be_clicked, + } + dic_conf = \ + { + "on_cancel_be_conf_clicked": \ + self.__on_cancel_be_conf_clicked, + "on_ok_be_conf_clicked": \ + self.__on_ok_be_conf_clicked, + } + w_tree_beadmin.signal_autoconnect(dic) + w_tree_beconfirmation.signal_autoconnect(dic_conf) + except AttributeError, error: + print self.parent._('GUI will not respond to any event! %s. \ + Check beadmin.py signals') \ + % error + Thread(target = self.__progress_pulse).start() + Thread(target = self.__prepare_beadmin_list).start() + sel = self.w_be_treeview.get_selection() + self.w_cancel_button.grab_focus() + sel.set_mode(gtk.SELECTION_NONE) + sel = self.w_beconfirmation_treeview.get_selection() + sel.set_mode(gtk.SELECTION_NONE) + self.w_beadmin_dialog.show_all() + self.w_progress_dialog.set_title(\ + self.parent._("Loading Boot Environment Information")) + self.w_progressinfo_label.set_text(\ + self.parent._("Fetching BE entries...")) + self.be_destroy_supports_capital_f = \ + self.__check_if_be_supports_capital_f() + self.w_progress_dialog.show() + + def __progress_pulse(self): + while not self.progress_stop_thread: + gobject.idle_add(self.w_progressbar.pulse) + time.sleep(0.1) + gobject.idle_add(self.w_progress_dialog.hide) + + def __prepare_beadmin_list(self): + be_list = be.beList() + gobject.idle_add(self.__create_view_with_be, be_list) + self.progress_stop_thread = True + return + + def __init_tree_views(self): + model = self.w_be_treeview.get_model() + + column = gtk.TreeViewColumn() + column.set_title("") + render_pixbuf = gtk.CellRendererPixbuf() + column.pack_start(render_pixbuf, expand = True) + column.add_attribute(render_pixbuf, "pixbuf", 4) # BE_CURRENT + self.w_be_treeview.append_column(column) + + name_renderer = gtk.CellRendererText() + column = gtk.TreeViewColumn(self.parent._("Boot Environment"), \ + name_renderer, text = 2) # 2 = BE_NAME + column.set_cell_data_func(name_renderer, self.__cell_data_function, None) + column.set_expand(True) + self.w_be_treeview.append_column(column) + + datetime_renderer = gtk.CellRendererText() + datetime_renderer.set_property('xalign', 0.0) + column = gtk.TreeViewColumn(self.parent._("Created"), datetime_renderer, \ + text = 3) # 3 = BE_DATE_TIME + column.set_cell_data_func(datetime_renderer, \ + self.__cell_data_function, None) + column.set_expand(True) + self.w_be_treeview.append_column(column) + + size_renderer = gtk.CellRendererText() + size_renderer.set_property('xalign', 1.0) + column = gtk.TreeViewColumn(self.parent._("Size"), size_renderer, \ + text = 6) # 6 = BE_SIZE + column.set_cell_data_func(size_renderer, self.__cell_data_function, None) + column.set_expand(False) + self.w_be_treeview.append_column(column) + + radio_renderer = gtk.CellRendererToggle() + radio_renderer.connect('toggled', self.__active_pane_default, model) + column = gtk.TreeViewColumn(self.parent._("Active on Reboot"), \ + radio_renderer, active = 5) # 1 = BE_MARK + radio_renderer.set_property("activatable", True) + radio_renderer.set_property("radio", True) + column.set_cell_data_func(radio_renderer, \ + self.__cell_data_default_function, None) + column.set_expand(False) + self.w_be_treeview.append_column(column) + + toggle_renderer = gtk.CellRendererToggle() + toggle_renderer.connect('toggled', self.__active_pane_toggle, model) + column = gtk.TreeViewColumn(self.parent._("Delete"), toggle_renderer, \ + active = 1) # 1 = BE_MARK + toggle_renderer.set_property("activatable", True) + column.set_cell_data_func(toggle_renderer, \ + self.__cell_data_delete_function, None) + column.set_expand(False) + self.w_be_treeview.append_column(column) + + def __on_reset_be_clicked(self, widget): + self.be_list.clear() + self.w_progress_dialog.show() + self.progress_stop_thread = False + Thread(target = self.__progress_pulse).start() + Thread(target = self.__prepare_beadmin_list).start() + self.__enable_disable_reset() + + def __on_ok_be_clicked(self, widget): + self.w_progress_dialog.set_title(self.parent._("Applying changes")) + self.w_progressinfo_label.set_text(\ + self.parent._("Applying changes, please wait ...")) + if self.w_reset_button.get_property('sensitive') == 0: + self.progress_stop_thread = True + self.__on_beadmin_delete_event(None, None) + return + Thread(target = self.__activate).start() + + def __on_cancel_be_clicked(self, widget): + self.__on_beadmin_delete_event(None, None) + + def __on_cancel_be_conf_clicked(self, widget): + self.w_beconfirmation_dialog.hide() + + def __on_ok_be_conf_clicked(self, widget): + self.w_beconfirmation_dialog.hide() + self.progress_stop_thread = False + Thread(target = self.__on_progressdialog_progress).start() + Thread(target = self.__delete_activate_be).start() + + def __on_beadmin_delete_event(self, widget, event): + self.w_beadmin_dialog.destroy() + return True + + def __activate(self): + to_delete = [] + default = None + treestore = self.w_beconfirmation_treeview.get_model() + treestore.clear() + first = True + for row in self.be_list: + if row[1]: + treestore.append([row[2]]) + if first: + self.w_beconfirmation_treeview.set_sensitive(True) + first = False + if row[5] == True and row[0] != self.initial_default: + default = row[2] + summary_text = "" + be_change_no = len(treestore) + if be_change_no == 0: + treestore.append([self.parent._("No change")]) + self.w_beconfirmation_treeview.set_sensitive(False) + else: + summary_text += \ + self.parent._("%d BE's will be deleted") % be_change_no + + if default: + self.w_beconfirmationdefault_label.set_text(default+"\n") + self.w_beconfirmationdefault_label.set_sensitive(True) + if be_change_no > 0: + summary_text += "\n" + summary_text += \ + self.parent._("The Active BE will be changed upon reboot") + else: + self.w_beconfirmationdefault_label.set_sensitive(False) + self.w_beconfirmationdefault_label.set_text(\ + self.parent._("No change\n")) + self.w_beconfirmationsummary_label.set_text(summary_text) + self.w_beconfirmation_treeview.expand_all() + self.w_cancelbe_button.grab_focus() + self.w_beconfirmation_dialog.show() + self.progress_stop_thread = True + + def __on_progressdialog_progress(self): + # This needs to be run in gobject.idle_add, otherwise we will get + # Xlib: unexpected async reply (sequence 0x2db0)! + gobject.idle_add(self.w_progress_dialog.show) + while not self.progress_stop_thread: + gobject.idle_add(self.w_progressbar.pulse) + time.sleep(0.1) + gobject.idle_add(self.w_progress_dialog.hide) + + def __delete_activate_be(self): + not_deleted = [] + not_default = None + for row in self.be_list: + if row[1]: + succeed = self.__destroy_be(row[2]) + if succeed == 1: + not_deleted.append(row[2]) + for row in self.be_list: + if row[5] == True and row[0] != self.initial_default: + succeed = self.__set_default_be(row[2]) + if succeed == 1: + not_default = row[2] + if len(not_deleted) == 0 and not_default == None: + self.progress_stop_thread = True + else: + self.progress_stop_thread = True + msg = "" + if not_default: + msg += self.parent._("Couldn't change Active " + \ + "Boot Environment to:\n") + not_default + if len(not_deleted) > 0: + if not_default: + msg+= "\n\n" + msg += self.parent._("Couldn't delete Boot " + \ + "Environments:\n") + for row in not_deleted: + msg += row + "\n" + gobject.idle_add(self.__error_occured, msg) + return + self.__on_beadmin_delete_event(None, None) + + def __error_occured(self, error_msg, reset=True): + msg = error_msg + msgbox = gtk.MessageDialog(parent = self.w_beadmin_dialog, \ + buttons = gtk.BUTTONS_CLOSE, \ + flags = gtk.DIALOG_MODAL, type = gtk.MESSAGE_ERROR, \ + message_format = None) + msgbox.set_markup(msg) + msgbox.set_title("BE error") + result = msgbox.run() + msgbox.destroy() + if reset: + self.__on_reset_be_clicked(None) + + def __active_pane_toggle(self, cell, filtered_path, filtered_model): + model = filtered_model.get_model() + path = filtered_model.convert_path_to_child_path(filtered_path) + itr = model.get_iter(path) + if itr: + modified = model.get_value(itr, 1) + model.set_value(itr, 1, \ + not modified) + self.__enable_disable_reset() + + def __enable_disable_reset(self): + for row in self.be_list: + if row[1] == True: + self.w_reset_button.set_sensitive(True) + return + self.initial_default + self.initial_active + if row[0] == self.initial_default: + if row[5] == False: + self.w_reset_button.set_sensitive(True) + return + self.w_reset_button.set_sensitive(False) + return + + def __active_pane_default(self, cell, filtered_path, filtered_model): + model = filtered_model.get_model() + path = filtered_model.convert_path_to_child_path(filtered_path) + for row in model: + row[5] = False + itr = model.get_iter(path) + if itr: + modified = model.get_value(itr, 5) + model.set_value(itr, 5, \ + not modified) + self.__enable_disable_reset() + + def __create_view_with_be(self, be_list): + dates = None + i = 0 + j = 0 + error_code = None + be_list_loop = None + if len(be_list) > 1 and type(be_list[0]) == type(-1): + error_code = be_list[0] + if error_code != None and error_code == 0: + be_list_loop = be_list[1] + elif error_code != None and error_code != 0: + msg = self.parent._("The libbe library couldn't " + \ + "prepare list of Boot Environments." + \ + "\nAll functions for managing Boot Environments are disabled") + gobject.idle_add(self.__error_occured, msg, False) + return + else: + be_list_loop = be_list + + for bee in be_list_loop: + if bee.get("orig_be_name"): + name = bee.get("orig_be_name") + active = bee.get("active") + active_boot = bee.get("active_boot") + be_size = bee.get("space_used") + be_date = bee.get("date") + converted_size = \ + self.__convert_size_of_be_to_string(be_size) + active_img = None + if not be_date and j == 0: + dates = self.__get_dates_of_creation(be_list_loop) + if dates: + try: + date_time = repr(dates[i])[1:-3] + date_tmp = time.strptime(date_time, \ + "%a %b %d %H:%M %Y") + date_tmp2 = \ + datetime.datetime(*date_tmp[0:5]) + date_time = \ + date_tmp2.strftime("%m/%d/%y %H:%M") + i += 1 + except: + date_time = None + else: + date_tmp = time.gmtime(be_date) + date_time = time.strftime("%m/%d/%y %H:%M", date_tmp) + if active: + active_img = self.active_image + self.initial_active = j + if active_boot: + self.initial_default = j + self.be_list.insert(j, [j, False, \ + name, \ + date_time, active_img, \ + active_boot, converted_size]) + j += 1 + self.w_be_treeview.set_cursor(self.initial_active, None, \ + start_editing=True) + self.w_be_treeview.scroll_to_cell(self.initial_active) + + def __convert_size_of_be_to_string(self, be_size): + if not be_size: + be_size = 0 + return pkg.misc.bytes_to_str(be_size) + + def __get_dates_of_creation(self, be_list): + #zfs list -H -o creation rpool/ROOT/opensolaris-1 + cmd = [ "/sbin/zfs", "list", "-H", "-o","creation" ] + for bee in be_list: + if bee.get("orig_be_name"): + name = bee.get("orig_be_name") + pool = bee.get("orig_be_pool") + cmd += [pool+"/ROOT/"+name] + if len(cmd) <= 5: + return None + list_of_dates = [] + try: + proc = subprocess.Popen(cmd, stdout = subprocess.PIPE, \ + stderr = subprocess.PIPE,) + line_out = proc.stdout.readline() + while line_out: + list_of_dates.append(line_out) + line_out = proc.stdout.readline() + except OSError, e: + pass + return list_of_dates + + def __destroy_be(self, be_name): + cmd = [ "/sbin/beadm", "destroy", "-F", be_name ] + if not self.be_destroy_supports_capital_f: + cmd = [ "/sbin/beadm", "destroy", "-f", be_name ] + return self.__beadm_invoke_command(cmd) + + def __set_default_be(self, be_name): + cmd = [ "/sbin/beadm", "activate", be_name ] + return self.__beadm_invoke_command(cmd) + + def __beadm_invoke_command(self, cmd): + try: + # Subprocess platform specific, but beadm is only on Solars so we + # can use it... + stdouterr = open('/dev/null', 'w') + returncode = subprocess.call(cmd, stdout = stdouterr, \ + stderr = stdouterr,) + except OSError, e: + returncode = 1 + return returncode + + def __check_if_be_supports_capital_f(self): + '''The beadmin command changed arguments and before build 86 to supress + the prompt back for the destroy operation we had to used -f instead of + -F. This function should return True only when the old beadm is used.''' + supports_capital_f = True + try: + cmd = [ "/sbin/beadm" ] + stdout = open('/dev/null', 'w') + stderr = subprocess.Popen(cmd, stdout = stdout, \ + stderr=subprocess.PIPE).stderr + out = stderr.read().split('\n') + for line in out: + if "beadm destroy" in line: + if "[-f]" in line: + supports_capital_f = False + except OSError, e: + pass + return supports_capital_f + + + + def __cell_data_default_function(self, column, renderer, model, itr, data): + if itr: + if model.get_value(itr, 1): + self.__set_renderer_active(renderer, False) + else: + self.__set_renderer_active(renderer, True) + + def __cell_data_delete_function(self, column, renderer, model, itr, data): + if itr: + if model.get_value(itr, 5) or (self.initial_active == \ + model.get_value(itr, 0)): + self.__set_renderer_active(renderer, False) + else: + self.__set_renderer_active(renderer, True) + + + def __set_renderer_active(self, renderer, active): + if active: + renderer.set_property("sensitive", True) + renderer.set_property("mode", gtk.CELL_RENDERER_MODE_ACTIVATABLE) + else: + renderer.set_property("sensitive", False) + renderer.set_property("mode", gtk.CELL_RENDERER_MODE_INERT) + + def __cell_data_function(self, column, renderer, model, itr, data): + if itr: + if model.get_value(itr, 4): + renderer.set_property("weight", pango.WEIGHT_BOLD) + else: + renderer.set_property("weight", pango.WEIGHT_NORMAL) --- old/src/packagemanager.py 2008-09-17 01:14:00.713459839 +0100 +++ new/src/packagemanager.py 2008-09-17 01:14:00.250090974 +0100 @@ -59,6 +59,7 @@ import pkg.client.progress as progress import pkg.misc as misc import pkg.portable as portable +import pkg.gui.beadmin as beadm import pkg.gui.imageinfo as imageinfo import pkg.gui.installupdate as installupdate import pkg.gui.remove as remove @@ -226,6 +227,7 @@ self.__on_repositorycombobox_changed, #menu signals "on_file_quit_activate":self.__on_file_quit_activate, + "on_file_be_activate":self.__on_file_be_activate, "on_package_install_update_activate": \ self.__on_install_update, "on_package_remove_activate":self.__on_remove, @@ -429,6 +431,10 @@ ''' handler for quit menu event ''' self.__on_mainwindow_delete_event(None, None) + def __on_file_be_activate(self, widget): + ''' handler for be menu event ''' + beadm.Beadmin(self) + def __on_searchentry_changed(self, widget): '''On text search field changed we should refilter the main view''' Thread(target = self.__on_searchentry_threaded, args = ()).start() @@ -1222,7 +1228,7 @@ # but here for completeness. raise #Only one instance of those icons should be in memory - update_available_icon = self.__get_icon_pixbuf("new_update") + update_available_icon = self.get_icon_pixbuf("new_update") #Imageinfo for categories imginfo = imageinfo.ImageInfo() sectioninfo = imageinfo.ImageInfo() @@ -1452,11 +1458,6 @@ enumerations. \ SECTION_ID]) - def __get_icon_pixbuf(self, icon_name): - #2821: The __get_icon_pixbuf should use PACKAGE_MANAGER_ROOT - return self.__get_pixbuf_from_path(self.application_dir + \ - "/usr/share/icons/package-manager/", icon_name) - def __get_pixbuf_from_path(self, path, icon_name): icon = icon_name.replace(' ', '_') @@ -1655,6 +1656,11 @@ self.w_sections_combobox.set_active(0) self.application_list_filter.set_visible_func(self.__application_filter) self.__setup_repositories_combobox(self.image_o) + + def get_icon_pixbuf(self, icon_name): + #2821: The get_icon_pixbuf should use PACKAGE_MANAGER_ROOT + return self.__get_pixbuf_from_path(self.application_dir + \ + "/usr/share/icons/package-manager/", icon_name) def get_manifests_for_packages(self): ''' Function, which get's manifest for packages. If the manifest is not @@ -1776,21 +1782,21 @@ #-----------------------------------------------------------------------------# def fill_with_fake_data(self): '''test data for gui''' - app1 = [False, self.__get_icon_pixbuf("locked"), \ - self.__get_icon_pixbuf("None"), "acc", None, None, None, 4, "desc6", \ + app1 = [False, self.get_icon_pixbuf("locked"), \ + self.get_icon_pixbuf("None"), "acc", None, None, None, 4, "desc6", \ "Object Name1", None, True, None] - app2 = [False, self.__get_icon_pixbuf("update_available"), \ - self.__get_icon_pixbuf(self._('All')), "acc_gam", \ + app2 = [False, self.get_icon_pixbuf("update_available"), \ + self.get_icon_pixbuf(self._('All')), "acc_gam", \ "2.3", None, "2.8", \ 4, "desc7", "Object Name2", None, True, None] - app3 = [False, self.__get_icon_pixbuf("None"), \ - self.__get_icon_pixbuf("Other"), "gam_grap", "2.3", None, None, 4, \ + app3 = [False, self.get_icon_pixbuf("None"), \ + self.get_icon_pixbuf("Other"), "gam_grap", "2.3", None, None, 4, \ "desc8", "Object Name3", None, True, None] - app4 = [False, self.__get_icon_pixbuf("update_locked"), \ - self.__get_icon_pixbuf("Office"), "grap_gam", "2.3", None, "2.8", 4, \ + app4 = [False, self.get_icon_pixbuf("update_locked"), \ + self.get_icon_pixbuf("Office"), "grap_gam", "2.3", None, "2.8", 4, \ "desc9", "Object Name2", None, True, None] - app5 = [False, self.__get_icon_pixbuf("update_available"), \ - self.__get_icon_pixbuf("None"), "grap", "2.3", None, "2.8", 4, \ + app5 = [False, self.get_icon_pixbuf("update_available"), \ + self.get_icon_pixbuf("None"), "grap", "2.3", None, "2.8", 4, \ "desc0", "Object Name3", None, True, None] itr1 = self.application_list.append(app1) itr2 = self.application_list.append(app2) --- old/src/pkgdefs/SUNWipkg-gui/Makefile 2008-09-17 01:14:02.110684737 +0100 +++ new/src/pkgdefs/SUNWipkg-gui/Makefile 2008-09-17 01:14:01.908817118 +0100 @@ -54,7 +54,7 @@ $$5 = "root"; \ $$6 = "bin"; \ } \ - $$3 ~ /(share(\/applications\/packagemanager.desktop|\/applications|\/icons|\/icons\/package\-manager|\/icons\/package\-manager\/new_update.png))$$/ { \ + $$3 ~ /(share(\/applications\/packagemanager.desktop|\/applications|\/icons|\/icons\/package\-manager|\/icons\/package\-manager\/new_update.png|\/icons\/package\-manager\/status_checkmark.png))$$/ { \ $$6 = "other"; \ } \ $$3 ~ /(share(\/package\-manager|\/package\-manager\/data|\/package\-manager(\/packagemanager.glade|\/PM_app_48x.png|\/PM_package_36x.png)))$$/ { \