summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/gui
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2015-08-31 14:54:52 -0400
committerKali Kaneko <kali@leap.se>2015-08-31 14:54:52 -0400
commitf4547479fc050f338845f4f546d8dd7c0e4512eb (patch)
tree0f737c7f102674230f5467ecaf17720e1d28f6eb /src/leap/bitmask/gui
parentdd43dad4b150adb66e571a56a8a5c053dec858d0 (diff)
parentfd27f48a35736d8ba186c423a7de15ffee5143dd (diff)
Merge tag '0.9.0rc2' into debian/experimental
Tag leap.bitmask version 0.9.0rc2
Diffstat (limited to 'src/leap/bitmask/gui')
-rw-r--r--src/leap/bitmask/gui/advanced_key_management.py7
-rw-r--r--src/leap/bitmask/gui/app.py6
-rw-r--r--src/leap/bitmask/gui/eip_preferenceswindow.py5
-rw-r--r--src/leap/bitmask/gui/eip_status.py5
-rw-r--r--src/leap/bitmask/gui/login.py12
-rw-r--r--src/leap/bitmask/gui/logwindow.py (renamed from src/leap/bitmask/gui/loggerwindow.py)68
-rw-r--r--src/leap/bitmask/gui/mail_status.py223
-rw-r--r--src/leap/bitmask/gui/mainwindow.py400
-rw-r--r--src/leap/bitmask/gui/passwordwindow.py8
-rw-r--r--src/leap/bitmask/gui/preferences_account_page.py13
-rw-r--r--src/leap/bitmask/gui/preferences_email_page.py6
-rw-r--r--src/leap/bitmask/gui/preferenceswindow.py14
-rw-r--r--src/leap/bitmask/gui/signaltracker.py6
-rw-r--r--src/leap/bitmask/gui/statemachines.py5
-rw-r--r--src/leap/bitmask/gui/ui/wizard.ui56
-rw-r--r--src/leap/bitmask/gui/wizard.py76
16 files changed, 508 insertions, 402 deletions
diff --git a/src/leap/bitmask/gui/advanced_key_management.py b/src/leap/bitmask/gui/advanced_key_management.py
index 7d147b7b..2e315d18 100644
--- a/src/leap/bitmask/gui/advanced_key_management.py
+++ b/src/leap/bitmask/gui/advanced_key_management.py
@@ -17,14 +17,13 @@
"""
Advanced Key Management
"""
-import logging
-
-from PySide import QtCore, QtGui
+from PySide import QtGui
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.services import get_service_display_name, MX_SERVICE
from ui_advanced_key_management import Ui_AdvancedKeyManagement
-logger = logging.getLogger(__name__)
+logger = get_logger()
class AdvancedKeyManagement(QtGui.QDialog):
diff --git a/src/leap/bitmask/gui/app.py b/src/leap/bitmask/gui/app.py
index 5fe031b1..02357b2b 100644
--- a/src/leap/bitmask/gui/app.py
+++ b/src/leap/bitmask/gui/app.py
@@ -18,16 +18,14 @@ A single App instances holds the signals that are shared among different
frontend UI components. The App also keeps a reference to the backend object
and the signaler get signals from the backend.
"""
-import logging
-
-from functools import partial
from PySide import QtCore, QtGui
from leap.bitmask.config.leapsettings import LeapSettings
from leap.bitmask.backend.backend_proxy import BackendProxy
from leap.bitmask.backend.leapsignaler import LeapSignaler
+from leap.bitmask.logs.utils import get_logger
-logger = logging.getLogger(__name__)
+logger = get_logger()
class App(QtGui.QWidget):
diff --git a/src/leap/bitmask/gui/eip_preferenceswindow.py b/src/leap/bitmask/gui/eip_preferenceswindow.py
index 8939c709..756e8adf 100644
--- a/src/leap/bitmask/gui/eip_preferenceswindow.py
+++ b/src/leap/bitmask/gui/eip_preferenceswindow.py
@@ -18,15 +18,14 @@
"""
EIP Preferences window
"""
-import logging
-
from functools import partial
from PySide import QtCore, QtGui
from leap.bitmask.config.leapsettings import LeapSettings
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.gui.ui_eippreferences import Ui_EIPPreferences
-logger = logging.getLogger(__name__)
+logger = get_logger()
class EIPPreferencesWindow(QtGui.QDialog):
diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py
index 83490cac..8334c2ee 100644
--- a/src/leap/bitmask/gui/eip_status.py
+++ b/src/leap/bitmask/gui/eip_status.py
@@ -17,13 +17,12 @@
"""
EIP Status Panel widget implementation
"""
-import logging
-
from datetime import datetime
from functools import partial
from PySide import QtCore, QtGui
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.services import get_service_display_name, EIP_SERVICE
from leap.bitmask.platform_init import IS_LINUX
from leap.bitmask.util.averages import RateMovingAverage
@@ -32,7 +31,7 @@ from leap.common.check import leap_assert_type
from ui_eip_status import Ui_EIPStatus
QtDelayedCall = QtCore.QTimer.singleShot
-logger = logging.getLogger(__name__)
+logger = get_logger()
class EIPStatusWidget(QtGui.QWidget):
diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py
index 90df0b73..756dd63c 100644
--- a/src/leap/bitmask/gui/login.py
+++ b/src/leap/bitmask/gui/login.py
@@ -30,8 +30,7 @@ The login sequence is the following:
- on success: _authentication_finished
"""
-import logging
-
+from keyring.errors import InitError as KeyringInitError
from PySide import QtCore, QtGui
from ui_login import Ui_LoginWidget
@@ -40,6 +39,7 @@ from ui_login import Ui_LoginWidget
from leap.bitmask.backend.leapbackend import ERROR_KEY, PASSED_KEY
from leap.bitmask.config import flags
from leap.bitmask.config.leapsettings import LeapSettings
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.gui.signaltracker import SignalTracker
from leap.bitmask.util import make_address
from leap.bitmask.util.credentials import USERNAME_REGEX
@@ -47,7 +47,7 @@ from leap.bitmask.util.keyring_helpers import has_keyring
from leap.bitmask.util.keyring_helpers import get_keyring
from leap.common.check import leap_assert_type
-logger = logging.getLogger(__name__)
+logger = get_logger()
class LoginState(object):
@@ -365,6 +365,9 @@ class LoginWidget(QtGui.QWidget, SignalTracker):
# Only save the username if it was saved correctly in
# the keyring
self._settings.set_user(full_user_id)
+ except KeyringInitError as e:
+ logger.error("Failed to unlock keyring, maybe the user "
+ "cancelled the operation {0!r}".format(e))
except Exception as e:
logger.exception("Problem saving data to keyring. %r" % (e,))
@@ -653,6 +656,9 @@ class LoginWidget(QtGui.QWidget, SignalTracker):
saved_password = keyring.get_password(self.KEYRING_KEY, u_user)
except ValueError as e:
logger.debug("Incorrect Password. %r." % (e,))
+ except KeyringInitError as e:
+ logger.error("Failed to unlock keyring, maybe the user "
+ "cancelled the operation {0!r}".format(e))
if saved_password is not None:
self.set_password(saved_password)
diff --git a/src/leap/bitmask/gui/loggerwindow.py b/src/leap/bitmask/gui/logwindow.py
index 463d2412..718269c9 100644
--- a/src/leap/bitmask/gui/loggerwindow.py
+++ b/src/leap/bitmask/gui/logwindow.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# loggerwindow.py
+# logwindow.py
# Copyright (C) 2013 LEAP
#
# This program is free software: you can redistribute it and/or modify
@@ -19,18 +19,18 @@
History log window
"""
import cgi
-import logging
from PySide import QtCore, QtGui
+import logbook
+
from ui_loggerwindow import Ui_LoggerWindow
+from leap.bitmask.logs.utils import get_logger, LOG_CONTROLLER
from leap.bitmask.util.constants import PASTEBIN_API_DEV_KEY
-from leap.bitmask.logs.leap_log_handler import LeapLogHandler
from leap.bitmask.util import pastebin
-from leap.common.check import leap_assert, leap_assert_type
-logger = logging.getLogger(__name__)
+logger = get_logger()
class LoggerWindow(QtGui.QDialog):
@@ -40,16 +40,11 @@ class LoggerWindow(QtGui.QDialog):
_paste_ok = QtCore.Signal(object)
_paste_error = QtCore.Signal(object)
- def __init__(self, parent, handler):
+ def __init__(self, parent):
"""
- Initialize the widget with the custom handler.
-
- :param handler: Custom handler that supports history and signal.
- :type handler: LeapLogHandler.
+ Initialize the widget.
"""
QtGui.QDialog.__init__(self, parent)
- leap_assert(handler, "We need a handler for the logger window")
- leap_assert_type(handler, LeapLogHandler)
# Load UI
self.ui = Ui_LoggerWindow()
@@ -72,36 +67,27 @@ class LoggerWindow(QtGui.QDialog):
self._current_filter = ""
self._current_history = ""
- # Load logging history and connect logger with the widget
- self._logging_handler = handler
- self._connect_to_handler()
- self._load_history()
+ self._set_logs_to_display()
- def _connect_to_handler(self):
- """
- This method connects the loggerwindow with the handler through a
- signal communicate the logger events.
- """
- self._logging_handler.new_log.connect(self._add_log_line)
+ LOG_CONTROLLER.new_log.connect(self._add_log_line)
+ self._load_history()
def _add_log_line(self, log):
"""
Adds a line to the history, only if it's in the desired levels to show.
:param log: a log record to be inserted in the widget
- :type log: a dict with RECORD_KEY and MESSAGE_KEY.
- the record contains the LogRecord of the logging module,
- the message contains the formatted message for the log.
+ :type log: Logbook.LogRecord.
"""
html_style = {
- logging.DEBUG: "background: #CDFFFF;",
- logging.INFO: "background: white;",
- logging.WARNING: "background: #FFFF66;",
- logging.ERROR: "background: red; color: white;",
- logging.CRITICAL: "background: red; color: white; font: bold;"
+ logbook.DEBUG: "background: #CDFFFF;",
+ logbook.INFO: "background: white;",
+ logbook.WARNING: "background: #FFFF66;",
+ logbook.ERROR: "background: red; color: white;",
+ logbook.CRITICAL: "background: red; color: white; font: bold;"
}
- level = log[LeapLogHandler.RECORD_KEY].levelno
- message = cgi.escape(log[LeapLogHandler.MESSAGE_KEY])
+ level = log.level
+ message = cgi.escape(log.msg)
if self._logs_to_display[level]:
open_tag = "<tr style='" + html_style[level] + "'>"
@@ -125,12 +111,10 @@ class LoggerWindow(QtGui.QDialog):
"""
self._set_logs_to_display()
self.ui.txtLogHistory.clear()
- history = self._logging_handler.log_history
current_history = []
- for line in history:
- self._add_log_line(line)
- message = line[LeapLogHandler.MESSAGE_KEY]
- current_history.append(message)
+ for record in LOG_CONTROLLER.get_logs():
+ self._add_log_line(record)
+ current_history.append(record.msg)
self._current_history = "\n".join(current_history)
@@ -139,11 +123,11 @@ class LoggerWindow(QtGui.QDialog):
Sets the logs_to_display dict getting the toggled options from the ui
"""
self._logs_to_display = {
- logging.DEBUG: self.ui.btnDebug.isChecked(),
- logging.INFO: self.ui.btnInfo.isChecked(),
- logging.WARNING: self.ui.btnWarning.isChecked(),
- logging.ERROR: self.ui.btnError.isChecked(),
- logging.CRITICAL: self.ui.btnCritical.isChecked()
+ logbook.DEBUG: self.ui.btnDebug.isChecked(),
+ logbook.INFO: self.ui.btnInfo.isChecked(),
+ logbook.WARNING: self.ui.btnWarning.isChecked(),
+ logbook.ERROR: self.ui.btnError.isChecked(),
+ logbook.CRITICAL: self.ui.btnCritical.isChecked()
}
def _filter_by(self, text):
diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index bbfbafb5..1a38c8cf 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -17,28 +17,27 @@
"""
Mail Status Panel widget implementation
"""
-import logging
-
from PySide import QtCore, QtGui
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.platform_init import IS_LINUX
from leap.bitmask.services import get_service_display_name, MX_SERVICE
from leap.common.check import leap_assert, leap_assert_type
from leap.common.events import register
-from leap.common.events import events_pb2 as proto
+from leap.common.events import catalog
from ui_mail_status import Ui_MailStatusWidget
-logger = logging.getLogger(__name__)
+logger = get_logger()
class MailStatusWidget(QtGui.QWidget):
"""
Status widget that displays the state of the LEAP Mail service
"""
- _soledad_event = QtCore.Signal(object)
+ _soledad_event = QtCore.Signal(object, object)
_smtp_event = QtCore.Signal(object)
- _imap_event = QtCore.Signal(object)
+ _imap_event = QtCore.Signal(object, object)
_keymanager_event = QtCore.Signal(object)
def __init__(self, parent=None):
@@ -70,51 +69,36 @@ class MailStatusWidget(QtGui.QWidget):
self.ERROR_ICON_TRAY = None
self._set_mail_icons()
- register(signal=proto.KEYMANAGER_LOOKING_FOR_KEY,
- callback=self._mail_handle_keymanager_events,
- reqcbk=lambda req, resp: None)
-
- register(signal=proto.KEYMANAGER_KEY_FOUND,
- callback=self._mail_handle_keymanager_events,
- reqcbk=lambda req, resp: None)
-
- # register(signal=proto.KEYMANAGER_KEY_NOT_FOUND,
- # callback=self._mail_handle_keymanager_events,
- # reqcbk=lambda req, resp: None)
-
- register(signal=proto.KEYMANAGER_STARTED_KEY_GENERATION,
- callback=self._mail_handle_keymanager_events,
- reqcbk=lambda req, resp: None)
-
- register(signal=proto.KEYMANAGER_FINISHED_KEY_GENERATION,
- callback=self._mail_handle_keymanager_events,
- reqcbk=lambda req, resp: None)
-
- register(signal=proto.KEYMANAGER_DONE_UPLOADING_KEYS,
- callback=self._mail_handle_keymanager_events,
- reqcbk=lambda req, resp: None)
-
- register(signal=proto.SOLEDAD_DONE_DOWNLOADING_KEYS,
- callback=self._mail_handle_soledad_events,
- reqcbk=lambda req, resp: None)
-
- register(signal=proto.SOLEDAD_DONE_UPLOADING_KEYS,
- callback=self._mail_handle_soledad_events,
- reqcbk=lambda req, resp: None)
-
- register(signal=proto.IMAP_UNREAD_MAIL,
- callback=self._mail_handle_imap_events,
- reqcbk=lambda req, resp: None)
- register(signal=proto.IMAP_SERVICE_STARTED,
- callback=self._mail_handle_imap_events,
- reqcbk=lambda req, resp: None)
- register(signal=proto.SMTP_SERVICE_STARTED,
- callback=self._mail_handle_imap_events,
- reqcbk=lambda req, resp: None)
-
- register(signal=proto.SOLEDAD_INVALID_AUTH_TOKEN,
- callback=self.set_soledad_invalid_auth_token,
- reqcbk=lambda req, resp: None)
+ register(event=catalog.KEYMANAGER_LOOKING_FOR_KEY,
+ callback=self._mail_handle_keymanager_events)
+ register(event=catalog.KEYMANAGER_KEY_FOUND,
+ callback=self._mail_handle_keymanager_events)
+ register(event=catalog.KEYMANAGER_KEY_NOT_FOUND,
+ callback=self._mail_handle_keymanager_events)
+ register(event=catalog.KEYMANAGER_STARTED_KEY_GENERATION,
+ callback=self._mail_handle_keymanager_events)
+ register(event=catalog.KEYMANAGER_FINISHED_KEY_GENERATION,
+ callback=self._mail_handle_keymanager_events)
+ register(event=catalog.KEYMANAGER_DONE_UPLOADING_KEYS,
+ callback=self._mail_handle_keymanager_events)
+
+ register(event=catalog.SOLEDAD_DONE_DOWNLOADING_KEYS,
+ callback=self._mail_handle_soledad_events)
+ register(event=catalog.SOLEDAD_DONE_UPLOADING_KEYS,
+ callback=self._mail_handle_soledad_events)
+ register(event=catalog.SOLEDAD_SYNC_RECEIVE_STATUS,
+ callback=self._mail_handle_soledad_events)
+ register(event=catalog.SOLEDAD_SYNC_SEND_STATUS,
+ callback=self._mail_handle_soledad_events)
+ register(event=catalog.SOLEDAD_INVALID_AUTH_TOKEN,
+ callback=self.set_soledad_invalid_auth_token)
+
+ register(event=catalog.MAIL_UNREAD_MESSAGES,
+ callback=self._mail_handle_imap_events)
+ register(event=catalog.IMAP_SERVICE_STARTED,
+ callback=self._mail_handle_imap_events)
+ register(event=catalog.SMTP_SERVICE_STARTED,
+ callback=self._mail_handle_imap_events)
self._soledad_event.connect(
self._mail_handle_soledad_events_slot)
@@ -194,12 +178,14 @@ class MailStatusWidget(QtGui.QWidget):
msg = self.tr("There was an unexpected problem with Soledad.")
self._set_mail_status(msg, ready=-1)
- def set_soledad_invalid_auth_token(self):
+ def set_soledad_invalid_auth_token(self, event, content):
"""
- TRIGGERS:
- SoledadBootstrapper.soledad_invalid_token
-
This method is called when the auth token is invalid
+
+ :param event: The event that triggered the callback.
+ :type event: str
+ :param content: The content of the event.
+ :type content: list
"""
msg = self.tr("Invalid auth token, try logging in again.")
self._set_mail_status(msg, ready=-1)
@@ -239,58 +225,85 @@ class MailStatusWidget(QtGui.QWidget):
self._action_mail_status.setText(tray_status)
self._update_systray_tooltip()
- def _mail_handle_soledad_events(self, req):
+ def _mail_handle_soledad_events(self, event, content):
"""
Callback for handling events that are emitted from Soledad
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param event: The event that triggered the callback.
+ :type event: str
+ :param content: The content of the event.
+ :type content: dict
"""
- self._soledad_event.emit(req)
+ self._soledad_event.emit(event, content)
- def _mail_handle_soledad_events_slot(self, req):
+ def _mail_handle_soledad_events_slot(self, event, content):
"""
TRIGGERS:
_mail_handle_soledad_events
Reacts to an Soledad event
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param event: The event that triggered the callback.
+ :type event: str
+ :param content: The content of the event.
+ :type content: dict
"""
self._set_mail_status(self.tr("Starting..."), ready=1)
ext_status = ""
+ ready = None
- if req.event == proto.SOLEDAD_DONE_UPLOADING_KEYS:
+ if event == catalog.SOLEDAD_DONE_UPLOADING_KEYS:
ext_status = self.tr("Soledad has started...")
- elif req.event == proto.SOLEDAD_DONE_DOWNLOADING_KEYS:
+ ready = 1
+ elif event == catalog.SOLEDAD_DONE_DOWNLOADING_KEYS:
ext_status = self.tr("Soledad is starting, please wait...")
+ ready = 1
+ elif event == catalog.SOLEDAD_SYNC_RECEIVE_STATUS:
+ sync_progress = content['received'] * 100 / content['total']
+ if sync_progress < 100:
+ ext_status = self.tr("Sync: downloading ({0:02}%)")
+ ext_status = ext_status.format(sync_progress)
+ else:
+ ext_status = self.tr("Sync: download completed.")
+
+ ready = 2
+ elif event == catalog.SOLEDAD_SYNC_SEND_STATUS:
+ sync_progress = content['sent'] * 100 / content['total']
+ if sync_progress < 100:
+ ext_status = self.tr("Sync: uploading ({0:02}%)")
+ ext_status = ext_status.format(sync_progress)
+ else:
+ ext_status = self.tr("Sync: upload complete.")
+
+ ready = 2
else:
leap_assert(False,
"Don't know how to handle this state: %s"
- % (req.event))
+ % (event))
- self._set_mail_status(ext_status, ready=1)
+ self._set_mail_status(ext_status, ready=ready)
- def _mail_handle_keymanager_events(self, req):
+ def _mail_handle_keymanager_events(self, event, content):
"""
Callback for the KeyManager events
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param event: The event that triggered the callback.
+ :type event: str
+ :param content: The content of the event.
+ :type content: list
"""
- self._keymanager_event.emit(req)
+ self._keymanager_event.emit(event)
- def _mail_handle_keymanager_events_slot(self, req):
+ def _mail_handle_keymanager_events_slot(self, event):
"""
TRIGGERS:
_mail_handle_keymanager_events
Reacts to an KeyManager event
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param event: The event that triggered the callback.
+ :type event: str
"""
# We want to ignore this kind of events once everything has
# started
@@ -299,88 +312,90 @@ class MailStatusWidget(QtGui.QWidget):
ext_status = ""
- if req.event == proto.KEYMANAGER_LOOKING_FOR_KEY:
+ if event == catalog.KEYMANAGER_LOOKING_FOR_KEY:
ext_status = self.tr("Initial sync in progress, please wait...")
- elif req.event == proto.KEYMANAGER_KEY_FOUND:
+ elif event == catalog.KEYMANAGER_KEY_FOUND:
ext_status = self.tr("Found key! Starting mail...")
- # elif req.event == proto.KEYMANAGER_KEY_NOT_FOUND:
- # ext_status = self.tr("Key not found!")
- elif req.event == proto.KEYMANAGER_STARTED_KEY_GENERATION:
+ elif event == catalog.KEYMANAGER_KEY_NOT_FOUND:
+ ext_status = self.tr(
+ "Key not found...")
+ elif event == catalog.KEYMANAGER_STARTED_KEY_GENERATION:
ext_status = self.tr(
"Generating new key, this may take a few minutes.")
- elif req.event == proto.KEYMANAGER_FINISHED_KEY_GENERATION:
+ elif event == catalog.KEYMANAGER_FINISHED_KEY_GENERATION:
ext_status = self.tr("Finished generating key!")
- elif req.event == proto.KEYMANAGER_DONE_UPLOADING_KEYS:
+ elif event == catalog.KEYMANAGER_DONE_UPLOADING_KEYS:
ext_status = self.tr("Starting mail...")
else:
- leap_assert(False,
- "Don't know how to handle this state: %s"
- % (req.event))
-
+ logger.warning("don't know to to handle %s" % (event,))
self._set_mail_status(ext_status, ready=1)
- def _mail_handle_smtp_events(self, req):
+ def _mail_handle_smtp_events(self, event):
"""
Callback for the SMTP events
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param event: The event that triggered the callback.
+ :type event: str
"""
- self._smtp_event.emit(req)
+ self._smtp_event.emit(event)
- def _mail_handle_smtp_events_slot(self, req):
+ def _mail_handle_smtp_events_slot(self, event):
"""
TRIGGERS:
_mail_handle_smtp_events
Reacts to an SMTP event
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param event: The event that triggered the callback.
+ :type event: str
"""
ext_status = ""
- if req.event == proto.SMTP_SERVICE_STARTED:
+ if event == catalog.SMTP_SERVICE_STARTED:
self._smtp_started = True
- elif req.event == proto.SMTP_SERVICE_FAILED_TO_START:
+ elif event == catalog.SMTP_SERVICE_FAILED_TO_START:
ext_status = self.tr("SMTP failed to start, check the logs.")
else:
leap_assert(False,
"Don't know how to handle this state: %s"
- % (req.event))
+ % (event))
self._set_mail_status(ext_status, ready=2)
# ----- XXX deprecate (move to mail conductor)
- def _mail_handle_imap_events(self, req):
+ def _mail_handle_imap_events(self, event, content):
"""
Callback for the IMAP events
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param event: The event that triggered the callback.
+ :type event: str
+ :param content: The content of the event.
+ :type content: list
"""
- self._imap_event.emit(req)
+ self._imap_event.emit(event, content)
- def _mail_handle_imap_events_slot(self, req):
+ def _mail_handle_imap_events_slot(self, event, content):
"""
TRIGGERS:
_mail_handle_imap_events
Reacts to an IMAP event
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param event: The event that triggered the callback.
+ :type event: str
+ :param content: The content of the event.
+ :type content: list
"""
ext_status = None
- if req.event == proto.IMAP_UNREAD_MAIL:
+ if event == catalog.MAIL_UNREAD_MESSAGES:
# By now, the semantics of the UNREAD_MAIL event are
# limited to mails with the Unread flag *in the Inbox".
# We could make this configurable to include all unread mail
# or all unread mail in subscribed folders.
if self._started:
- count = req.content
+ count = content
if count != "0":
status = self.tr("{0} Unread Emails "
"in your Inbox").format(count)
@@ -390,7 +405,7 @@ class MailStatusWidget(QtGui.QWidget):
self._set_mail_status(status, ready=2)
else:
self._set_mail_status("", ready=2)
- elif req.event == proto.IMAP_SERVICE_STARTED:
+ elif event == catalog.IMAP_SERVICE_STARTED:
self._imap_started = True
if ext_status is not None:
self._set_mail_status(ext_status, ready=1)
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index cbf7a636..312048ba 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -17,7 +17,6 @@
"""
Main window for Bitmask.
"""
-import logging
import time
from datetime import datetime
@@ -34,12 +33,11 @@ from leap.bitmask import __version_hash__ as VERSION_HASH
from leap.bitmask.backend.leapbackend import ERROR_KEY, PASSED_KEY
from leap.bitmask.config import flags
+from leap.bitmask.logs.utils import get_logger, LOG_CONTROLLER
from leap.bitmask.gui.advanced_key_management import AdvancedKeyManagement
-from leap.bitmask.gui.eip_status import EIPStatusWidget
-from leap.bitmask.gui.loggerwindow import LoggerWindow
+from leap.bitmask.gui.logwindow import LoggerWindow
from leap.bitmask.gui.login import LoginWidget
-from leap.bitmask.gui.mail_status import MailStatusWidget
from leap.bitmask.gui.preferenceswindow import PreferencesWindow
from leap.bitmask.gui.signaltracker import SignalTracker
from leap.bitmask.gui.systray import SysTray
@@ -53,24 +51,34 @@ from leap.bitmask.platform_init import locks
from leap.bitmask.platform_init.initializers import init_platform
from leap.bitmask.platform_init.initializers import init_signals
-from leap.bitmask.services.eip import conductor as eip_conductor
-from leap.bitmask.services.mail import conductor as mail_conductor
-
-from leap.bitmask.services import EIP_SERVICE, MX_SERVICE
-
from leap.bitmask.util import autostart, make_address
from leap.bitmask.util.keyring_helpers import has_keyring
-from leap.bitmask.logs.leap_log_handler import LeapLogHandler
from leap.common.events import register
-from leap.common.events import events_pb2 as proto
+from leap.common.events import catalog
from leap.mail.imap.service.imap import IMAP_PORT
from ui_mainwindow import Ui_MainWindow
+from leap.bitmask._components import HAS_EIP, HAS_MAIL
+
+if HAS_EIP:
+ from leap.bitmask.gui.eip_status import EIPStatusWidget
+ from leap.bitmask.services.eip import conductor as eip_conductor
+ from leap.bitmask.services import EIP_SERVICE
+
+if HAS_MAIL:
+ from leap.bitmask.gui.mail_status import MailStatusWidget
+ from leap.bitmask.services.mail import conductor as mail_conductor
+ from leap.bitmask.services import MX_SERVICE
+
QtDelayedCall = QtCore.QTimer.singleShot
-logger = logging.getLogger(__name__)
+
+logger = get_logger()
+
+if not HAS_EIP:
+ BITMASK_MAIL_ONLY_ICON = ":/images/menubar-mask-icon.png"
class MainWindow(QtGui.QMainWindow, SignalTracker):
@@ -78,17 +86,19 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
Main window for login and presenting status updates to the user
"""
# Signals
- eip_needs_login = QtCore.Signal([])
+
new_updates = QtCore.Signal(object)
raise_window = QtCore.Signal([])
soledad_ready = QtCore.Signal([])
all_services_stopped = QtCore.Signal()
- # We use this flag to detect abnormal terminations
- user_stopped_eip = False
+ if HAS_EIP:
+ eip_needs_login = QtCore.Signal([])
+ # We use this flag to detect abnormal terminations
+ user_stopped_eip = False
- # We give EIP some time to come up before starting soledad anyway
- EIP_START_TIMEOUT = 60000 # in milliseconds
+ # We give EIP some time to come up before starting soledad anyway
+ EIP_START_TIMEOUT = 60000 # in milliseconds
# We give the services some time to a halt before forcing quit.
SERVICES_STOP_TIMEOUT = 3000 # in milliseconds
@@ -107,12 +117,10 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
autostart.set_autostart(True)
# register leap events ########################################
- register(signal=proto.UPDATER_NEW_UPDATES,
- callback=self._new_updates_available,
- reqcbk=lambda req, resp: None) # make rpc call async
- register(signal=proto.RAISE_WINDOW,
- callback=self._on_raise_window_event,
- reqcbk=lambda req, resp: None) # make rpc call async
+ register(event=catalog.UPDATER_NEW_UPDATES,
+ callback=self._new_updates_available) # make rpc call async
+ register(event=catalog.RAISE_WINDOW,
+ callback=self._on_raise_window_event) # make rpc call async
# end register leap events ####################################
self._updates_content = ""
@@ -126,15 +134,17 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._backend = self.app.backend
self._leap_signaler = self.app.signaler
self._settings = self.app.settings
+ self._backend_settings = self._backend.settings
# Login Widget
self._login_widget = LoginWidget(self._backend,
self._leap_signaler, self)
self.ui.loginLayout.addWidget(self._login_widget)
- # Mail Widget
- self._mail_status = MailStatusWidget(self)
- self.ui.mailLayout.addWidget(self._mail_status)
+ if HAS_MAIL:
+ # Mail Widget
+ self._mail_status = MailStatusWidget(self)
+ self.ui.mailLayout.addWidget(self._mail_status)
# Provider List
self._providers = Providers(self.ui.cmbProviders)
@@ -151,41 +161,43 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._providers.connect_provider_changed(self._on_provider_changed)
- # EIP Control redux #########################################
- self._eip_conductor = eip_conductor.EIPConductor(
- self._settings, self._backend, self._leap_signaler)
- self._eip_status = EIPStatusWidget(self, self._eip_conductor,
- self._leap_signaler)
-
- init_signals.eip_missing_helpers.connect(
- self._disable_eip_missing_helpers)
-
- self.ui.eipLayout.addWidget(self._eip_status)
-
- # XXX we should get rid of the circular refs
- # conductor <-> status, right now keeping state on the widget ifself.
- self._eip_conductor.add_eip_widget(self._eip_status)
-
- self._eip_conductor.connect_signals()
- self._eip_conductor.qtsigs.connecting_signal.connect(
- self._on_eip_connecting)
- self._eip_conductor.qtsigs.connected_signal.connect(
- self._on_eip_connection_connected)
- self._eip_conductor.qtsigs.disconnected_signal.connect(
- self._on_eip_connection_disconnected)
- self._eip_conductor.qtsigs.connected_signal.connect(
- self._maybe_run_soledad_setup_checks)
+ if HAS_EIP:
+ # EIP Control redux #########################################
+ self._eip_conductor = eip_conductor.EIPConductor(
+ self._settings, self._backend, self._leap_signaler)
+ self._eip_status = EIPStatusWidget(self, self._eip_conductor,
+ self._leap_signaler)
+
+ init_signals.eip_missing_helpers.connect(
+ self._disable_eip_missing_helpers)
+
+ self.ui.eipLayout.addWidget(self._eip_status)
+
+ # XXX we should get rid of the circular refs
+ # conductor <-> status,
+ # right now keeping state on the widget ifself.
+ self._eip_conductor.add_eip_widget(self._eip_status)
+
+ self._eip_conductor.connect_signals()
+ self._eip_conductor.qtsigs.connecting_signal.connect(
+ self._on_eip_connecting)
+ self._eip_conductor.qtsigs.connected_signal.connect(
+ self._on_eip_connection_connected)
+ self._eip_conductor.qtsigs.disconnected_signal.connect(
+ self._on_eip_connection_disconnected)
+ self._eip_conductor.qtsigs.connected_signal.connect(
+ self._maybe_run_soledad_setup_checks)
+
+ self.eip_needs_login.connect(self._eip_status.disable_eip_start)
+ self.eip_needs_login.connect(self._disable_eip_start_action)
+
+ # XXX all this info about state should move to eip conductor too
+ self._already_started_eip = False
+ self._trying_to_start_eip = False
self._login_widget.login_offline_finished.connect(
self._maybe_run_soledad_setup_checks)
- self.eip_needs_login.connect(self._eip_status.disable_eip_start)
- self.eip_needs_login.connect(self._disable_eip_start_action)
-
- # XXX all this info about state should move to eip conductor too
- self._already_started_eip = False
- self._trying_to_start_eip = False
-
self._soledad_started = False
# This is created once we have a valid provider config
@@ -210,15 +222,14 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self.ui.action_wizard.triggered.connect(self._show_wizard)
self.ui.action_show_logs.triggered.connect(self._show_logger_window)
- # XXX hide the help menu since it only shows email information and
- # right now we don't have stable mail and just confuses users.
- self.ui.action_help.setVisible(False)
- # self.ui.action_help.triggered.connect(self._help)
+ self.ui.action_help.setVisible(True)
+ self.ui.action_help.triggered.connect(self._help)
self.ui.action_create_new_account.triggered.connect(
self._on_provider_changed)
# Action item hidden since we don't provide stable mail yet.
+ # TODO enable for 0.9.0 release??
# self.ui.action_advanced_key_management.triggered.connect(
# self._show_AKM)
@@ -230,11 +241,16 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._systray = None
# XXX separate actions into a different module.
- self._action_mail_status = QtGui.QAction(self.tr("Mail is OFF"), self)
- self._mail_status.set_action_mail_status(self._action_mail_status)
+ if HAS_MAIL:
+ self._action_mail_status = QtGui.QAction(
+ self.tr("Mail is OFF"), self)
+ self._mail_status.set_action_mail_status(
+ self._action_mail_status)
- self._action_eip_startstop = QtGui.QAction("", self)
- self._eip_status.set_action_eip_startstop(self._action_eip_startstop)
+ if HAS_EIP:
+ self._action_eip_startstop = QtGui.QAction("", self)
+ self._eip_status.set_action_eip_startstop(
+ self._action_eip_startstop)
self._action_visible = QtGui.QAction(self.tr("Show Main Window"), self)
self._action_visible.triggered.connect(self._ensure_visible)
@@ -272,19 +288,21 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._start_hidden = start_hidden
self._backend_pid = backend_pid
- self._mail_conductor = mail_conductor.MailConductor(self._backend)
- self._mail_conductor.connect_mail_signals(self._mail_status)
+ if HAS_MAIL:
+ self._mail_conductor = mail_conductor.MailConductor(self._backend)
+ self._mail_conductor.connect_mail_signals(self._mail_status)
if not init_platform():
self.quit()
return
# start event machines from within the eip and mail conductors
-
# TODO should encapsulate all actions into one object
- self._eip_conductor.start_eip_machine(
- action=self._action_eip_startstop)
- self._mail_conductor.start_mail_machine()
+ if HAS_EIP:
+ self._eip_conductor.start_eip_machine(
+ action=self._action_eip_startstop)
+ if HAS_MAIL:
+ self._mail_conductor.start_mail_machine()
if self._first_run():
self._wizard_firstrun = True
@@ -363,17 +381,17 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
# here.
sig.srp_not_logged_in_error.connect(self._not_logged_in_error)
- # EIP start signals ==============================================
- self._eip_conductor.connect_backend_signals()
- sig.eip_can_start.connect(self._backend_can_start_eip)
- sig.eip_cannot_start.connect(self._backend_cannot_start_eip)
+ if HAS_EIP:
+ # EIP start signals ==============================================
+ self._eip_conductor.connect_backend_signals()
+ sig.eip_can_start.connect(self._backend_can_start_eip)
+ sig.eip_cannot_start.connect(self._backend_cannot_start_eip)
- sig.eip_dns_error.connect(self._eip_dns_error)
+ sig.eip_dns_error.connect(self._eip_dns_error)
- sig.eip_get_gateway_country_code.connect(self._set_eip_provider)
- sig.eip_no_gateway.connect(self._set_eip_provider)
-
- # ==================================================================
+ sig.eip_get_gateway_country_code.connect(self._set_eip_provider)
+ sig.eip_no_gateway.connect(self._set_eip_provider)
+ # ==================================================================
# Soledad signals
# TODO delegate connection to soledad bootstrapper
@@ -491,25 +509,11 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._login_widget.set_password(possible_password)
self._login()
else:
- self.eip_needs_login.emit()
+ if HAS_EIP:
+ self.eip_needs_login.emit()
self._wizard = None
- def _get_leap_logging_handler(self):
- """
- Gets the leap handler from the top level logger
-
- :return: a logging handler or None
- :rtype: LeapLogHandler or None
- """
- # TODO this can be a function, does not need
- # to be a method.
- leap_logger = logging.getLogger('leap')
- for h in leap_logger.handlers:
- if isinstance(h, LeapLogHandler):
- return h
- return None
-
def _show_logger_window(self):
"""
TRIGGERS:
@@ -518,13 +522,8 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
Display the window with the history of messages logged until now
and displays the new ones on arrival.
"""
- leap_log_handler = self._get_leap_logging_handler()
- if leap_log_handler is None:
- logger.error('Leap logger handler not found')
- return
- else:
- lw = LoggerWindow(self, handler=leap_log_handler)
- lw.show()
+ lw = LoggerWindow(self)
+ lw.show()
def _show_AKM(self):
"""
@@ -589,22 +588,26 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._backend_cannot_start_eip()
return
- if EIP_SERVICE not in self.app.settings.get_enabled_services(domain):
- self._eip_conductor.terminate()
+ services_enabled = self.app.settings.get_enabled_services(domain)
- def hide():
- self.app.backend.eip_can_start(domain=domain)
+ if HAS_EIP:
+ if EIP_SERVICE not in services_enabled:
+ self._eip_conductor.terminate()
- QtDelayedCall(100, hide)
- # ^^ VERY VERY Hacky, but with the simple state machine,
- # there is no way to signal 'disconnect and then disable'
+ def hide():
+ self.app.backend.eip_can_start(domain=domain)
- else:
- self._trying_to_start_eip = self.app.settings.get_autostart_eip()
- if not self._trying_to_start_eip:
- self._backend.eip_setup(provider=domain, skip_network=True)
- # check if EIP can start (will trigger widget update)
- self.app.backend.eip_can_start(domain=domain)
+ QtDelayedCall(100, hide)
+ # ^^ VERY VERY Hacky, but with the simple state machine,
+ # there is no way to signal 'disconnect and then disable'
+
+ else:
+ settings = self.app.settings
+ self._trying_to_start_eip = settings.get_autostart_eip()
+ if not self._trying_to_start_eip:
+ self._backend.eip_setup(provider=domain, skip_network=True)
+ # check if EIP can start (will trigger widget update)
+ self.app.backend.eip_can_start(domain=domain)
def _backend_can_start_eip(self):
"""
@@ -656,15 +659,16 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
if default_provider is not None:
enabled_services = settings.get_enabled_services(default_provider)
- if EIP_SERVICE in enabled_services:
- # we don't have a usable provider
- # so the user needs to log in first
- self._eip_status.disable_eip_start()
- else:
- self._eip_status.disable_eip_start()
- # NOTE: we shouldn't be setting the message here.
- if not self._eip_status.missing_helpers:
- self._eip_status.set_eip_status(self.tr("Disabled"))
+ if HAS_EIP:
+ if EIP_SERVICE in enabled_services:
+ # we don't have a usable provider
+ # so the user needs to log in first
+ self._eip_status.disable_eip_start()
+ else:
+ self._eip_status.disable_eip_start()
+ # NOTE: we shouldn't be setting the message here.
+ if not self._eip_status.missing_helpers:
+ self._eip_status.set_eip_status(self.tr("Disabled"))
# this state flag is responsible for deferring the login
# so we must update it, otherwise we're in a deadlock.
@@ -683,29 +687,31 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
# updates
#
- def _new_updates_available(self, req):
+ def _new_updates_available(self, event, content):
"""
Callback for the new updates event
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param event: The event that triggered the callback.
+ :type event: str
+ :param content: The content of the event.
+ :type content: list
"""
- self.new_updates.emit(req)
+ self.new_updates.emit(content)
- def _react_to_new_updates(self, req):
+ def _react_to_new_updates(self, content):
"""
TRIGGERS:
self.new_updates
Display the new updates label and sets the updates_content
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
+ :param content: The content of the event.
+ :type content: list
"""
self.moveToThread(QtCore.QCoreApplication.instance().thread())
self.ui.lblNewUpdates.setVisible(True)
self.ui.btnMore.setVisible(True)
- self._updates_content = req.content
+ self._updates_content = content
def _updates_details(self):
"""
@@ -761,6 +767,8 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._show_hide_unsupported_services()
+ LOG_CONTROLLER.start_logbook_subscriber()
+
# XXX - HACK, kind of...
# With the 1ms QTimer.singleShot call we schedule the call right after
# other signals waiting for the qt reactor to take control.
@@ -798,12 +806,13 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
only, the mail widget won't be displayed.
"""
providers = self._settings.get_configured_providers()
-
self._backend.provider_get_all_services(providers=providers)
def _provider_get_all_services(self, services):
- self._set_eip_visible(EIP_SERVICE in services)
- self._set_mx_visible(MX_SERVICE in services)
+ if HAS_EIP:
+ self._set_eip_visible(EIP_SERVICE in services)
+ if HAS_MAIL:
+ self._set_mx_visible(MX_SERVICE in services)
def _set_mx_visible(self, visible):
"""
@@ -856,23 +865,34 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
systrayMenu.addAction(self._action_visible)
systrayMenu.addSeparator()
- eip_status_label = u"{0}: {1}".format(
- self._eip_conductor.eip_name, self.tr("OFF"))
- self._eip_menu = eip_menu = systrayMenu.addMenu(eip_status_label)
- eip_menu.addAction(self._action_eip_startstop)
- self._eip_status.set_eip_status_menu(eip_menu)
- systrayMenu.addSeparator()
- systrayMenu.addAction(self._action_mail_status)
- systrayMenu.addSeparator()
+ if HAS_EIP:
+ eip_status_label = u"{0}: {1}".format(
+ self._eip_conductor.eip_name, self.tr("OFF"))
+ self._eip_menu = eip_menu = systrayMenu.addMenu(eip_status_label)
+ eip_menu.addAction(self._action_eip_startstop)
+ self._eip_status.set_eip_status_menu(eip_menu)
+ systrayMenu.addSeparator()
+ if HAS_MAIL:
+ systrayMenu.addAction(self._action_mail_status)
+ systrayMenu.addSeparator()
systrayMenu.addAction(self.ui.action_quit)
+
self._systray = SysTray(self)
self._systray.setContextMenu(systrayMenu)
- self._systray.setIcon(self._eip_status.ERROR_ICON_TRAY)
+
+ if HAS_EIP:
+ self._systray.setIcon(self._eip_status.ERROR_ICON_TRAY)
+ else:
+ mail_status_icon = QtGui.QPixmap(BITMASK_MAIL_ONLY_ICON)
+ self._systray.setIcon(mail_status_icon)
+
self._systray.setVisible(True)
self._systray.activated.connect(self._tray_activated)
- self._mail_status.set_systray(self._systray)
- self._eip_status.set_systray(self._systray)
+ if HAS_EIP:
+ self._eip_status.set_systray(self._systray)
+ if HAS_MAIL:
+ self._mail_status.set_systray(self._systray)
if self._start_hidden:
hello = lambda: self._systray.showMessage(
@@ -1004,7 +1024,7 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
"manager or download it from <a href='{0}'>"
"addons.mozilla.org</a>.".format(thunderbird_extension_url))
manual_text = self.tr(
- "Alternately, you can manually configure "
+ "Alternatively, you can manually configure "
"your mail client to use Bitmask Email with these options:")
manual_imap = self.tr("IMAP: localhost, port {0}".format(IMAP_PORT))
manual_smtp = self.tr("SMTP: localhost, port {0}".format(smtp_port))
@@ -1055,7 +1075,7 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
if not e.spontaneous():
# if the system requested the `close` then we should quit.
self._system_quit = True
- self.quit()
+ self.quit(disable_autostart=False)
return
if QtGui.QSystemTrayIcon.isSystemTrayAvailable() and \
@@ -1112,8 +1132,11 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
# TODO: we should handle the case that EIP is autostarting since we
# won't get a warning until EIP has fully started.
# TODO: we need to add a check for the mail status (smtp/imap/soledad)
- something_runing = (self._login_widget.get_logged_user() is not None or
- self._already_started_eip)
+
+ something_runing = self._login_widget.get_logged_user() is not None
+ if HAS_EIP:
+ something_runing = something_runing or self._already_started_eip
+
provider = self._providers.get_selected_provider()
self._login_widget.set_provider(provider)
@@ -1192,22 +1215,34 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._disconnect_login_wait()
user = self._login_widget.get_logged_user()
- domain = self._providers.get_selected_provider()
- full_user_id = make_address(user, domain)
- self._mail_conductor.userid = full_user_id
- self._start_eip_bootstrap()
- self.ui.action_create_new_account.setEnabled(True)
+ # XXX the widget now gives us the full user id.
+ # this is confusing.
- # if soledad/mail is enabled:
- if MX_SERVICE in self._enabled_services:
- btn_enabled = self._login_widget.set_logout_btn_enabled
- btn_enabled(False)
- sig = self._leap_signaler
- sig.soledad_bootstrap_failed.connect(lambda: btn_enabled(True))
- sig.soledad_bootstrap_finished.connect(lambda: btn_enabled(True))
+ self.ui.action_create_new_account.setEnabled(True)
- if MX_SERVICE not in self._provider_details['services']:
- self._set_mx_visible(False)
+ if HAS_EIP:
+ self._start_eip_bootstrap()
+ if HAS_MAIL:
+ # XXX the casting to str (needed by smtp gateway) should be done
+ # in a better place.
+ self._mail_conductor.userid = str(user)
+ if MX_SERVICE in self._enabled_services:
+ btn_enabled = self._login_widget.set_logout_btn_enabled
+ btn_enabled(False)
+ sig = self._leap_signaler
+ sig.soledad_bootstrap_failed.connect(
+ lambda: btn_enabled(True))
+ sig.soledad_bootstrap_finished.connect(
+ lambda: btn_enabled(True))
+
+ if MX_SERVICE not in self._provider_details['services']:
+ self._set_mx_visible(False)
+
+ if not HAS_EIP:
+ # This has to be worked out in Bitmask 0.10.
+ # Since EIP won't start, we need to trigger
+ # the soledad setup service from here.
+ self._maybe_run_soledad_setup_checks()
def _on_user_logged_out(self):
"""
@@ -1217,8 +1252,9 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
Switch the stackedWidget back to the login stage after
logging out
"""
- self._mail_conductor.stop_mail_services()
- self._mail_status.mail_state_disabled()
+ if HAS_MAIL:
+ self._mail_conductor.stop_mail_services()
+ self._mail_status.mail_state_disabled()
self._show_hide_unsupported_services()
def _start_eip_bootstrap(self):
@@ -1312,10 +1348,10 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
if flags.OFFLINE:
full_user_id = make_address(username, provider_domain)
- uuid = self._settings.get_uuid(full_user_id)
+ uuid = self._backend_settings.get_uuid(full_user_id)
self._mail_conductor.userid = full_user_id
- if uuid is None:
+ if not uuid:
# We don't need more visibility at the moment,
# this is mostly for internal use/debug for now.
logger.warning("Sorry! Log-in at least one time.")
@@ -1479,9 +1515,9 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
missing_helpers = self._eip_status.missing_helpers
already_started = self._already_started_eip
- can_start = (should_start
- and not already_started
- and not missing_helpers)
+ can_start = (should_start and
+ not already_started and
+ not missing_helpers)
if can_start:
if self._eip_status.is_cold_start:
@@ -1518,7 +1554,9 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
msg = self.tr("Disabled")
self._eip_status.disable_eip_start()
self._eip_status.set_eip_status(msg)
+
# eip will not start, so we start soledad anyway
+ # XXX This is the entry point for soledad startup.
self._maybe_run_soledad_setup_checks()
def _finish_eip_bootstrap(self, data):
@@ -1566,9 +1604,14 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
# window handling methods
#
- def _on_raise_window_event(self, req):
+ def _on_raise_window_event(self, event, content):
"""
Callback for the raise window event
+
+ :param event: The event that triggered the callback.
+ :type event: str
+ :param content: The content of the event.
+ :type content: list
"""
if IS_WIN:
locks.raise_window_ack()
@@ -1618,18 +1661,24 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
logger.debug('Terminating vpn')
self._backend.eip_stop(shutdown=True)
- def quit(self):
+ def quit(self, disable_autostart=True):
"""
Start the quit sequence and wait for services to finish.
Cleanup and close the main window before quitting.
+
+ :param disable_autostart: whether we should disable the autostart
+ feature or not
+ :type disable_autostart: bool
"""
if self._quitting:
return
+ if disable_autostart:
+ autostart.set_autostart(False)
+
self._quitting = True
self._close_to_tray = False
logger.debug('Quitting...')
- autostart.set_autostart(False)
# first thing to do quitting, hide the mainwindow and show tooltip.
self.hide()
@@ -1712,6 +1761,7 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
self._leap_signaler.stop()
+ LOG_CONTROLLER.stop_logbook_subscriber()
self._backend.stop()
time.sleep(0.05) # give the thread a little time to finish.
diff --git a/src/leap/bitmask/gui/passwordwindow.py b/src/leap/bitmask/gui/passwordwindow.py
index 88565829..94cf25da 100644
--- a/src/leap/bitmask/gui/passwordwindow.py
+++ b/src/leap/bitmask/gui/passwordwindow.py
@@ -19,14 +19,14 @@
Change password dialog window
"""
-from PySide import QtCore, QtGui
-from leap.bitmask.util.credentials import password_checks
+from PySide import QtGui
+from leap.bitmask.logs.utils import get_logger
+from leap.bitmask.util.credentials import password_checks
from leap.bitmask.gui.ui_password_change import Ui_PasswordChange
from leap.bitmask.gui.flashable import Flashable
-import logging
-logger = logging.getLogger(__name__)
+logger = get_logger()
class PasswordWindow(QtGui.QDialog, Flashable):
diff --git a/src/leap/bitmask/gui/preferences_account_page.py b/src/leap/bitmask/gui/preferences_account_page.py
index cab90eec..da9da14d 100644
--- a/src/leap/bitmask/gui/preferences_account_page.py
+++ b/src/leap/bitmask/gui/preferences_account_page.py
@@ -16,16 +16,17 @@
"""
Widget for "account" preferences
"""
-import logging
-
from functools import partial
from PySide import QtCore, QtGui
-from leap.bitmask.gui.ui_preferences_account_page import Ui_PreferencesAccountPage
+
+from leap.bitmask.logs.utils import get_logger
+from leap.bitmask.gui import ui_preferences_account_page as ui_pref
from leap.bitmask.gui.passwordwindow import PasswordWindow
from leap.bitmask.services import get_service_display_name
+from leap.bitmask._components import HAS_EIP
-logger = logging.getLogger(__name__)
+logger = get_logger()
class PreferencesAccountPage(QtGui.QWidget):
@@ -42,7 +43,7 @@ class PreferencesAccountPage(QtGui.QWidget):
:type app: App
"""
QtGui.QWidget.__init__(self, parent)
- self.ui = Ui_PreferencesAccountPage()
+ self.ui = ui_pref.Ui_PreferencesAccountPage()
self.ui.setupUi(self)
self.account = account
@@ -120,6 +121,8 @@ class PreferencesAccountPage(QtGui.QWidget):
# add one checkbox per service and set the current value
# from what is saved in settings.
for service in services:
+ if not HAS_EIP and service == "openvpn":
+ continue
try:
checkbox = QtGui.QCheckBox(
get_service_display_name(service), self)
diff --git a/src/leap/bitmask/gui/preferences_email_page.py b/src/leap/bitmask/gui/preferences_email_page.py
index 80e8d93e..3087f343 100644
--- a/src/leap/bitmask/gui/preferences_email_page.py
+++ b/src/leap/bitmask/gui/preferences_email_page.py
@@ -16,12 +16,12 @@
"""
Widget for "email" preferences
"""
-import logging
+from PySide import QtGui
-from PySide import QtCore, QtGui
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.gui.ui_preferences_email_page import Ui_PreferencesEmailPage
-logger = logging.getLogger(__name__)
+logger = get_logger()
class PreferencesEmailPage(QtGui.QWidget):
diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py
index daad08b0..baa71252 100644
--- a/src/leap/bitmask/gui/preferenceswindow.py
+++ b/src/leap/bitmask/gui/preferenceswindow.py
@@ -18,18 +18,18 @@
"""
Preferences window
"""
-import logging
-
from PySide import QtCore, QtGui
-from leap.bitmask.services import EIP_SERVICE, MX_SERVICE
+from leap.bitmask.services import EIP_SERVICE
+from leap.bitmask._components import HAS_EIP
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.gui.ui_preferences import Ui_Preferences
from leap.bitmask.gui.preferences_account_page import PreferencesAccountPage
from leap.bitmask.gui.preferences_vpn_page import PreferencesVpnPage
from leap.bitmask.gui.preferences_email_page import PreferencesEmailPage
-logger = logging.getLogger(__name__)
+logger = get_logger()
class PreferencesWindow(QtGui.QDialog):
@@ -121,7 +121,8 @@ class PreferencesWindow(QtGui.QDialog):
"""
Adds the pages for the different configuration categories.
"""
- self._account_page = PreferencesAccountPage(self, self.account, self.app)
+ self._account_page = PreferencesAccountPage(
+ self, self.account, self.app)
self._vpn_page = PreferencesVpnPage(self, self.account, self.app)
self._email_page = PreferencesEmailPage(self, self.account, self.app)
@@ -179,6 +180,7 @@ class PreferencesWindow(QtGui.QDialog):
if account != self.account:
return
- self._vpn_item.setHidden(not EIP_SERVICE in services)
+ if HAS_EIP:
+ self._vpn_item.setHidden(EIP_SERVICE not in services)
# self._email_item.setHidden(not MX_SERVICE in services)
# ^^ disable email for now, there is nothing there yet.
diff --git a/src/leap/bitmask/gui/signaltracker.py b/src/leap/bitmask/gui/signaltracker.py
index 0e3b2dce..3dfcfe18 100644
--- a/src/leap/bitmask/gui/signaltracker.py
+++ b/src/leap/bitmask/gui/signaltracker.py
@@ -14,11 +14,11 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import logging
-
from PySide import QtCore
-logger = logging.getLogger(__name__)
+from leap.bitmask.logs.utils import get_logger
+
+logger = get_logger()
class SignalTracker(QtCore.QObject):
diff --git a/src/leap/bitmask/gui/statemachines.py b/src/leap/bitmask/gui/statemachines.py
index 91f1f605..ab48b756 100644
--- a/src/leap/bitmask/gui/statemachines.py
+++ b/src/leap/bitmask/gui/statemachines.py
@@ -17,16 +17,15 @@
"""
State machines for the Bitmask app.
"""
-import logging
-
from PySide import QtCore
from PySide.QtCore import QStateMachine, QState, Signal
from PySide.QtCore import QObject
from leap.bitmask.services import connections
from leap.common.check import leap_assert_type
+from leap.bitmask.logs.utils import get_logger
-logger = logging.getLogger(__name__)
+logger = get_logger()
_tr = QObject().tr
diff --git a/src/leap/bitmask/gui/ui/wizard.ui b/src/leap/bitmask/gui/ui/wizard.ui
index 0e28ecbf..b125577e 100644
--- a/src/leap/bitmask/gui/ui/wizard.ui
+++ b/src/leap/bitmask/gui/ui/wizard.ui
@@ -43,7 +43,7 @@
<string>Welcome to Bitmask</string>
</property>
<property name="subTitle">
- <string> </string>
+ <string/>
</property>
<attribute name="pageId">
<string notr="true">0</string>
@@ -59,7 +59,7 @@
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
- <string></string>
+ <string/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
@@ -112,7 +112,7 @@
<string>Choose a provider</string>
</property>
<property name="subTitle">
- <string> </string>
+ <string/>
</property>
<attribute name="pageId">
<string notr="true">1</string>
@@ -187,15 +187,15 @@
<height>22</height>
</size>
</property>
- <property name="scaledContents">
- <bool>true</bool>
- </property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../../data/resources/icons.qrc">:/images/black/22/question.png</pixmap>
</property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="2" column="1">
@@ -218,15 +218,15 @@
<height>22</height>
</size>
</property>
- <property name="scaledContents">
- <bool>true</bool>
- </property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../../data/resources/icons.qrc">:/images/black/22/question.png</pixmap>
</property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="1" column="1">
@@ -249,15 +249,15 @@
<height>22</height>
</size>
</property>
- <property name="scaledContents">
- <bool>true</bool>
- </property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../../data/resources/icons.qrc">:/images/black/22/question.png</pixmap>
</property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="1" column="0">
@@ -363,6 +363,12 @@
</item>
<item>
<widget class="QPushButton" name="btnCheck">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
<property name="text">
<string>Check</string>
</property>
@@ -380,7 +386,7 @@
<string>About this provider</string>
</property>
<property name="subTitle">
- <string> </string>
+ <string/>
</property>
<attribute name="pageId">
<string notr="true">2</string>
@@ -522,7 +528,7 @@
<string>Provider setup</string>
</property>
<property name="subTitle">
- <string> </string>
+ <string/>
</property>
<attribute name="pageId">
<string notr="true">3</string>
@@ -590,15 +596,15 @@
<height>22</height>
</size>
</property>
- <property name="scaledContents">
- <bool>true</bool>
- </property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../../data/resources/icons.qrc">:/images/black/22/question.png</pixmap>
</property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="1" column="1">
@@ -621,15 +627,15 @@
<height>22</height>
</size>
</property>
- <property name="scaledContents">
- <bool>true</bool>
- </property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../../data/resources/icons.qrc">:/images/black/22/question.png</pixmap>
</property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="1" column="0">
@@ -673,15 +679,15 @@
<height>22</height>
</size>
</property>
- <property name="scaledContents">
- <bool>true</bool>
- </property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../../data/resources/icons.qrc">:/images/black/22/question.png</pixmap>
</property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="0" column="0">
@@ -720,7 +726,7 @@
<string>Register new user</string>
</property>
<property name="subTitle">
- <string> </string>
+ <string/>
</property>
<attribute name="pageId">
<string notr="true">4</string>
@@ -845,7 +851,7 @@
<string>Service selection</string>
</property>
<property name="subTitle">
- <string> </string>
+ <string/>
</property>
<attribute name="pageId">
<string notr="true">5</string>
diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py
index 5da021d1..abaf2108 100644
--- a/src/leap/bitmask/gui/wizard.py
+++ b/src/leap/bitmask/gui/wizard.py
@@ -17,7 +17,6 @@
"""
First run wizard
"""
-import logging
import random
from functools import partial
@@ -30,16 +29,18 @@ from leap.bitmask.backend.leapbackend import ERROR_KEY, PASSED_KEY
from leap.bitmask.config import flags
from leap.bitmask.config.leapsettings import LeapSettings
+from leap.bitmask.logs.utils import get_logger
from leap.bitmask.gui.signaltracker import SignalTracker
from leap.bitmask.services import get_service_display_name, get_supported
from leap.bitmask.util.credentials import password_checks, username_checks
from leap.bitmask.util.credentials import USERNAME_REGEX
from leap.bitmask.util.keyring_helpers import has_keyring
+from leap.bitmask._components import HAS_EIP
from ui_wizard import Ui_Wizard
QtDelayedCall = QtCore.QTimer.singleShot
-logger = logging.getLogger(__name__)
+logger = get_logger()
class Wizard(QtGui.QWizard, SignalTracker):
@@ -264,6 +265,20 @@ class Wizard(QtGui.QWizard, SignalTracker):
if reset:
self._reset_provider_check()
+ def _provider_widget_set_enabled(self, enabled):
+ """
+ Enable/Disable the provider widget.
+ The widget to use depends on whether the used decided to use an
+ existing provider or a new one.
+
+ :param enabled: the new state for the widget
+ :type enabled: bool
+ """
+ if self.ui.rbNewProvider.isChecked():
+ self.ui.lnProvider.setEnabled(enabled)
+ else:
+ self.ui.cbProviders.setEnabled(enabled)
+
def _focus_username(self):
"""
Focus at the username lineedit for the registration page
@@ -371,6 +386,19 @@ class Wizard(QtGui.QWizard, SignalTracker):
self._set_register_status(error_msg, error=True)
self.ui.btnRegister.setEnabled(True)
+ def _registration_disabled(self):
+ """
+ TRIGGERS:
+ self._backend.signaler.srp_registration_disabled
+
+ The registration is disabled in the current provider.
+ """
+ self._username = self._password = None
+
+ error_msg = self.tr("The registration is disabled for this provider.")
+ self._set_register_status(error_msg, error=True)
+ self.ui.btnRegister.setEnabled(True)
+
def _registration_taken(self):
"""
TRIGGERS:
@@ -439,11 +467,7 @@ class Wizard(QtGui.QWizard, SignalTracker):
self.ui.grpCheckProvider.setVisible(True)
self.ui.btnCheck.setEnabled(False)
- # Disable provider widget
- if self.ui.rbNewProvider.isChecked():
- self.ui.lnProvider.setEnabled(False)
- else:
- self.ui.cbProviders.setEnabled(False)
+ self._provider_widget_set_enabled(False)
self.button(QtGui.QWizard.BackButton).clearFocus()
@@ -510,7 +534,7 @@ class Wizard(QtGui.QWizard, SignalTracker):
self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON)
self.ui.lblProviderSelectStatus.setText(status)
self.ui.btnCheck.setEnabled(not passed)
- self.ui.lnProvider.setEnabled(not passed)
+ self._provider_widget_set_enabled(not passed)
def _https_connection(self, data):
"""
@@ -529,7 +553,8 @@ class Wizard(QtGui.QWizard, SignalTracker):
else:
self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON)
self.ui.btnCheck.setEnabled(not passed)
- self.ui.lnProvider.setEnabled(not passed)
+
+ self._provider_widget_set_enabled(not passed)
def _download_provider_info(self, data):
"""
@@ -558,13 +583,9 @@ class Wizard(QtGui.QWizard, SignalTracker):
status = self.tr("<font color='red'><b>Not a valid provider"
"</b></font>")
self.ui.lblProviderSelectStatus.setText(status)
- self.ui.btnCheck.setEnabled(True)
- # Enable provider widget
- if self.ui.rbNewProvider.isChecked():
- self.ui.lnProvider.setEnabled(True)
- else:
- self.ui.cbProviders.setEnabled(True)
+ self.ui.btnCheck.setEnabled(True)
+ self._provider_widget_set_enabled(True)
def _provider_get_details(self, details):
"""
@@ -574,6 +595,22 @@ class Wizard(QtGui.QWizard, SignalTracker):
:type details: dict
"""
self._provider_details = details
+ self._check_registration_allowed()
+
+ def _check_registration_allowed(self):
+ """
+ Check whether the provider allows new users registration or not.
+ If it is not allowed we display a message and prevent the user moving
+ forward on the wizard.
+ """
+ if self._show_register: # user wants to register a new account
+ if not self._provider_details['allow_registration']:
+ logger.debug("Registration not allowed")
+ status = ("<font color='red'><b>" +
+ self.tr("The provider has disabled registration") +
+ "</b></font>")
+ self.ui.lblProviderSelectStatus.setText(status)
+ self.button(QtGui.QWizard.NextButton).setEnabled(False)
def _download_ca_cert(self, data):
"""
@@ -654,6 +691,12 @@ class Wizard(QtGui.QWizard, SignalTracker):
checkbox.stateChanged.connect(
partial(self._service_selection_changed, service))
checkbox.setChecked(True)
+
+ if service == "openvpn" and not HAS_EIP:
+ # this is a mail-only build, we disable eip.
+ checkbox.setEnabled(False)
+ checkbox.setChecked(False)
+
self._shown_services.add(service)
except ValueError:
logger.error(
@@ -675,9 +718,11 @@ class Wizard(QtGui.QWizard, SignalTracker):
skip = self.ui.rbExistingProvider.isChecked()
if not self._provider_checks_ok:
self._enable_check()
+ self.ui.btnCheck.setFocus()
self._skip_provider_checks(skip)
else:
self._enable_check(reset=False)
+ self._check_registration_allowed()
if pageId == self.SETUP_PROVIDER_PAGE:
if not self._provider_setup_ok:
@@ -757,5 +802,6 @@ class Wizard(QtGui.QWizard, SignalTracker):
conntrack(sig.prov_check_api_certificate, self._check_api_certificate)
conntrack(sig.srp_registration_finished, self._registration_finished)
+ conntrack(sig.srp_registration_disabled, self._registration_disabled)
conntrack(sig.srp_registration_failed, self._registration_failed)
conntrack(sig.srp_registration_taken, self._registration_taken)