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 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 add(self, package_name, command_string, callback, sender): """ Add a process to the queue """ debug.dprint("TERM_QUEUE: add(): command = " + str(command_string)) # if the last process was killed, check if it's the same thing self.resume_string = None skip_first = False if self.killed_id: debug.dprint("TERM_QUEUE: add(): self.killed is true") if package_name == self.get_name( ) and command_string == self.get_command(): debug.dprint("TERM_QUEUE: add(): showing resume dialog") # The process has been killed, so help the user out a bit message = _("The package you selected is already in the emerge queue,\n" \ "but it has been killed. Would you like to resume the emerge?") result = self.resume_dialog(message) if result == gtk.RESPONSE_ACCEPT: # Execute self.cleanup() elif result == gtk.RESPONSE_YES: # Resume self.resume_string = " --resume" else: # Cancel return False # add resume to the command only if it's queue id matches. # this allows Resume to restart the queue if the killed process was removed from the queue if self.killed_id == self.queue_model.get_value( self.process_iter, self.queue_model.column['id']): command = self.queue_model.get_value( self.process_iter, self.queue_model.column['command']) command += self.resume_string self.queue_model.set_value( self.process_iter, self.queue_model.column['command'], str(command)) else: # clean up the killed process self.cleanup() skip_first = True if self.resume_string is None: debug.dprint("TERM_QUEUE: add(): resume is None") # check if the package is already in the emerge queue if self.process_iter: search_iter = self.process_iter.copy() while search_iter: command = self.queue_model.get_value( search_iter, self.queue_model.column['command']) name = self.queue_model.get_value( search_iter, self.queue_model.column['name']) if package_name == name and command_string == command: debug.dprint("TERM_QUEUE: add(): repeat command match") # Let the user know it's already in the list message = _( "The package you selected is already in the emerge queue!" ) debug.dprint("TERM_QUEUE: add(); gettext result = " + _("Error Adding Package To Queue!")) SingleButtonDialog(_("Error Adding Package To Queue!"), None, message, None, _("OK")) debug.dprint( "TERM_QUEUE: add(): returning from match dialog & returning" ) return False search_iter = self.queue_model.iter_next(search_iter) del search_iter # show the window if it isn't visible if self.new_window: self.new_window = False if self.resume_string is None: # add to the queue tab insert_iter = self.queue_model.append() #insert_before(None, None) self.queue_model.set_data( insert_iter, { 'icon': None, 'name': str(package_name), 'command': str(command_string), 'id': self.next_id, 'sender': str(sender), 'callback': callback, 'completed': False }) if self.queue_paused and self.paused_iter == None: self.paused_id = self.process_id + 1 if self.process_iter: self.paused_iter = self.queue_model.iter_next( self.process_iter) elif self.next_id == 1: self.paused_iter = self.queue_model.get_iter_first() self.set_icon(PAUSED, self.paused_id) self.next_id += 1 # show the queue tab! self.show_queue() self.qmenu_items["clear_queue"].set_sensitive(True) # if no process is running, let's start one! if not self.reader.process_running: self.start(skip_first) return True
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
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