diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/leap/app.py | 27 | ||||
| -rw-r--r-- | src/leap/gui/mainwindow.py | 76 | ||||
| -rw-r--r-- | src/leap/gui/twisted_main.py | 60 | ||||
| -rw-r--r-- | src/leap/platform_init/initializers.py | 3 | ||||
| -rw-r--r-- | src/leap/services/tx.py | 46 | 
5 files changed, 173 insertions, 39 deletions
| diff --git a/src/leap/app.py b/src/leap/app.py index bb8add0d..797cea8a 100644 --- a/src/leap/app.py +++ b/src/leap/app.py @@ -17,7 +17,6 @@  import logging  import signal -import socket  import sys  from functools import partial @@ -28,14 +27,19 @@ from leap.common.events import server as event_server  from leap.util import __version__ as VERSION  from leap.util import leap_argparse  from leap.gui import locale_rc +from leap.gui import twisted_main  from leap.gui.mainwindow import MainWindow  from leap.platform_init import IS_MAC  from leap.platform_init.locks import we_are_the_one_and_only +from leap.services.tx import leap_services  import codecs  codecs.register(lambda name: codecs.lookup('utf-8')                  if name == 'cp65001' else None) +# pylint: avoid unused import +assert(locale_rc) +  def sigint_handler(*args, **kwargs):      """ @@ -48,9 +52,15 @@ def sigint_handler(*args, **kwargs):      mainwindow.quit() +def install_qtreactor(logger): +    import qt4reactor +    qt4reactor.install() +    logger.debug("Qt4 reactor installed") + +  def main():      """ -    Launches the main event loop +    Starts the main event loop and launches the main window.      """      event_server.ensure_server(event_server.SERVER_PORT) @@ -96,6 +106,9 @@ def main():      logger.info('Starting app')      app = QtGui.QApplication(sys.argv) +    # install the qt4reactor. +    install_qtreactor(logger) +      # To test:      # $ LANG=es ./app.py      locale = QtCore.QLocale.system().name() @@ -119,7 +132,10 @@ def main():      timer.start(500)      timer.timeout.connect(lambda: None) -    window = MainWindow(standalone, bypass_checks) +    window = MainWindow( +        lambda: twisted_main.quit(app), +        standalone=standalone, +        bypass_checks=bypass_checks)      window.show()      sigint_window = partial(sigint_handler, window, logger=logger) @@ -128,8 +144,11 @@ def main():      if IS_MAC:          window.raise_() +    tx_app = leap_services() +    assert(tx_app) +      # Run main loop -    sys.exit(app.exec_()) +    twisted_main.start(app)  if __name__ == "__main__":      main() diff --git a/src/leap/gui/mainwindow.py b/src/leap/gui/mainwindow.py index b3ab56d3..fdf84766 100644 --- a/src/leap/gui/mainwindow.py +++ b/src/leap/gui/mainwindow.py @@ -71,15 +71,22 @@ class MainWindow(QtGui.QMainWindow):      new_updates = QtCore.Signal(object)      raise_window = QtCore.Signal([]) -    def __init__(self, standalone=False, bypass_checks=False): +    def __init__(self, quit_callback, +                 standalone=False, bypass_checks=False):          """          Constructor for the client main window +        :param quit_callback: Function to be called when closing +                              the application. +        :type quit_callback: callable +          :param standalone: Set to true if the app should use configs -        inside its pwd +                           inside its pwd          :type standalone: bool +          :param bypass_checks: Set to true if the app should bypass -        first round of checks for CA certificates at bootstrap +                              first round of checks for CA +                              certificates at bootstrap          :type bypass_checks: bool          """          QtGui.QMainWindow.__init__(self) @@ -89,6 +96,7 @@ class MainWindow(QtGui.QMainWindow):                   callback=self._new_updates_available)          register(signal=proto.RAISE_WINDOW,                   callback=self._on_raise_window_event) +        self._quit_callback = quit_callback          self._updates_content = "" @@ -173,27 +181,6 @@ class MainWindow(QtGui.QMainWindow):          self._vpn.process_finished.connect(              self._eip_finished) -        QtCore.QCoreApplication.instance().connect( -            QtCore.QCoreApplication.instance(), -            QtCore.SIGNAL("aboutToQuit()"), -            self._vpn.set_should_quit) -        QtCore.QCoreApplication.instance().connect( -            QtCore.QCoreApplication.instance(), -            QtCore.SIGNAL("aboutToQuit()"), -            self._vpn.wait) -        QtCore.QCoreApplication.instance().connect( -            QtCore.QCoreApplication.instance(), -            QtCore.SIGNAL("aboutToQuit()"), -            self._checker_thread.set_should_quit) -        QtCore.QCoreApplication.instance().connect( -            QtCore.QCoreApplication.instance(), -            QtCore.SIGNAL("aboutToQuit()"), -            self._checker_thread.wait) -        QtCore.QCoreApplication.instance().connect( -            QtCore.QCoreApplication.instance(), -            QtCore.SIGNAL("aboutToQuit()"), -            self._cleanup_pidfiles) -          self.ui.chkRemember.stateChanged.connect(              self._remember_state_changed)          self.ui.chkRemember.setEnabled(keyring.get_keyring() is not None) @@ -447,12 +434,6 @@ class MainWindow(QtGui.QMainWindow):                      "<a href=\"https://leap.se\">More about LEAP"                      "</a>") % (VERSION,)) -    def quit(self): -        self._really_quit = True -        if self._wizard: -            self._wizard.close() -        self.close() -      def changeEvent(self, e):          """          Reimplements the changeEvent method to minimize to tray @@ -976,17 +957,42 @@ class MainWindow(QtGui.QMainWindow):      def _cleanup_pidfiles(self):          """ -        SLOT -        TRIGGERS: -            self.aboutToQuit +        Removes lockfiles on a clean shutdown. -        Triggered on about to quit signal, removes lockfiles on a clean -        shutdown +        Triggered after aboutToQuit signal.          """          if IS_WIN:              lockfile = WindowsLock()              lockfile.release_lock() +    def _cleanup_and_quit(self): +        """ +        Call all the cleanup actions in a serialized way. +        Should be called from the quit function. +        """ +        logger.debug('About to quit, doing cleanup...') +        self._vpn.set_should_quit() +        self._vpn.wait() +        self._checker_thread.set_should_quit() +        self._checker_thread.wait() +        self._cleanup_pidfiles() + +    def quit(self): +        """ +        Cleanup and tidely close the main window before quitting. +        """ +        self._cleanup_and_quit() + +        self._really_quit = True +        if self._wizard: +            self._wizard.close() +        self.close() + +        if self._quit_callback: +            self._quit_callback() +        logger.debug('Bye.') + +  if __name__ == "__main__":      import signal diff --git a/src/leap/gui/twisted_main.py b/src/leap/gui/twisted_main.py new file mode 100644 index 00000000..c7add3ee --- /dev/null +++ b/src/leap/gui/twisted_main.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# twisted_main.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. +""" +Main functions for integration of twisted reactor +""" +import logging + +from twisted.internet import error + +# Resist the temptation of putting the import reactor here, +# it will raise an "reactor already imported" error. + +logger = logging.getLogger(__name__) + + +def start(app): +    """ +    Start the mainloop. + +    :param app: the main qt QApplication instance. +    :type app: QtCore.QApplication +    """ +    from twisted.internet import reactor +    logger.debug('starting twisted reactor') + +    # this seems to be troublesome under some +    # unidentified settings. +    #reactor.run() + +    reactor.runReturn() +    app.exec_() + + +def quit(app): +    """ +    Stop the mainloop. + +    :param app: the main qt QApplication instance. +    :type app: QtCore.QApplication +    """ +    from twisted.internet import reactor +    logger.debug('stopping twisted reactor') +    try: +        reactor.stop() +    except error.ReactorNotRunning: +        logger.debug('reactor not running') diff --git a/src/leap/platform_init/initializers.py b/src/leap/platform_init/initializers.py index 91c7086b..2e8cbe95 100644 --- a/src/leap/platform_init/initializers.py +++ b/src/leap/platform_init/initializers.py @@ -28,6 +28,9 @@ from PySide import QtGui  logger = logging.getLogger(__name__) +# NOTE we could use a deferToThread here, but should +# be aware of this bug: http://www.themacaque.com/?p=1067 +  def init_platform():      """ diff --git a/src/leap/services/tx.py b/src/leap/services/tx.py new file mode 100644 index 00000000..ef08fcc6 --- /dev/null +++ b/src/leap/services/tx.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# twisted.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. +""" +Twisted services launched by the client +""" +import logging + +from twisted.application.service import Application +from twisted.internet.task import LoopingCall + +logger = logging.getLogger(__name__) + + +def task(): +    """ +    stub periodic task, mainly for tests. +    DELETE-ME when there's real meat here :) +    """ +    from datetime import datetime +    logger.debug("hi there %s", datetime.now()) + + +def leap_services(): +    """ +    Check which twisted services are enabled and +    register them. +    """ +    logger.debug('starting leap services') +    application = Application("LEAP Client Local Services") +    #lc = LoopingCall(task) +    #lc.start(5) +    return application | 
