Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
    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_()
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
        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'):