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)
def windowCreated(self, window, target): win.addWindow(window, target) Api.instance = KooApi() log = logging.getLogger('koo.view') log.debug('Starting main window') win.show() from Koo.Common import Debug Debug.installExceptionHook() if Settings.value('koo.pos_mode'): import Koo.Pos app.installEventFilter(Koo.Pos.PosEventFilter(win)) if Settings.value('koo.enter_as_tab'): from Koo.Common import EnterEventFilter app.installEventFilter(EnterEventFilter.EnterEventFilter(win)) from Koo.Common import ArrowsEventFilter app.installEventFilter(ArrowsEventFilter.ArrowsEventFilter(win)) from Koo.Common import WhatsThisEventFilter app.installEventFilter(WhatsThisEventFilter.WhatsThisEventFilter(win)) if Settings.value('tip.autostart'): from Koo.Dialogs.TipOfTheDayDialog import * dialog = TipOfTheDayDialog() dialog.exec_()
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)
WindowService.createWindow(view_ids, model, res_id, domain, view_type, window, context, mode, name, autoReload, target) def windowCreated(self, window, target): mainWindow.setCentralWidget(window) window.setParent(mainWindow) window.show() Api.instance = KooApi() mainWindow.showFullScreen() if Settings.value('koo.pos_mode'): import Koo.Pos app.installEventFilter(Koo.Pos.PosEventFilter(mainWindow)) if Settings.value('koo.enter_as_tab'): from Koo.Common import EnterEventFilter app.installEventFilter(EnterEventFilter.EnterEventFilter(mainWindow)) from Koo.Common import ArrowsEventFilter app.installEventFilter(ArrowsEventFilter.ArrowsEventFilter(mainWindow)) from Koo.Common import WhatsThisEventFilter app.installEventFilter(WhatsThisEventFilter.WhatsThisEventFilter(mainWindow)) # Load default wizard if not Settings.value('login.url'): sys.exit("Error: No connection parameters given.") if not Settings.value('login.db'):