class Application: """ Main application class; starting and stopping of the application is controlled from here, together with some interactions from the tray icon. """ def __init__(self): aboutData = KAboutData(APP_NAME, CATALOG, PROGRAM_NAME, VERSION, DESCRIPTION, LICENSE, COPYRIGHT, TEXT, HOMEPAGE, BUG_EMAIL) aboutData.addAuthor(ki18n("GuoCi"), ki18n("Python 3 port maintainer"), "*****@*****.**", "") aboutData.addAuthor(ki18n("Chris Dekter"), ki18n("Developer"), "*****@*****.**", "") aboutData.addAuthor(ki18n("Sam Peterson"), ki18n("Original developer"), "*****@*****.**", "") aboutData.setProgramIconName(common.ICON_FILE) self.aboutData = aboutData KCmdLineArgs.init(sys.argv, aboutData) options = KCmdLineOptions() options.add("l").add("verbose", ki18n("Enable verbose logging")) options.add("c").add("configure", ki18n("Show the configuration window on startup")) KCmdLineArgs.addCmdLineOptions(options) args = KCmdLineArgs.parsedArgs() self.app = KApplication() try: # Create configuration directory if not os.path.exists(CONFIG_DIR): os.makedirs(CONFIG_DIR) # Initialise logger rootLogger = logging.getLogger() rootLogger.setLevel(logging.DEBUG) if args.isSet("verbose"): handler = logging.StreamHandler(sys.stdout) else: handler = logging.handlers.RotatingFileHandler(LOG_FILE, maxBytes=MAX_LOG_SIZE, backupCount=MAX_LOG_COUNT) handler.setLevel(logging.INFO) handler.setFormatter(logging.Formatter(LOG_FORMAT)) rootLogger.addHandler(handler) if self.__verifyNotRunning(): self.__createLockFile() self.initialise(args.isSet("configure")) except Exception as e: self.show_error_dialog(i18n("Fatal error starting AutoKey.\n") + str(e)) logging.exception("Fatal error starting AutoKey: " + str(e)) sys.exit(1) def __createLockFile(self): f = open(LOCK_FILE, 'w') f.write(str(os.getpid())) f.close() def __verifyNotRunning(self): if os.path.exists(LOCK_FILE): f = open(LOCK_FILE, 'r') pid = f.read() f.close() # Check that the found PID is running and is autokey with subprocess.Popen(["ps", "-p", pid, "-o", "command"], stdout=subprocess.PIPE) as p: output = p.communicate()[0].decode() if "autokey" in output: logging.debug("AutoKey is already running as pid %s", pid) bus = dbus.SessionBus() try: dbusService = bus.get_object("org.autokey.Service", "/AppService") dbusService.show_configure(dbus_interface = "org.autokey.Service") sys.exit(0) except dbus.DBusException as e: logging.exception("Error communicating with Dbus service") self.show_error_dialog(i18n("AutoKey is already running as pid %1 but is not responding", pid), str(e)) sys.exit(1) return True def main(self): self.app.exec_() def initialise(self, configure): logging.info("Initialising application") self.monitor = monitor.FileMonitor(self) self.configManager = get_config_manager(self) self.service = service.Service(self) self.serviceDisabled = False # Initialise user code dir if self.configManager.userCodeDir is not None: sys.path.append(self.configManager.userCodeDir) try: self.service.start() except Exception as e: logging.exception("Error starting interface: " + str(e)) self.serviceDisabled = True self.show_error_dialog(i18n("Error starting interface. Keyboard monitoring will be disabled.\n" + "Check your system/configuration."), str(e)) self.notifier = Notifier(self) self.configWindow = None self.monitor.start() dbus.mainloop.qt.DBusQtMainLoop(set_as_default=True) self.dbusService = common.AppService(self) if ConfigManager.SETTINGS[IS_FIRST_RUN] or configure: ConfigManager.SETTINGS[IS_FIRST_RUN] = False self.show_configure() self.handler = CallbackEventHandler() kbChangeFilter = KeyboardChangeFilter(self.service.mediator.interface) self.app.installEventFilter(kbChangeFilter) def init_global_hotkeys(self, configManager): logging.info("Initialise global hotkeys") configManager.toggleServiceHotkey.set_closure(self.toggle_service) configManager.configHotkey.set_closure(self.show_configure_async) def config_altered(self, persistGlobal): self.configManager.config_altered(persistGlobal) self.notifier.build_menu() def hotkey_created(self, item): logging.debug("Created hotkey: %r %s", item.modifiers, item.hotKey) self.service.mediator.interface.grab_hotkey(item) def hotkey_removed(self, item): logging.debug("Removed hotkey: %r %s", item.modifiers, item.hotKey) self.service.mediator.interface.ungrab_hotkey(item) def path_created_or_modified(self, path): time.sleep(0.5) changed = self.configManager.path_created_or_modified(path) if changed and self.configWindow is not None: self.configWindow.config_modified() def path_removed(self, path): time.sleep(0.5) changed = self.configManager.path_removed(path) if changed and self.configWindow is not None: self.configWindow.config_modified() def unpause_service(self): """ Unpause the expansion service (start responding to keyboard and mouse events). """ self.service.unpause() self.notifier.update_tool_tip() def pause_service(self): """ Pause the expansion service (stop responding to keyboard and mouse events). """ self.service.pause() self.notifier.update_tool_tip() def toggle_service(self): """ Convenience method for toggling the expansion service on or off. """ if self.service.is_running(): self.pause_service() else: self.unpause_service() def shutdown(self): """ Shut down the entire application. """ logging.info("Shutting down") self.app.closeAllWindows() self.notifier.hide_icon() self.service.shutdown() self.monitor.stop() self.app.quit() os.remove(LOCK_FILE) logging.debug("All shutdown tasks complete... quitting") def notify_error(self, message): """ Show an error notification popup. @param message: Message to show in the popup """ self.exec_in_main(self.notifier.notify_error, message) def update_notifier_visibility(self): self.notifier.update_visible_status() def show_configure(self): """ Show the configuration window, or deiconify (un-minimise) it if it's already open. """ logging.info("Displaying configuration window") try: self.configWindow.showNormal() self.configWindow.activateWindow() except (AttributeError, RuntimeError): # AttributeError when the main window is shown the first time, RuntimeError subsequently. self.configWindow = ConfigWindow(self) self.configWindow.show() def show_configure_async(self): self.exec_in_main(self.show_configure) def show_error_dialog(self, message, details=None): """ Convenience method for showing an error dialog. """ if details is None: KMessageBox.error(None, message) else: KMessageBox.detailedError(None, message, details) def show_script_error(self): """ Show the last script error (if any) """ if self.service.scriptRunner.error != '': KMessageBox.information(None, self.service.scriptRunner.error, i18n("View Script Error Details")) self.service.scriptRunner.error = '' else: KMessageBox.information(None, i18n("No error information available"), i18n("View Script Error Details")) def show_popup_menu(self, folders=[], items=[], onDesktop=True, title=None): self.exec_in_main(self.__createMenu, folders, items, onDesktop, title) def hide_menu(self): self.exec_in_main(self.menu.hide) def __createMenu(self, folders, items, onDesktop, title): self.menu = PopupMenu(self.service, folders, items, onDesktop, title) self.menu.popup(QCursor.pos()) self.menu.setFocus() def exec_in_main(self, callback, *args): self.handler.postEventWithCallback(callback, *args)
class Magneto(MagnetoCore): """ Magneto Updates Notification Applet class. """ def __init__(self): app_name = "magneto" catalog = "" prog_name = ki18n("Magneto") version = "1.0" description = ki18n("System Update Status") lic = KAboutData.License_GPL cright = ki18n("(c) 2013 Fabio Erculiani") text = ki18n("none") home_page = "www.sabayon.org" bug_mail = "*****@*****.**" self._kabout = KAboutData (app_name, catalog, prog_name, version, description, lic, cright, text, home_page, bug_mail) argv = [sys.argv[0]] KCmdLineArgs.init(argv, self._kabout) self._app = KApplication() from dbus.mainloop.qt import DBusQtMainLoop super(Magneto, self).__init__(main_loop_class = DBusQtMainLoop) self._window = KStatusNotifierItem() # do not show "Quit" and use quitSelected() signal self._window.setStandardActionsEnabled(False) icon_name = self.icons.get("okay") self._window.setIconByName(icon_name) self._window.setStatus(KStatusNotifierItem.Passive) self._window.connect(self._window, SIGNAL("activateRequested(bool,QPoint)"), self.applet_activated) self._menu = KMenu(_("Magneto Entropy Updates Applet")) self._window.setContextMenu(self._menu) self._menu_items = {} for item in self._menu_item_list: if item is None: self._menu.addSeparator() continue myid, _unused, mytxt, myslot_func = item name = self.get_menu_image(myid) action_icon = KIcon(name) w = KAction(action_icon, mytxt, self._menu) self._menu_items[myid] = w self._window.connect(w, SIGNAL("triggered()"), myslot_func) self._menu.addAction(w) self._menu.hide() def _first_check(self): def _do_check(): self.send_check_updates_signal(startup_check = True) return False if self._dbus_service_available: QTimer.singleShot(10000, _do_check) def startup(self): """ Start user interface. """ self._dbus_service_available = self.setup_dbus() if config.settings["APPLET_ENABLED"] and \ self._dbus_service_available: self.enable_applet(do_check = False) else: self.disable_applet() if not self._dbus_service_available: QTimer.singleShot(30000, self.show_service_not_available) else: self._first_check() # Notice Window instance self._notice_window = AppletNoticeWindow(self) # Enter main loop self._app.exec_() def close_service(self): super(Magneto, self).close_service() self._app.quit() def change_icon(self, icon_name): name = self.icons.get(icon_name) self._window.setIconByName(name) def disable_applet(self, *args): super(Magneto, self).disable_applet() self._menu_items["disable_applet"].setEnabled(False) self._menu_items["enable_applet"].setEnabled(True) def enable_applet(self, w = None, do_check = True): done = super(Magneto, self).enable_applet(do_check = do_check) if done: self._menu_items["disable_applet"].setEnabled(True) self._menu_items["enable_applet"].setEnabled(False) def show_alert(self, title, text, urgency = None, force = False, buttons = None): if ((title, text) == self.last_alert) and not force: return def _action_activate_cb(action_num): if not buttons: return try: action_info = buttons[action_num - 1] except IndexError: return _action_id, _button_name, button_callback = action_info button_callback() def do_show(): notification = KNotification("Updates") # Keep a reference or the callback of the actions added # below will never work. # See: https://bugzilla.redhat.com/show_bug.cgi?id=241531 self.__last_notification = notification notification.setFlags(KNotification.CloseOnTimeout) notification.setText("<b>%s</b><br/>%s" % (title, text,)) if buttons: notification.setActions([x[1] for x in buttons]) notification.connect( notification, SIGNAL("activated(unsigned int)"), _action_activate_cb) icon_name = "okay" status = KStatusNotifierItem.Passive if urgency == "critical": icon_name = "critical" status = KStatusNotifierItem.Active name = self.icons.get(icon_name) icon = KIcon(name) self._window.setStatus(status) notification.setPixmap(icon.pixmap(48, 48)) notification.sendEvent() self.last_alert = (title, text) # thread safety QTimer.singleShot(0, do_show) def update_tooltip(self, tip): def do_update(): self._window.setToolTipTitle(tip) QTimer.singleShot(0, do_update) def applet_context_menu(self): """ No action for now. """ pass def applet_activated(self, active, pos): if active: self.applet_doubleclick() def hide_notice_window(self): self.notice_window_shown = False self._notice_window.hide() def show_notice_window(self): if self.notice_window_shown: return if not self.package_updates: return entropy_ver = None packages = [] for atom in self.package_updates: key = entropy.dep.dep_getkey(atom) avail_rev = entropy.dep.dep_get_entropy_revision(atom) avail_tag = entropy.dep.dep_gettag(atom) my_pkg = entropy.dep.remove_entropy_revision(atom) my_pkg = entropy.dep.remove_tag(my_pkg) pkgcat, pkgname, pkgver, pkgrev = entropy.dep.catpkgsplit(my_pkg) ver = pkgver if pkgrev != "r0": ver += "-%s" % (pkgrev,) if avail_tag: ver += "#%s" % (avail_tag,) if avail_rev: ver += "~%s" % (avail_tag,) if key == "sys-apps/entropy": entropy_ver = ver packages.append("%s (%s)" % (key, ver,)) critical_msg = "" if entropy_ver is not None: critical_msg = "%s <b>sys-apps/entropy</b> " "%s, %s <b>%s</b>. %s." % ( _("Your system currently has an outdated version of"), _("installed"), _("the latest available version is"), entropy_ver, _("It is recommended that you upgrade to " "the latest before updating any other packages") ) self._notice_window.populate(packages, critical_msg) self._notice_window.show() self.notice_window_shown = True
class Application: """ Main application class; starting and stopping of the application is controlled from here, together with some interactions from the tray icon. """ def __init__(self): aboutData = KAboutData(APP_NAME, CATALOG, PROGRAM_NAME, VERSION, DESCRIPTION, LICENSE, COPYRIGHT, TEXT, HOMEPAGE, BUG_EMAIL) aboutData.addAuthor(ki18n("GuoCi"), ki18n("Python 3 port maintainer"), "*****@*****.**", "") aboutData.addAuthor(ki18n("Chris Dekter"), ki18n("Developer"), "*****@*****.**", "") aboutData.addAuthor(ki18n("Sam Peterson"), ki18n("Original developer"), "*****@*****.**", "") aboutData.setProgramIconName(common.ICON_FILE) self.aboutData = aboutData KCmdLineArgs.init(sys.argv, aboutData) options = KCmdLineOptions() options.add("l").add("verbose", ki18n("Enable verbose logging")) options.add("c").add("configure", ki18n("Show the configuration window on startup")) KCmdLineArgs.addCmdLineOptions(options) args = KCmdLineArgs.parsedArgs() self.app = KApplication() try: # Create configuration directory if not os.path.exists(CONFIG_DIR): os.makedirs(CONFIG_DIR) # Initialise logger rootLogger = logging.getLogger() rootLogger.setLevel(logging.DEBUG) if args.isSet("verbose"): handler = logging.StreamHandler(sys.stdout) else: handler = logging.handlers.RotatingFileHandler( LOG_FILE, maxBytes=MAX_LOG_SIZE, backupCount=MAX_LOG_COUNT) handler.setLevel(logging.INFO) handler.setFormatter(logging.Formatter(LOG_FORMAT)) rootLogger.addHandler(handler) if self.__verifyNotRunning(): self.__createLockFile() self.initialise(args.isSet("configure")) except Exception as e: self.show_error_dialog( i18n("Fatal error starting AutoKey.\n") + str(e)) logging.exception("Fatal error starting AutoKey: " + str(e)) sys.exit(1) def __createLockFile(self): f = open(LOCK_FILE, 'w') f.write(str(os.getpid())) f.close() def __verifyNotRunning(self): if os.path.exists(LOCK_FILE): f = open(LOCK_FILE, 'r') pid = f.read() f.close() # Check that the found PID is running and is autokey with subprocess.Popen(["ps", "-p", pid, "-o", "command"], stdout=subprocess.PIPE) as p: output = p.communicate()[0].decode() if "autokey" in output: logging.debug("AutoKey is already running as pid %s", pid) bus = dbus.SessionBus() try: dbusService = bus.get_object("org.autokey.Service", "/AppService") dbusService.show_configure( dbus_interface="org.autokey.Service") sys.exit(0) except dbus.DBusException as e: logging.exception("Error communicating with Dbus service") self.show_error_dialog( i18n( "AutoKey is already running as pid %1 but is not responding", pid), str(e)) sys.exit(1) return True def main(self): self.app.exec_() def initialise(self, configure): logging.info("Initialising application") self.monitor = monitor.FileMonitor(self) self.configManager = get_config_manager(self) self.service = service.Service(self) self.serviceDisabled = False # Initialise user code dir if self.configManager.userCodeDir is not None: sys.path.append(self.configManager.userCodeDir) try: self.service.start() except Exception as e: logging.exception("Error starting interface: " + str(e)) self.serviceDisabled = True self.show_error_dialog( i18n( "Error starting interface. Keyboard monitoring will be disabled.\n" + "Check your system/configuration."), str(e)) self.notifier = Notifier(self) self.configWindow = None self.monitor.start() dbus.mainloop.qt.DBusQtMainLoop(set_as_default=True) self.dbusService = common.AppService(self) if ConfigManager.SETTINGS[IS_FIRST_RUN] or configure: ConfigManager.SETTINGS[IS_FIRST_RUN] = False self.show_configure() self.handler = CallbackEventHandler() kbChangeFilter = KeyboardChangeFilter(self.service.mediator.interface) self.app.installEventFilter(kbChangeFilter) def init_global_hotkeys(self, configManager): logging.info("Initialise global hotkeys") configManager.toggleServiceHotkey.set_closure(self.toggle_service) configManager.configHotkey.set_closure(self.show_configure_async) def config_altered(self, persistGlobal): self.configManager.config_altered(persistGlobal) self.notifier.build_menu() def hotkey_created(self, item): logging.debug("Created hotkey: %r %s", item.modifiers, item.hotKey) self.service.mediator.interface.grab_hotkey(item) def hotkey_removed(self, item): logging.debug("Removed hotkey: %r %s", item.modifiers, item.hotKey) self.service.mediator.interface.ungrab_hotkey(item) def path_created_or_modified(self, path): time.sleep(0.5) changed = self.configManager.path_created_or_modified(path) if changed and self.configWindow is not None: self.configWindow.config_modified() def path_removed(self, path): time.sleep(0.5) changed = self.configManager.path_removed(path) if changed and self.configWindow is not None: self.configWindow.config_modified() def unpause_service(self): """ Unpause the expansion service (start responding to keyboard and mouse events). """ self.service.unpause() self.notifier.update_tool_tip() def pause_service(self): """ Pause the expansion service (stop responding to keyboard and mouse events). """ self.service.pause() self.notifier.update_tool_tip() def toggle_service(self): """ Convenience method for toggling the expansion service on or off. """ if self.service.is_running(): self.pause_service() else: self.unpause_service() def shutdown(self): """ Shut down the entire application. """ logging.info("Shutting down") self.app.closeAllWindows() self.notifier.hide_icon() self.service.shutdown() self.monitor.stop() self.app.quit() os.remove(LOCK_FILE) logging.debug("All shutdown tasks complete... quitting") def notify_error(self, message): """ Show an error notification popup. @param message: Message to show in the popup """ self.exec_in_main(self.notifier.notify_error, message) def update_notifier_visibility(self): self.notifier.update_visible_status() def show_configure(self): """ Show the configuration window, or deiconify (un-minimise) it if it's already open. """ logging.info("Displaying configuration window") try: self.configWindow.showNormal() self.configWindow.activateWindow() except (AttributeError, RuntimeError): # AttributeError when the main window is shown the first time, RuntimeError subsequently. self.configWindow = ConfigWindow(self) self.configWindow.show() def show_configure_async(self): self.exec_in_main(self.show_configure) def show_error_dialog(self, message, details=None): """ Convenience method for showing an error dialog. """ if details is None: KMessageBox.error(None, message) else: KMessageBox.detailedError(None, message, details) def show_script_error(self): """ Show the last script error (if any) """ if self.service.scriptRunner.error != '': KMessageBox.information(None, self.service.scriptRunner.error, i18n("View Script Error Details")) self.service.scriptRunner.error = '' else: KMessageBox.information(None, i18n("No error information available"), i18n("View Script Error Details")) def show_popup_menu(self, folders=[], items=[], onDesktop=True, title=None): self.exec_in_main(self.__createMenu, folders, items, onDesktop, title) def hide_menu(self): self.exec_in_main(self.menu.hide) def __createMenu(self, folders, items, onDesktop, title): self.menu = PopupMenu(self.service, folders, items, onDesktop, title) self.menu.popup(QCursor.pos()) self.menu.setFocus() def exec_in_main(self, callback, *args): self.handler.postEventWithCallback(callback, *args)
class Magneto(MagnetoCore): """ Magneto Updates Notification Applet class. """ def __init__(self): app_name = "magneto" catalog = "" prog_name = ki18n("Magneto") version = "1.0" description = ki18n("System Update Status") lic = KAboutData.License_GPL cright = ki18n("(c) 2013 Fabio Erculiani") text = ki18n("none") home_page = "www.sabayon.org" bug_mail = "*****@*****.**" self._kabout = KAboutData(app_name, catalog, prog_name, version, description, lic, cright, text, home_page, bug_mail) argv = [sys.argv[0]] KCmdLineArgs.init(argv, self._kabout) self._app = KApplication() from dbus.mainloop.qt import DBusQtMainLoop super(Magneto, self).__init__(main_loop_class=DBusQtMainLoop) self._window = KStatusNotifierItem() # do not show "Quit" and use quitSelected() signal self._window.setStandardActionsEnabled(False) icon_name = self.icons.get("okay") self._window.setIconByName(icon_name) self._window.setStatus(KStatusNotifierItem.Passive) self._window.connect(self._window, SIGNAL("activateRequested(bool,QPoint)"), self.applet_activated) self._menu = KMenu(_("Magneto Entropy Updates Applet")) self._window.setContextMenu(self._menu) self._menu_items = {} for item in self._menu_item_list: if item is None: self._menu.addSeparator() continue myid, _unused, mytxt, myslot_func = item name = self.get_menu_image(myid) action_icon = KIcon(name) w = KAction(action_icon, mytxt, self._menu) self._menu_items[myid] = w self._window.connect(w, SIGNAL("triggered()"), myslot_func) self._menu.addAction(w) self._menu.hide() def _first_check(self): def _do_check(): self.send_check_updates_signal(startup_check=True) return False if self._dbus_service_available: QTimer.singleShot(10000, _do_check) def startup(self): """ Start user interface. """ self._dbus_service_available = self.setup_dbus() if config.settings["APPLET_ENABLED"] and \ self._dbus_service_available: self.enable_applet(do_check=False) else: self.disable_applet() if not self._dbus_service_available: QTimer.singleShot(30000, self.show_service_not_available) else: self._first_check() # Notice Window instance self._notice_window = AppletNoticeWindow(self) # Enter main loop self._app.exec_() def close_service(self): super(Magneto, self).close_service() self._app.quit() def change_icon(self, icon_name): name = self.icons.get(icon_name) self._window.setIconByName(name) def disable_applet(self, *args): super(Magneto, self).disable_applet() self._menu_items["disable_applet"].setEnabled(False) self._menu_items["enable_applet"].setEnabled(True) def enable_applet(self, w=None, do_check=True): done = super(Magneto, self).enable_applet(do_check=do_check) if done: self._menu_items["disable_applet"].setEnabled(True) self._menu_items["enable_applet"].setEnabled(False) def show_alert(self, title, text, urgency=None, force=False, buttons=None): if ((title, text) == self.last_alert) and not force: return def _action_activate_cb(action_num): if not buttons: return try: action_info = buttons[action_num - 1] except IndexError: return _action_id, _button_name, button_callback = action_info button_callback() def do_show(): notification = KNotification("Updates") # Keep a reference or the callback of the actions added # below will never work. # See: https://bugzilla.redhat.com/show_bug.cgi?id=241531 self.__last_notification = notification notification.setFlags(KNotification.CloseOnTimeout) notification.setText("<b>%s</b><br/>%s" % ( title, text, )) if buttons: notification.setActions([x[1] for x in buttons]) notification.connect(notification, SIGNAL("activated(unsigned int)"), _action_activate_cb) icon_name = "okay" status = KStatusNotifierItem.Passive if urgency == "critical": icon_name = "critical" status = KStatusNotifierItem.Active name = self.icons.get(icon_name) icon = KIcon(name) self._window.setStatus(status) notification.setPixmap(icon.pixmap(48, 48)) notification.sendEvent() self.last_alert = (title, text) # thread safety QTimer.singleShot(0, do_show) def update_tooltip(self, tip): def do_update(): self._window.setToolTipTitle(tip) QTimer.singleShot(0, do_update) def applet_context_menu(self): """ No action for now. """ pass def applet_activated(self, active, pos): if active: self.applet_doubleclick() def hide_notice_window(self): self.notice_window_shown = False self._notice_window.hide() def show_notice_window(self): if self.notice_window_shown: return if not self.package_updates: return entropy_ver = None packages = [] for atom in self.package_updates: key = entropy.dep.dep_getkey(atom) avail_rev = entropy.dep.dep_get_entropy_revision(atom) avail_tag = entropy.dep.dep_gettag(atom) my_pkg = entropy.dep.remove_entropy_revision(atom) my_pkg = entropy.dep.remove_tag(my_pkg) pkgcat, pkgname, pkgver, pkgrev = entropy.dep.catpkgsplit(my_pkg) ver = pkgver if pkgrev != "r0": ver += "-%s" % (pkgrev, ) if avail_tag: ver += "#%s" % (avail_tag, ) if avail_rev: ver += "~%s" % (avail_tag, ) if key == "sys-apps/entropy": entropy_ver = ver packages.append("%s (%s)" % ( key, ver, )) critical_msg = "" if entropy_ver is not None: critical_msg = "%s <b>sys-apps/entropy</b> " "%s, %s <b>%s</b>. %s." % ( _("Your system currently has an outdated version of"), _("installed"), _("the latest available version is"), entropy_ver, _("It is recommended that you upgrade to " "the latest before updating any other packages")) self._notice_window.populate(packages, critical_msg) self._notice_window.show() self.notice_window_shown = True