Exemplo n.º 1
0
class MainWindow(PluginHandler):
    """Main Window class to setup and manage main window interface."""
    def __init__(self):
        debug.dprint("MAINWINDOW: process id = %d ****************" %
                     os.getpid())

        # set unfinished items to not be sensitive
        #self.wtree.get_widget("contents2").set_sensitive(False)
        # self.wtree.get_widget("btn_help").set_sensitive(False)

        # Initialize our subclasses
        PluginHandler.__init__(self)

        self.status = StatusHandler(self.wtree.get_widget("statusbar2"),
                                    self.wtree.get_widget("progressbar1"),
                                    self.category_view, self.package_view,
                                    self.current_pkg_path,
                                    self.current_pkg_cursor, self.plugin_views)

        # get an empty tooltip
        ##self.synctooltip = gtk.Tooltips()
        self.sync_tip = _(
            " Synchronise Package Database \n The last sync was done:\n")
        # set the sync label to the saved one set in the options
        self.widget["btn_sync"].set_label(config.Prefs.globals.Sync_label)
        self.widget["view_refresh"].set_sensitive(False)
        # restore last window width/height
        if config.Prefs.main.xpos and config.Prefs.main.ypos:
            self.mainwindow.move(config.Prefs.main.xpos,
                                 config.Prefs.main.ypos)
        self.mainwindow.resize(config.Prefs.main.width,
                               config.Prefs.main.height)
        # connect gtk callback for window movement and resize events
        self.mainwindow.connect("configure-event", self.size_update)
        # restore maximized state and set window-state-event
        # handler to keep track of it
        if config.Prefs.main.maximized:
            self.mainwindow.maximize()
        self.mainwindow.connect("window-state-event",
                                self.on_window_state_event)
        # move horizontal and vertical panes
        #debug.dprint("MAINWINDOW: __init__() before hpane; " +
        #"%d, vpane; %d"
        #%(config.Prefs.main.hpane, config.Prefs.main.vpane))
        self.hpane = self.wtree.get_widget("hpane")
        self.hpane.set_position(config.Prefs.main.hpane)
        self.hpane.connect("notify", self.on_pane_notify)
        self.vpane = self.wtree.get_widget("vpane")
        self.vpane.set_position(config.Prefs.main.vpane)
        self.vpane.connect("notify", self.on_pane_notify)
        # Intercept the window delete event signal
        self.mainwindow.connect('delete-event', self.confirm_delete)
        # initialize some variable to fix the hpane jump bug
        #self.hpane_bug_count = 0
        #self.hpane_bug = True
        # initialize now so that the update_db_callback doesn't puke
        self.status.set_statusbar2("Starting")
        # set if we are root or not
        self.is_root = utils.is_root()
        debug.dprint("MAINWINDOW: __init__(); is_root = " + str(self.is_root))
        if config.Prefs.main.show_nag_dialog:
            # let the user know if he can emerge or not
            self.check_for_root()
        self.toolbar_expander = self.wtree.get_widget("toolbar_expander")
        # This should be set in the glade file, but doesn't seem to work ?
        self.toolbar_expander.set_expand(True)
        # populate the view_filter menu
        self.widget["view_filter_list"] = gtk.ListStore(str)
        for i in [
                _("All Packages"),
                _("Installed Packages"),
                _("Search Results"),
                _("Upgradable Packages"),
                _("Deprecated Packages"),
                _("Sets")
        ]:
            self.widget["view_filter_list"].append([i])
        self.widget["view_filter"].set_model(self.widget["view_filter_list"])
        self.widget["view_filter"].set_active(SHOW_ALL)
        self.setup_plugins()

        callbacks = {
            "action_callback": self.action_callback,
            "re_init_portage": self.re_init_portage,
            "set_package_actions_sensitive": self.set_package_actions_sensitive
        }
        self.assign_packagebook(self.wtree, callbacks,
                                self.plugin_package_tabs)
        # initialize our data
        self.init_data()
        self.search_dispatcher = Dispatcher(self.search_done)
        debug.dprint("MAINWINDOW: Showing main window")
        self.mainwindow.show_all()
        if self.is_root:
            # hide warning toolbar widget
            debug.dprint("MAINWINDOW: __init__(); hiding btn_root_warning")
            self.wtree.get_widget("btn_root_warning").hide()

    def init_data(self):
        """initialize the db and anything else related to package selection"""
        # set things we can't do unless a package is selected to not sensitive
        self.set_package_actions_sensitive(False)
        debug.dprint("MAINWINDOW: init_data(); Initializing data")
        # set status
        #self.status.set_statusbar(_("Obtaining package list "))
        self.status.status_root = _("Loading database: ")
        self.status.set_statusbar2(_("Initializing database. Please wait..."))
        self.set_cancel_btn(OFF)
        db.db.set_callback(self.update_db_read)
        # init some dictionaries
        self.loaded_callback = {}
        self.current_cat_name = {}
        self.current_cat_cursor = {}
        self.current_pkg_name = {}
        self.current_pkg_cursor = {}
        self.current_pkg_path = {}
        self.pkg_list = {}
        self.pkg_count = {}
        self.loaded = {}
        for i in INDEX_TYPES:
            self.current_cat_name[i] = None
            self.current_cat_cursor[i] = None
            self.current_pkg_name[i] = None
            self.current_pkg_cursor[i] = None
            self.current_pkg_path[i] = None
            if i not in ["All", "Installed", "Binpkgs"]:
                # init pkg lists, counts
                self.pkg_list[i] = {}
                self.pkg_count[i] = {}
                self.loaded[i] = False
            if i in ["Upgradable", "Deprecated", "Sets", "Binpkgs"]:
                self.loaded_callback[i] = None

        # next add any index names that need to be reset on a reload
        self.loaded_resets = ["Search", "Deprecated", "Binpkgs"]
        self.current_search = None
        # descriptions loaded?
        #self.desc_loaded = False
        # view filter setting
        self.last_view_setting = None
        # set notebook tabs to load new package info
        self.packagebook.reset_tabs()
        self.reader_running = False
        self.reader = None
        # load the db
        #debug.dprint("MAINWINDOW: init_db(); starting db.db.db_thread")
        self.reload = False
        self.upgrade_view = False
        #self.db_timeout = gobject.timeout_add(100, self.update_db_read)
        self.last_sync = _("Unknown")
        self.valid_sync = False
        self.get_sync_time()
        self.set_sync_tip()
        self.new_sync = False
        self.reload_depth = 0

    def reload_db(self, *widget):
        """initiatiate a full db reload"""
        debug.dprint("MAINWINDOW: reload_db() callback")
        self.status.progress_done()
        self.set_cancel_btn(OFF)
        for x in self.loaded_resets:
            self.loaded[x] = False
        for i in ["All", "Installed", "Binpkgs"]:
            self.current_pkg_path[i] = None
        self.current_pkg_cursor["Search"] = None
        # test to reset portage
        #PMS_LIB.reload_portage()
        PMS_LIB.settings.reload_world()
        self.upgrade_view = False
        self.get_sync_time()
        self.set_sync_tip()
        # load the db
        #self.dbtime = 0
        db.db.db_init(self.new_sync)
        #test = 87/0  # used to test pycrash is functioning
        self.reload = True
        self.new_sync = False
        # set status
        #self.status.set_statusbar(_("Obtaining package list "))
        self.status.status_root = _("Reloading database")
        self.status.set_statusbar2(self.status.status_root)
        return False

    def reload_view(self, *widget):
        """reload the package view"""
        if self.widget["view_filter"].get_active() == SHOW_UPGRADE:
            self.loaded["Upgradable"] = False
        else:
            self.category_view.populate(db.db.categories.keys())
        self.package_view.clear()
        self.set_package_actions_sensitive(False, None)
        # update the views by calling view_filter_changed
        self.view_filter_changed(self.widget["view_filter"])
        #self.widget["view_refresh"].set_sensitive(False)
        return False

    def emerge_setting_set(self, widget, option='null'):
        """Set whether or not we are going to use an emerge option"""
        debug.dprint("MAINWINDOW: emerge_setting_set(%s)" % option)
        debug.dprint("MAINWINDOW: emerge_setting_set; " + str(widget) + " " +
                     option)
        setattr(config.Prefs.emerge, option, widget.get_active())
        #config.Prefs.emerge.oneshot = widget.get_active()

    def search_set(self, widget):
        """Set whether or not to search descriptions"""
        config.Prefs.main.search_desc = widget.get_active()

    def emerge_btn(self, widget, sudo=False):
        """callback for the emerge toolbutton and menu entries"""
        if not self.process_selection("emerge"):
            package = utils.get_treeview_selection(self.package_view, 2)
            self.emerge_package(package, sudo)

    def adv_emerge_btn(self, *widget):
        """Advanced emerge of the currently selected package."""
        package = utils.get_treeview_selection(self.package_view, 2)
        self.adv_emerge_package(package)

    def unmerge_btn(self, widget, sudo=False):
        """callback for the Unmerge button and menu entry to
        unmerge the currently selected package."""
        if not self.process_selection("emerge --unmerge"):
            package = utils.get_treeview_selection(self.package_view, 2)
            self.unmerge_package(package, sudo)

    def on_cancel_btn(self, *widget):
        """cancel button callback function"""
        debug.dprint("MAINWINDOW: on_cancel_btn() callback")
        # terminate the thread
        self.reader.please_die()
        self.reader.join()
        self.status.progress_done()
        self.set_cancel_btn(OFF)

    def on_window_state_event(self, widget, event):
        """Handler for window-state-event gtk callback.
        Just checks if the window is maximized or not"""
        if widget is not self.mainwindow:
            return False
        debug.dprint("MAINWINDOW: on_window_state_event(); event detected")
        if gtk.gdk.WINDOW_STATE_MAXIMIZED & event.new_window_state:
            config.Prefs.main.maximized = True
        else:
            config.Prefs.main.maximized = False

    def on_pane_notify(self, pane, gparamspec):
        """callback function for the pane re-size signal
        stores the new settings for next time"""
        if gparamspec.name == "position":
            # save hpane, vpane positions
            config.Prefs.main.hpane = self.hpane.get_position()
            config.Prefs.main.vpane = self.vpane.get_position()

    def upgrades_loaded_dialog_response(self, widget, response):
        """ Get and parse user's response """
        if response == 0:  # Yes was selected; upgrade all
            #self.load_upgrades_list()
            #self.loaded_callback["Upgradable"] = self.upgrade_packages
            if not utils.is_root() and utils.can_sudo() \
                    and not config.Prefs.emerge.pretend:
                self.setup_command(
                    'world', 'sudo -p "Password: "******"emerge --update" +
                    config.Prefs.emerge.get_string() + 'world')
        else:
            # load the upgrades view to select which packages
            self.widget["view_filter"].set_active(SHOW_UPGRADE)
        # get rid of the dialog
        self.upgrades_loaded_dialog.destroy()

    def load_descriptions_list(self):
        """ Load a list of all descriptions for searching """
        self.desc_dialog = SingleButtonDialog(
            _("Please Wait!"), self.mainwindow,
            _("Loading package descriptions..."), self.desc_dialog_response,
            "_Cancel", True)
        debug.dprint("MAINWINDOW: load_descriptions_list(); " +
                     "starting self.desc_thread")
        db.db.load_descriptions()
        db.db.set_desc_callback(self.desc_thread_update)

    def desc_dialog_response(self, widget, response):
        """ Get response from description loading dialog """
        # kill the update thread
        db.db.cancell_desc_update()
        self.desc_dialog.destroy()

    def desc_thread_update(self, args):
        """ Update status of description loading process """
        if args['done']:
            if not args['cancelled']:
                # search with descriptions
                self.package_search(None)
            self.desc_dialog.destroy()
            return False
        else:
            # print self.desc_thread.count
            if args['count']:
                fraction = args['count'] / float(len(db.db.list))
                self.desc_dialog.progbar.set_text(
                    str(int(fraction * 100)) + "%")
                self.desc_dialog.progbar.set_fraction(fraction)
        return True

    # start of search callback
    def search_done(self):
        """show the search results from the search thread"""
        #if self.search_thread.done:
        if not self.search_thread.cancelled:
            # grab the list
            package_list = self.search_thread.package_list
            count = self.search_thread.pkg_count
            search_term = self.search_thread.search_term
            # kill off the thread
            self.search_thread.join()
        # in case the search view was already active
        self.status.update_statusbar(SHOW_SEARCH)
        self.pkg_list["Search"][search_term] = package_list
        self.pkg_count["Search"][search_term] = count
        #Add the current search item & select it
        self.category_view.populate(self.pkg_list["Search"].keys(), True,
                                    self.pkg_count["Search"])
        _iter = self.category_view.model.get_iter_first()
        while _iter != None:
            if self.category_view.model.get_value(_iter, 1) == search_term:
                selection = self.category_view.get_selection()
                selection.select_iter(_iter)
                break
            _iter = self.category_view.model.iter_next(_iter)
        self.package_view.populate(package_list)
        if count == 1:  # then select it
            self.current_pkg_name["Search"] = package_list.keys()[0]
        self.category_view.last_category = search_term
        self.category_changed(search_term)

    def view_filter_changed(self, widget):
        """Update the treeviews for the selected filter"""
        #debug.dprint("MAINWINDOW: view_filter_changed()")
        myview = widget.get_active()
        debug.dprint("MAINWINDOW: view_filter_changed(); myview = %d" % myview)
        self.status.update_statusbar(myview, self.reader)
        cat_scroll = self.wtree.get_widget("category_scrolled_window")
        self.category_view.set_search(False)
        self.clear_package_detail()
        cat = None
        pack = None
        sort_categories = False

        if myview in self.plugin_views.keys():
            if self.plugin_view[myview]["package_view"]:
                self.chg_pkgview(self.plugin_view[myview]["package_view"])
            self.plugin_view[myview]["view_changed"]
        elif myview in (SHOW_INSTALLED, SHOW_ALL):
            self.chg_pkgview(self.package_view)
            if myview == SHOW_ALL:
                items = db.db.categories.keys()
                count = db.db.pkg_count
            else:
                items = db.db.installed.keys()
                count = db.db.installed_pkg_count
            self.category_view.populate(items, True, count)
            cat_scroll.show()
            debug.dprint("MAINWINDOW: view_filter_changed(); " +
                         "reset package_view")
            self.package_view.set_view(PACKAGES)
            debug.dprint("MAINWINDOW: view_filter_changed(); " +
                         "init package_view")
            self.package_view._init_view()
            #debug.dprint("MAINWINDOW: view_filter_changed(); " +
            #"clear package_view")
            #self.package_view.clear()
            cat = self.current_cat_name[INDEX_TYPES[myview]]
            pack = self.current_pkg_name[INDEX_TYPES[myview]]
            debug.dprint("MAINWINDOW: view_filter_changed(); " +
                         "reselect category & package")
        elif myview == SHOW_SEARCH:
            self.chg_pkgview(self.package_view)
            self.category_view.set_search(True)
            if not self.loaded[INDEX_TYPES[myview]]:
                self.set_package_actions_sensitive(False, None)
                self.category_view.populate(
                    self.pkg_list[INDEX_TYPES[myview]].keys(), True,
                    self.pkg_count[INDEX_TYPES[myview]])
                self.package_search(None)
                self.loaded[INDEX_TYPES[myview]] = True
            else:
                self.category_view.populate(
                    self.pkg_list[INDEX_TYPES[myview]].keys(), True,
                    self.pkg_count[INDEX_TYPES[myview]])
            cat_scroll.show()
            debug.dprint("MAIN: Showing search results")
            self.package_view.set_view(SEARCH)
            cat = self.current_search
            pack = self.current_pkg_name[INDEX_TYPES[myview]]
        elif myview in [SHOW_UPGRADE, SHOW_DEPRECATED, SHOW_SETS]:
            debug.dprint("MAINWINDOW: view_filter_changed(); '" +
                         INDEX_TYPES[myview] + "' selected")
            self.chg_pkgview(self.package_view)
            cat_scroll.show()
            # all need to be sorted for them to be
            # displayed in the tree correctly
            sort_categories = True
            if myview == SHOW_UPGRADE:
                self.package_view.set_view(UPGRADABLE)
            elif myview == SHOW_DEPRECATED:
                self.package_view.set_view(DEPRECATED)
            else:
                self.package_view.set_view(SETS)
            if not self.loaded[INDEX_TYPES[myview]]:
                debug.dprint(
                    "MAINWINDOW: view_filter_changed(); " +
                    "calling load_reader_list('" + INDEX_TYPES[myview] +
                    "') reader_running = %s ********************************" %
                    self.reader_running)
                self.load_reader_list(INDEX_TYPES[myview])
                self.package_view.clear()
                self.category_view.clear()
                debug.dprint("MAINWINDOW: view_filter_changed(); " +
                             "back from load_reader_list('" +
                             INDEX_TYPES[myview] + "')")
            else:
                debug.dprint(
                    "MAINWINDOW: view_filter_changed(); " +
                    "calling category_view.populate() with categories:" +
                    str(self.pkg_list[INDEX_TYPES[myview]].keys()))
                self.category_view.populate(
                    self.pkg_list[INDEX_TYPES[myview]].keys(), sort_categories,
                    self.pkg_count[INDEX_TYPES[myview]])
            #self.package_view.set_view(UPGRADABLE)
            debug.dprint(
                "MAINWINDOW: view_filter_changed(); init package_view")
            self.package_view._init_view()
            #debug.dprint("MAINWINDOW: view_filter_changed(); " +
            #"clear package_view")
            #self.package_view.clear()
            cat = self.current_cat_name[INDEX_TYPES[myview]]
            pack = self.current_pkg_name[INDEX_TYPES[myview]]
        #~ elif myview == SHOW_SETS:
        #~ debug.dprint("MAINWINDOW: view_filter_changed(); Sets selected")
        #~ cat = None #self.current_cat_name["All_Installed"]
        #~ pack = None #self.current_pkg_name["All_Installed"]
        #~ pass

        debug.dprint("MAINWINDOW: view_filter_changed(); " +
                     "reselect category & package (maybe)")
        if cat != None:  # and pack != None:
            self.select_category_package(cat, pack)
        # clear the notebook tabs
        #self.clear_package_detail()
        #if self.last_view_setting != myview:
        debug.dprint("MAINWINDOW: view_filter_changed(); last_view_setting " +
                     str(self.last_view_setting) + " changed: myview = " +
                     str(myview))
        self.last_view_setting = myview
        #self.current_cat_name["All_Installed"] = None
        #self.category_view.last_category = None
        #self.current_cat_cursor["All_Installed"] = None
        #self.current_pkg_cursor["All_Installed"] = None

    def load_reader_list(self, reader):
        """multipurpose loader can run a number of different
        reader threads"""
        self.reader_progress = 1
        # package list is not loaded, create dialog and load them
        self.status.set_statusbar2(
            _("Generating '%s' packages list...") % READER_NAMES[reader])
        # create reader thread for loading the packages
        if self.reader_running:
            debug.dprint(
                "MAINWINDOW: load_reader_list(); " +
                "thread already running!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
            return
        debug.dprint("MAINWINDOW: load_reader_list(); starting thread")
        if reader == "Deprecated":
            self.reader = DeprecatedReader(db.db.installed.items())
        elif reader == "Upgradable":
            self.reader = UpgradableListReader(db.db.installed.items())
        elif reader == "Sets":
            self.reader = SetListReader()

        self.reader.start()
        self.reader_running = True
        debug.dprint("MAINWINDOW: load_reader_list(); " +
                     "reader_running set to True")
        self.build_deps = False
        # add a timeout to check if thread is done
        gobject.timeout_add(200, self.update_reader_thread)
        self.set_cancel_btn(ON)

    def wait_dialog_response(self, widget, response):
        """ Get a response from the wait dialog """
        if response == 0:
            # terminate the thread
            self.reader.please_die()
            self.reader.join()
            # get rid of the dialog
            self.wait_dialog.destroy()

    def update_reader_thread(self):
        """ Find out if thread is finished """
        # needs error checking perhaps...
        reader_type = self.reader.reader_type
        if self.reader.done:
            debug.dprint("MAINWINDOW: update_reader_thread(): " +
                         "self.reader.done detected")
            return self._reader_done(reader_type)
        elif self.reader.progress < 2:
            # Still building system package list nothing to do
            pass
        else:
            # statusbar hack,
            # should probably be converted to use a Dispatcher callback
            if self.reader.progress >= 2 and self.reader_progress == 1:
                self.status.set_statusbar2(
                    _("Searching for '%s' packages...") %
                    READER_NAMES[self.reader.reader_type])
                self.reader_progress = 2
            if self.reader_running:
                try:
                    if self.build_deps:
                        count = 0
                        for key in self.reader.pkg_count:
                            count += self.reader.pkg_count[key]
                        fraction = count / float(self.reader.pkg_dict_total)
                        self.status.progressbar.set_text(
                            str(int(fraction * 100)) + "%")
                        self.status.progressbar.set_fraction(fraction)
                    else:
                        fraction = \
                            self.reader.count / float(db.db.installed_count)
                        self.status.progressbar.set_text(
                            str(int(fraction * 100)) + "%")
                        self.status.progressbar.set_fraction(fraction)
                        if fraction == 1:
                            self.build_deps = True
                            self.status.set_statusbar2(
                                _("Building Package List"))
                except Exception, _error:
                    debug.dprint("MAINWINDOW: update_reader_thread(): " +
                                 "Exception: %s" % _error)
        return True
Exemplo n.º 2
0
class ActionHandler(CategoryHandler):
    '''Support functions for mainwindow actions'''
    def __init__(self):
        CategoryHandler.__init__(self)
        self.get_sync_time()
        self.new_sync = False
        # create and start our process manager
        self.process_manager = ProcessManager(utils.environment(), False)

    def package_update(self, pkg):
        """callback function to update an individual package
            after a successfull emerge was detected"""
        # find the pkg in db.db
        db.db.update(PMS_LIB.extract_package(pkg))

    def sync_callback(self):
        """re-initializes portage so it uses the new metadata cache
           then init our db"""
        #self.re_init_portage()
        PMS_LIB.settings.reset()
        # self.reload==False is currently broken for init_data when
        # reloading after a sync
        #self.init_data()
        self.new_sync = True
        self.reload_db()
        self.refresh()

    def get_sync_time(self):
        """gets and returns the timestamp info saved during
           the last portage tree sync"""
        self.last_sync, self.valid_sync = get_sync_info()

    def set_sync_tip(self):
        """Sets the sync tip for the new or old toolbar API"""
        self.widget["btn_sync"].set_has_tooltip(True)
        self.widget["btn_sync"].set_tooltip_text(' '.join(
            [self.sync_tip, self.last_sync[:], '']))

    def action_callback(self, action=None, arg=None):
        """dispatcher interface callback to handle various actions."""
        debug.dprint("MAINWINDOW: action_callback(); " +
                     "caller = %s, action = '%s', arg = %s" %
                     (arg['caller'], str(action), str(arg)))
        if action in ["adv_emerge", "set path", "package changed", "refresh"]:
            # handle possible spaces in callback action string
            _action = action.replace(' ', '_')
            ret_val = None
            ret_val = getattr(self, "_action_%s_" % _action)(arg)
            if ret_val:
                return ret_val
        else:
            return self._action_install(action, arg)

    def _action_adv_emerge_(self, arg):
        """handle advanced emerge action callback"""
        if 'package' in arg:
            package = arg['package']
        elif 'full_name' in arg:
            package = db.db.get_package(arg['full_name'])
        else:
            debug.dprint(
                "MAINWINDOW: _action_adv_emerge_(); did not get an " +
                "expected arg variable for 'adv_emerge' action arg = " +
                str(arg))
            return False
        self.adv_emerge_package(package)
        return True

    def _action_set_path_(self, arg):
        """handle a path setting callback"""
        # save the path to the package that matched the name passed
        # to populate() in PackageView... (?)
        x = self.widget["view_filter"].get_active()
        self.current_pkg_path[x] = arg['path']  # arg = path

    def _action_package_changed_(self, arg):
        """handle a package changed callback"""
        self.package_changed(arg['package'])
        return True

    def _action_refresh_(self, arg):
        """handle a refresh action callback"""
        self.refresh()
        return True

    def _action_install(self, action, arg):
        """handle install commnad callbacks"""
        old_pretend_value = config.Prefs.emerge.pretend
        old_verbose_value = config.Prefs.emerge.verbose
        if "emerge" in action:
            commands = ["emerge "]
        elif "unmerge" in action:
            commands = ["emerge --unmerge "]
        if "pretend" in action:
            config.Prefs.emerge.pretend = True
        else:
            config.Prefs.emerge.pretend = False
        if "sudo" in action:
            commands = ['sudo -p "Password: "******"ebuild" in arg:
            commands.append('=' + arg['ebuild'])
            cp = PMS_LIB.pkgsplit(arg['ebuild'])[0]
        elif 'package' in arg:
            cp = arg['package'].full_name
            commands.append(arg['package'].full_name)
        elif 'full_name' in arg:
            cp = arg['full_name']
            commands.append(arg['full_name'])
        else:
            debug.dprint("MAINWINDOW action_callback(): unknown arg '%s'" %
                         str(arg))
            return False
        self.setup_command(PMS_LIB.get_name(cp), ''.join(commands))
        config.Prefs.emerge.pretend = old_pretend_value
        config.Prefs.emerge.verbose = old_verbose_value
        return True

    def setup_command(self, package_name, command, run_anyway=False):
        """Setup the command to run or not"""
        if (self.is_root or run_anyway
                or (config.Prefs.emerge.pretend
                    and not command.startswith(config.Prefs.globals.Sync))
                or command.startswith("sudo ")
                or utils.pretend_check(command)):
            if command.startswith('sudo -p "Password: "******"Password: "******"MAINWINDOW: setup_command(); emerge.pretend = " +
                "%s, pretend_check = %s, help_check = %s, info_check = %s" %
                (str(config.Prefs.emerge.pretend), str(is_pretend),
                 str(utils.help_check(command)),
                 str(utils.info_check(command))))
            if (config.Prefs.emerge.pretend or is_pretend
                    or utils.help_check(command) or utils.info_check(command)):
                # temp set callback for testing
                #callback = self.sync_callback
                callback = lambda: None  # a function that does nothing
                debug.dprint("MAINWINDOW: setup_command(); " +
                             "callback set to lambda: None")
            elif package_name == "Sync Portage Tree":
                callback = self.sync_callback  #self.init_data
                debug.dprint("MAINWINDOW: setup_command(); " +
                             "callback set to self.sync_callback")
            else:
                #debug.dprint("MAINWINDOW: setup_command(); " +
                #"setting callback()")
                callback = self.reload_db
                debug.dprint("MAINWINDOW: setup_command(); " +
                             "callback set to self.reload_db")
                #callback = self.package_update
            #ProcessWindow(command, env, config.Prefs, callback)
            self.process_manager.add(package_name, command, callback,
                                     _("Porthole Main Window"))
        else:
            debug.dprint("MAINWINDOW: Must be root user to run command '%s' " %
                         command)
            #self.sorry_dialog=utils.SingleButtonDialog(_("You are not root!"),
            #        self.mainwindow,
            #        _("Please run Porthole as root to emerge packages!"),
            #        None, "_Ok")
            self.check_for_root()  # displays not root dialog
            return False
        return True

    def emerge_package(self, package, sudo=False):
        """Emerge the package."""
        if (sudo or (not utils.is_root() and utils.can_sudo())) \
                and not config.Prefs.emerge.pretend:
            self.setup_command(
                package.get_name(), 'sudo -p "Password: "******"emerge" +
                config.Prefs.emerge.get_string() + package.full_name)

    def adv_emerge_package(self, package):
        """Advanced emerge of the package."""
        # Activate the advanced emerge dialog window
        # re_init_portage callback is for when package.use etc. are modified
        return AdvancedEmergeDialog(package, self.setup_command,
                                    self.re_init_portage)

    def unmerge_package(self, package, sudo=False):
        """Unmerge the package."""
        if (sudo or (not self.is_root and utils.can_sudo())) \
                and not config.Prefs.emerge.pretend:
            self.setup_command(
                package.get_name(), 'sudo -p "Password: "******"emerge --unmerge" +
                config.Prefs.emerge.get_string() + package.full_name)

    def sync_tree(self, *widget):
        """Sync the portage tree and reload it when done."""
        sync = config.Prefs.globals.Sync
        if config.Prefs.emerge.verbose:
            sync += " --verbose"
        if config.Prefs.emerge.nospinner:
            sync += " --nospinner "
        if utils.is_root():
            self.setup_command("Sync Portage Tree", sync)
        elif utils.can_sudo():
            self.setup_command("Sync Portage Tree",
                               'sudo -p "Password: "******""" Open a log of a previous emerge in a new terminal window """
        newterm = ProcessManager(utils.environment(), True)
        newterm.do_open(widget, None)
        return

    def custom_run(self, *widget):
        """ Run a custom command in the terminal window """
        #debug.dprint("MAINWINDOW: entering custom_run")
        #debug.dprint(config.Prefs.run_dialog.history)
        RunDialog(self.setup_command, run_anyway=True)
        return

    def check_for_root(self, *args):
        """figure out if the user can emerge or not..."""
        if not self.is_root:
            self.no_root_dialog = SingleButtonDialog(
                _("No root privileges"), self.mainwindow,
                _("In order to access all the features of Porthole,\nplease run it with root privileges."
                  ), self.remove_nag_dialog, _("_Ok"))

    def remove_nag_dialog(self, widget, response):
        """ Remove the nag dialog and set it to not display next time """
        self.no_root_dialog.destroy()
        config.Prefs.main.show_nag_dialog = False