summaryrefslogtreecommitdiff
path: root/src/leap/gui
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2013-08-12 13:25:44 +0200
committerKali Kaneko <kali@leap.se>2013-08-12 13:25:44 +0200
commit6da8d09846db4d2eed01e488bc6a6f5ba48b959f (patch)
tree3b82e8c4e14b1730ff292b6eb632c145dafb332a /src/leap/gui
parent00d98a47c60764475d97df1c2eb847e20a77cae5 (diff)
move everything into bitmask namespace
Diffstat (limited to 'src/leap/gui')
-rw-r--r--src/leap/gui/__init__.py21
-rw-r--r--src/leap/gui/loggerwindow.py137
-rw-r--r--src/leap/gui/login.py245
-rw-r--r--src/leap/gui/mainwindow.py1537
-rw-r--r--src/leap/gui/statuspanel.py459
-rw-r--r--src/leap/gui/twisted_main.py60
-rw-r--r--src/leap/gui/ui/loggerwindow.ui155
-rw-r--r--src/leap/gui/ui/login.ui132
-rw-r--r--src/leap/gui/ui/mainwindow.ui315
-rw-r--r--src/leap/gui/ui/statuspanel.ui289
-rw-r--r--src/leap/gui/ui/wizard.ui846
-rw-r--r--src/leap/gui/wizard.py626
-rw-r--r--src/leap/gui/wizardpage.py40
13 files changed, 0 insertions, 4862 deletions
diff --git a/src/leap/gui/__init__.py b/src/leap/gui/__init__.py
deleted file mode 100644
index 4b289442..00000000
--- a/src/leap/gui/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-# __init__.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/>.
-"""
-init file for leap.gui
-"""
-app = __import__("app", globals(), locals(), [], 2)
-__all__ = [app]
diff --git a/src/leap/gui/loggerwindow.py b/src/leap/gui/loggerwindow.py
deleted file mode 100644
index fcbdbf19..00000000
--- a/src/leap/gui/loggerwindow.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# -*- coding: utf-8 -*-
-# loggerwindow.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/>.
-
-"""
-History log window
-"""
-import logging
-
-from PySide import QtGui
-from ui_loggerwindow import Ui_LoggerWindow
-from leap.common.check import leap_assert, leap_assert_type
-from leap.util.leap_log_handler import LeapLogHandler
-
-logger = logging.getLogger(__name__)
-
-
-class LoggerWindow(QtGui.QDialog):
- """
- Window that displays a history of the logged messages in the app.
- """
- def __init__(self, handler):
- """
- Initialize the widget with the custom handler.
-
- :param handler: Custom handler that supports history and signal.
- :type handler: LeapLogHandler.
- """
- QtGui.QDialog.__init__(self)
- leap_assert(handler, "We need a handler for the logger window")
- leap_assert_type(handler, LeapLogHandler)
-
- # Load UI
- self.ui = Ui_LoggerWindow()
- self.ui.setupUi(self)
-
- # Make connections
- self.ui.btnSave.clicked.connect(self._save_log_to_file)
- self.ui.btnDebug.toggled.connect(self._load_history),
- self.ui.btnInfo.toggled.connect(self._load_history),
- self.ui.btnWarning.toggled.connect(self._load_history),
- self.ui.btnError.toggled.connect(self._load_history),
- self.ui.btnCritical.toggled.connect(self._load_history)
-
- # Load logging history and connect logger with the widget
- self._logging_handler = handler
- self._connect_to_handler()
- self._load_history()
-
- 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)
-
- 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.
- """
- 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;"
- }
- level = log[LeapLogHandler.RECORD_KEY].levelno
- message = log[LeapLogHandler.MESSAGE_KEY]
- message = message.replace('\n', '<br>\n')
-
- if self._logs_to_display[level]:
- open_tag = "<tr style='" + html_style[level] + "'>"
- open_tag += "<td width='100%' style='padding: 5px;'>"
- close_tag = "</td></tr>"
- message = open_tag + message + close_tag
-
- self.ui.txtLogHistory.append(message)
-
- def _load_history(self):
- """
- Load the previous logged messages in the widget.
- They are stored in the custom handler.
- """
- self._set_logs_to_display()
- self.ui.txtLogHistory.clear()
- history = self._logging_handler.log_history
- for line in history:
- self._add_log_line(line)
-
- def _set_logs_to_display(self):
- """
- 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()
- }
-
- def _save_log_to_file(self):
- """
- Lets the user save the current log to a file
- """
- fileName, filtr = QtGui.QFileDialog.getSaveFileName(
- self, self.tr("Save As"))
-
- if fileName:
- try:
- with open(fileName, 'w') as output:
- output.write(self.ui.txtLogHistory.toPlainText())
- output.write('\n')
- logger.debug('Log saved in %s' % (fileName, ))
- except IOError, e:
- logger.error("Error saving log file: %r" % (e, ))
- else:
- logger.debug('Log not saved!')
diff --git a/src/leap/gui/login.py b/src/leap/gui/login.py
deleted file mode 100644
index de0b2d50..00000000
--- a/src/leap/gui/login.py
+++ /dev/null
@@ -1,245 +0,0 @@
-# -*- coding: utf-8 -*-
-# login.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/>.
-
-"""
-Login widget implementation
-"""
-import logging
-
-from PySide import QtCore, QtGui
-from ui_login import Ui_LoginWidget
-
-from leap.util.keyring_helpers import has_keyring
-
-logger = logging.getLogger(__name__)
-
-
-class LoginWidget(QtGui.QWidget):
- """
- Login widget that emits signals to display the wizard or to
- perform login.
- """
-
- # Emitted when the login button is clicked
- login = QtCore.Signal()
- cancel_login = QtCore.Signal()
-
- # Emitted when the user selects "Other..." in the provider
- # combobox or click "Create Account"
- show_wizard = QtCore.Signal()
-
- MAX_STATUS_WIDTH = 40
-
- BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$"
-
- def __init__(self, settings, parent=None):
- """
- Constructs the LoginWidget.
-
- :param settings: client wide settings
- :type settings: LeapSettings
- :param parent: The parent widget for this widget
- :type parent: QWidget or None
- """
- QtGui.QWidget.__init__(self, parent)
-
- self._settings = settings
- self._selected_provider_index = -1
-
- self.ui = Ui_LoginWidget()
- self.ui.setupUi(self)
-
- self.ui.chkRemember.stateChanged.connect(
- self._remember_state_changed)
- self.ui.chkRemember.setEnabled(has_keyring())
-
- self.ui.lnPassword.setEchoMode(QtGui.QLineEdit.Password)
-
- self.ui.btnLogin.clicked.connect(self.login)
- self.ui.lnPassword.returnPressed.connect(self.login)
-
- self.ui.lnUser.returnPressed.connect(self._focus_password)
-
- self.ui.cmbProviders.currentIndexChanged.connect(
- self._current_provider_changed)
- self.ui.btnCreateAccount.clicked.connect(
- self.show_wizard)
-
- username_re = QtCore.QRegExp(self.BARE_USERNAME_REGEX)
- self.ui.lnUser.setValidator(
- QtGui.QRegExpValidator(username_re, self))
-
- def _remember_state_changed(self, state):
- """
- Saves the remember state in the LeapSettings
-
- :param state: possible stats can be Checked, Unchecked and
- PartiallyChecked
- :type state: QtCore.Qt.CheckState
- """
- enable = True if state == QtCore.Qt.Checked else False
- self._settings.set_remember(enable)
-
- def set_providers(self, provider_list):
- """
- Set the provider list to provider_list plus an "Other..." item
- that triggers the wizard
-
- :param provider_list: list of providers
- :type provider_list: list of str
- """
- self.ui.cmbProviders.blockSignals(True)
- self.ui.cmbProviders.clear()
- self.ui.cmbProviders.addItems(provider_list + [self.tr("Other...")])
- self.ui.cmbProviders.blockSignals(False)
-
- def select_provider_by_name(self, name):
- """
- Given a provider name/domain, it selects it in the combobox
-
- :param name: name or domain for the provider
- :type name: str
- """
- provider_index = self.ui.cmbProviders.findText(name)
- self.ui.cmbProviders.setCurrentIndex(provider_index)
-
- def get_selected_provider(self):
- """
- Returns the selected provider in the combobox
- """
- return self.ui.cmbProviders.currentText()
-
- def set_remember(self, value):
- """
- Checks the remember user and password checkbox
-
- :param value: True to mark it checked, False otherwise
- :type value: bool
- """
- self.ui.chkRemember.setChecked(value)
-
- def get_remember(self):
- """
- Returns the remember checkbox state
-
- :rtype: bool
- """
- return self.ui.chkRemember.isChecked()
-
- def set_user(self, user):
- """
- Sets the user and focuses on the next field, password.
-
- :param user: user to set the field to
- :type user: str
- """
- self.ui.lnUser.setText(user)
- self._focus_password()
-
- def get_user(self):
- """
- Returns the user that appears in the widget.
-
- :rtype: str
- """
- return self.ui.lnUser.text()
-
- def set_password(self, password):
- """
- Sets the password for the widget
-
- :param password: password to set
- :type password: str
- """
- self.ui.lnPassword.setText(password)
-
- def get_password(self):
- """
- Returns the password that appears in the widget
-
- :rtype: str
- """
- return self.ui.lnPassword.text()
-
- def set_status(self, status, error=True):
- """
- Sets the status label at the login stage to status
-
- :param status: status message
- :type status: str
- """
- if len(status) > self.MAX_STATUS_WIDTH:
- status = status[:self.MAX_STATUS_WIDTH] + "..."
- if error:
- status = "<font color='red'><b>%s</b></font>" % (status,)
- self.ui.lblStatus.setText(status)
-
- def set_enabled(self, enabled=False):
- """
- Enables or disables all the login widgets
-
- :param enabled: wether they should be enabled or not
- :type enabled: bool
- """
- self.ui.lnUser.setEnabled(enabled)
- self.ui.lnPassword.setEnabled(enabled)
- self.ui.chkRemember.setEnabled(enabled)
- self.ui.cmbProviders.setEnabled(enabled)
-
- self._set_cancel(not enabled)
-
- def _set_cancel(self, enabled=False):
- """
- Enables or disables the cancel action in the "log in" process.
-
- :param enabled: wether it should be enabled or not
- :type enabled: bool
- """
- text = self.tr("Cancel")
- login_or_cancel = self.cancel_login
-
- if not enabled:
- text = self.tr("Log In")
- login_or_cancel = self.login
-
- self.ui.btnLogin.setText(text)
-
- self.ui.btnLogin.clicked.disconnect()
- self.ui.btnLogin.clicked.connect(login_or_cancel)
-
- def _focus_password(self):
- """
- Focuses in the password lineedit
- """
- self.ui.lnPassword.setFocus()
-
- def _current_provider_changed(self, param):
- """
- SLOT
- TRIGGERS: self.ui.cmbProviders.currentIndexChanged
- """
- if param == (self.ui.cmbProviders.count() - 1):
- self.show_wizard.emit()
- # Leave the previously selected provider in the combobox
- prev_provider = 0
- if self._selected_provider_index != -1:
- prev_provider = self._selected_provider_index
- self.ui.cmbProviders.blockSignals(True)
- self.ui.cmbProviders.setCurrentIndex(prev_provider)
- self.ui.cmbProviders.blockSignals(False)
- else:
- self._selected_provider_index = param
diff --git a/src/leap/gui/mainwindow.py b/src/leap/gui/mainwindow.py
deleted file mode 100644
index 5ace1043..00000000
--- a/src/leap/gui/mainwindow.py
+++ /dev/null
@@ -1,1537 +0,0 @@
-# -*- coding: utf-8 -*-
-# mainwindow.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 window for the leap client
-"""
-import logging
-import os
-import platform
-import tempfile
-from functools import partial
-
-import keyring
-
-from PySide import QtCore, QtGui
-from twisted.internet import threads
-
-from leap.common.check import leap_assert
-from leap.common.events import register
-from leap.common.events import events_pb2 as proto
-from leap.config.leapsettings import LeapSettings
-from leap.config.providerconfig import ProviderConfig
-from leap.crypto.srpauth import SRPAuth
-from leap.gui.loggerwindow import LoggerWindow
-from leap.gui.wizard import Wizard
-from leap.gui.login import LoginWidget
-from leap.gui.statuspanel import StatusPanelWidget
-from leap.services.eip.eipbootstrapper import EIPBootstrapper
-from leap.services.eip.eipconfig import EIPConfig
-from leap.services.eip.providerbootstrapper import ProviderBootstrapper
-# XXX: Soledad might not work out of the box in Windows, issue #2932
-from leap.services.soledad.soledadbootstrapper import SoledadBootstrapper
-from leap.services.mail.smtpbootstrapper import SMTPBootstrapper
-from leap.services.mail import imap
-from leap.platform_init import IS_WIN, IS_MAC
-from leap.platform_init.initializers import init_platform
-
-from leap.services.eip.vpnprocess import VPN
-from leap.services.eip.vpnprocess import OpenVPNAlreadyRunning
-from leap.services.eip.vpnprocess import AlienOpenVPNAlreadyRunning
-
-from leap.services.eip.vpnlaunchers import VPNLauncherException
-from leap.services.eip.vpnlaunchers import OpenVPNNotFoundException
-from leap.services.eip.vpnlaunchers import EIPNoPkexecAvailable
-from leap.services.eip.vpnlaunchers import EIPNoPolkitAuthAgentAvailable
-from leap.services.eip.vpnlaunchers import EIPNoTunKextLoaded
-
-from leap.util import __version__ as VERSION
-from leap.util.keyring_helpers import has_keyring
-
-from leap.services.mail.smtpconfig import SMTPConfig
-
-if IS_WIN:
- from leap.platform_init.locks import WindowsLock
- from leap.platform_init.locks import raise_window_ack
-
-from ui_mainwindow import Ui_MainWindow
-
-logger = logging.getLogger(__name__)
-
-
-class MainWindow(QtGui.QMainWindow):
- """
- Main window for login and presenting status updates to the user
- """
-
- # StackedWidget indexes
- LOGIN_INDEX = 0
- EIP_STATUS_INDEX = 1
-
- # Keyring
- KEYRING_KEY = "bitmask"
-
- # SMTP
- PORT_KEY = "port"
- IP_KEY = "ip_address"
-
- OPENVPN_SERVICE = "openvpn"
- MX_SERVICE = "mx"
-
- # Signals
- new_updates = QtCore.Signal(object)
- raise_window = QtCore.Signal([])
- soledad_ready = QtCore.Signal([])
-
- # We use this flag to detect abnormal terminations
- user_stopped_eip = False
-
- def __init__(self, quit_callback,
- standalone=False,
- openvpn_verb=1,
- 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
- :type standalone: bool
-
- :param bypass_checks: Set to true if the app should bypass
- first round of checks for CA
- certificates at bootstrap
- :type bypass_checks: bool
- """
- QtGui.QMainWindow.__init__(self)
-
- # 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
-
- self._quit_callback = quit_callback
-
- self._updates_content = ""
-
- self.ui = Ui_MainWindow()
- self.ui.setupUi(self)
-
- self._settings = LeapSettings(standalone)
-
- self._login_widget = LoginWidget(
- self._settings,
- self.ui.stackedWidget.widget(self.LOGIN_INDEX))
- self.ui.loginLayout.addWidget(self._login_widget)
-
- # Signals
- # TODO separate logic from ui signals.
-
- self._login_widget.login.connect(self._login)
- self._login_widget.cancel_login.connect(self._cancel_login)
- self._login_widget.show_wizard.connect(
- self._launch_wizard)
-
- self.ui.btnShowLog.clicked.connect(self._show_logger_window)
-
- self._status_panel = StatusPanelWidget(
- self.ui.stackedWidget.widget(self.EIP_STATUS_INDEX))
- self.ui.statusLayout.addWidget(self._status_panel)
-
- self.ui.stackedWidget.setCurrentIndex(self.LOGIN_INDEX)
-
- self._status_panel.start_eip.connect(self._start_eip)
- self._status_panel.stop_eip.connect(self._stop_eip)
-
- # This is loaded only once, there's a bug when doing that more
- # than once
- ProviderConfig.standalone = standalone
- EIPConfig.standalone = standalone
- self._standalone = standalone
- self._provider_config = ProviderConfig()
- # Used for automatic start of EIP
- self._provisional_provider_config = ProviderConfig()
- self._eip_config = EIPConfig()
-
- self._already_started_eip = False
-
- # This is created once we have a valid provider config
- self._srp_auth = None
- self._logged_user = None
-
- # This thread is always running, although it's quite
- # lightweight when it's done setting up provider
- # configuration and certificate.
- self._provider_bootstrapper = ProviderBootstrapper(bypass_checks)
-
- # Intermediate stages, only do something if there was an error
- self._provider_bootstrapper.name_resolution.connect(
- self._intermediate_stage)
- self._provider_bootstrapper.https_connection.connect(
- self._intermediate_stage)
- self._provider_bootstrapper.download_ca_cert.connect(
- self._intermediate_stage)
-
- # Important stages, loads the provider config and checks
- # certificates
- self._provider_bootstrapper.download_provider_info.connect(
- self._load_provider_config)
- self._provider_bootstrapper.check_api_certificate.connect(
- self._provider_config_loaded)
-
- # This thread is similar to the provider bootstrapper
- self._eip_bootstrapper = EIPBootstrapper()
-
- self._eip_bootstrapper.download_config.connect(
- self._eip_intermediate_stage)
- self._eip_bootstrapper.download_client_certificate.connect(
- self._finish_eip_bootstrap)
-
- self._soledad_bootstrapper = SoledadBootstrapper()
- self._soledad_bootstrapper.download_config.connect(
- self._soledad_intermediate_stage)
- self._soledad_bootstrapper.gen_key.connect(
- self._soledad_bootstrapped_stage)
-
- self._smtp_bootstrapper = SMTPBootstrapper()
- self._smtp_bootstrapper.download_config.connect(
- self._smtp_bootstrapped_stage)
-
- self._vpn = VPN(openvpn_verb=openvpn_verb)
- self._vpn.qtsigs.state_changed.connect(
- self._status_panel.update_vpn_state)
- self._vpn.qtsigs.status_changed.connect(
- self._status_panel.update_vpn_status)
- self._vpn.qtsigs.process_finished.connect(
- self._eip_finished)
-
- self.ui.action_log_out.setEnabled(False)
- self.ui.action_log_out.triggered.connect(self._logout)
- self.ui.action_about_leap.triggered.connect(self._about)
- self.ui.action_quit.triggered.connect(self.quit)
- self.ui.action_wizard.triggered.connect(self._launch_wizard)
- self.ui.action_show_logs.triggered.connect(self._show_logger_window)
- self.raise_window.connect(self._do_raise_mainwindow)
-
- # Used to differentiate between real quits and close to tray
- self._really_quit = False
-
- self._systray = None
-
- self._action_eip_provider = QtGui.QAction(
- self.tr("No default provider"), self)
- self._action_eip_provider.setEnabled(False)
- self._action_eip_status = QtGui.QAction(
- self.tr("Encrypted internet is OFF"),
- self)
- self._action_eip_status.setEnabled(False)
-
- self._status_panel.set_action_eip_status(
- self._action_eip_status)
-
- self._action_eip_startstop = QtGui.QAction(
- self.tr("Turn OFF"), self)
- self._action_eip_startstop.triggered.connect(
- self._stop_eip)
- self._action_eip_startstop.setEnabled(False)
- self._status_panel.set_action_eip_startstop(
- self._action_eip_startstop)
-
- self._action_visible = QtGui.QAction(self.tr("Hide Main Window"), self)
- self._action_visible.triggered.connect(self._toggle_visible)
-
- self._enabled_services = []
-
- self._center_window()
-
- self.ui.lblNewUpdates.setVisible(False)
- self.ui.btnMore.setVisible(False)
- self.ui.btnMore.clicked.connect(self._updates_details)
-
- self.new_updates.connect(self._react_to_new_updates)
- self.soledad_ready.connect(self._start_imap_service)
-
- init_platform()
-
- self._wizard = None
- self._wizard_firstrun = False
-
- self._logger_window = None
-
- self._bypass_checks = bypass_checks
-
- self._soledad = None
- self._keymanager = None
- self._imap_service = None
-
- self._login_defer = None
- self._download_provider_defer = None
-
- self._smtp_config = SMTPConfig()
-
- if self._first_run():
- self._wizard_firstrun = True
- self._wizard = Wizard(standalone=standalone,
- bypass_checks=bypass_checks)
- # Give this window time to finish init and then show the wizard
- QtCore.QTimer.singleShot(1, self._launch_wizard)
- self._wizard.accepted.connect(self._finish_init)
- self._wizard.rejected.connect(self._rejected_wizard)
- else:
- self._finish_init()
-
- def _rejected_wizard(self):
- """
- SLOT
- TRIGGERS: self._wizard.rejected
-
- Called if the wizard has been cancelled or closed before
- finishing.
- """
- if self._wizard_firstrun:
- self._settings.set_properprovider(False)
- self.quit()
- else:
- self._finish_init()
-
- def _launch_wizard(self):
- """
- SLOT
- TRIGGERS:
- self._login_widget.show_wizard
- self.ui.action_wizard.triggered
-
- Also called in first run.
-
- Launches the wizard, creating the object itself if not already
- there.
- """
- if self._wizard is None:
- self._wizard = Wizard(bypass_checks=self._bypass_checks)
- self._wizard.accepted.connect(self._finish_init)
- self._wizard.rejected.connect(self._wizard.close)
-
- self.setVisible(False)
- # Do NOT use exec_, it will use a child event loop!
- # Refer to http://www.themacaque.com/?p=1067 for funny details.
- self._wizard.show()
- if IS_MAC:
- self._wizard.raise_()
- self._wizard.finished.connect(self._wizard_finished)
-
- def _wizard_finished(self):
- """
- SLOT
- TRIGGERS
- self._wizard.finished
-
- Called when the wizard has finished.
- """
- self.setVisible(True)
-
- 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
- """
- from leap.util.leap_log_handler import LeapLogHandler
- leap_logger = logging.getLogger('leap')
- for h in leap_logger.handlers:
- if isinstance(h, LeapLogHandler):
- return h
- return None
-
- def _show_logger_window(self):
- """
- SLOT
- TRIGGERS:
- self.ui.action_show_logs.triggered
- self.ui.btnShowLog.clicked
-
- Displays the window with the history of messages logged until now
- and displays the new ones on arrival.
- """
- if self._logger_window is None:
- leap_log_handler = self._get_leap_logging_handler()
- if leap_log_handler is None:
- logger.error('Leap logger handler not found')
- else:
- self._logger_window = LoggerWindow(handler=leap_log_handler)
- self._logger_window.setVisible(
- not self._logger_window.isVisible())
- self.ui.btnShowLog.setChecked(self._logger_window.isVisible())
- else:
- self._logger_window.setVisible(not self._logger_window.isVisible())
- self.ui.btnShowLog.setChecked(self._logger_window.isVisible())
-
- self._logger_window.finished.connect(self._uncheck_logger_button)
-
- def _uncheck_logger_button(self):
- """
- SLOT
- Sets the checked state of the loggerwindow button to false.
- """
- self.ui.btnShowLog.setChecked(False)
-
- def _new_updates_available(self, req):
- """
- Callback for the new updates event
-
- :param req: Request type
- :type req: leap.common.events.events_pb2.SignalRequest
- """
- self.new_updates.emit(req)
-
- def _react_to_new_updates(self, req):
- """
- SLOT
- TRIGGER: self._new_updates_available
-
- Displays the new updates label and sets the updates_content
- """
- self.moveToThread(QtCore.QCoreApplication.instance().thread())
- self.ui.lblNewUpdates.setVisible(True)
- self.ui.btnMore.setVisible(True)
- self._updates_content = req.content
-
- def _updates_details(self):
- """
- SLOT
- TRIGGER: self.ui.btnMore.clicked
-
- Parses and displays the updates details
- """
- msg = self.tr("The Bitmask app is ready to update, please"
- " restart the application.")
-
- # We assume that if there is nothing in the contents, then
- # the Bitmask bundle is what needs updating.
- if len(self._updates_content) > 0:
- files = self._updates_content.split(", ")
- files_str = ""
- for f in files:
- final_name = f.replace("/data/", "")
- final_name = final_name.replace(".thp", "")
- files_str += final_name
- files_str += "\n"
- msg += self.tr(" The following components will be updated:\n%s") \
- % (files_str,)
-
- QtGui.QMessageBox.information(self,
- self.tr("Updates available"),
- msg)
-
- def _finish_init(self):
- """
- SLOT
- TRIGGERS:
- self._wizard.accepted
-
- Also called at the end of the constructor if not first run,
- and after _rejected_wizard if not first run.
-
- Implements the behavior after either constructing the
- mainwindow object, loading the saved user/password, or after
- the wizard has been executed.
- """
- # XXX: May be this can be divided into two methods?
-
- self._login_widget.set_providers(self._configured_providers())
- self._show_systray()
- self.show()
- if IS_MAC:
- self.raise_()
-
- if self._wizard:
- possible_username = self._wizard.get_username()
- possible_password = self._wizard.get_password()
-
- # select the configured provider in the combo box
- domain = self._wizard.get_domain()
- self._login_widget.select_provider_by_name(domain)
-
- self._login_widget.set_remember(self._wizard.get_remember())
- self._enabled_services = list(self._wizard.get_services())
- self._settings.set_enabled_services(
- self._login_widget.get_selected_provider(),
- self._enabled_services)
- if possible_username is not None:
- self._login_widget.set_user(possible_username)
- if possible_password is not None:
- self._login_widget.set_password(possible_password)
- self._login()
- self._wizard = None
- self._settings.set_properprovider(True)
- else:
- self._try_autostart_eip()
- if not self._settings.get_remember():
- # nothing to do here
- return
-
- saved_user = self._settings.get_user()
-
- try:
- username, domain = saved_user.split('@')
- except (ValueError, AttributeError) as e:
- # if the saved_user does not contain an '@' or its None
- logger.error('Username@provider malformed. %r' % (e, ))
- saved_user = None
-
- if saved_user is not None and has_keyring():
- # fill the username
- self._login_widget.set_user(username)
-
- # select the configured provider in the combo box
- self._login_widget.select_provider_by_name(domain)
-
- self._login_widget.set_remember(True)
-
- saved_password = None
- try:
- saved_password = keyring.get_password(self.KEYRING_KEY,
- saved_user
- .encode("utf8"))
- except ValueError, e:
- logger.debug("Incorrect Password. %r." % (e,))
-
- if saved_password is not None:
- self._login_widget.set_password(
- saved_password.decode("utf8"))
- self._login()
-
- def _try_autostart_eip(self):
- """
- Tries to autostart EIP
- """
- default_provider = self._settings.get_defaultprovider()
-
- if default_provider is None:
- logger.info("Cannot autostart Encrypted Internet because there is "
- "no default provider configured")
- return
-
- self._action_eip_provider.setText(default_provider)
-
- self._enabled_services = self._settings.get_enabled_services(
- default_provider)
-
- if self._provisional_provider_config.load(
- os.path.join("leap",
- "providers",
- default_provider,
- "provider.json")):
- self._download_eip_config()
- else:
- # XXX: Display a proper message to the user
- logger.error("Unable to load %s config, cannot autostart." %
- (default_provider,))
-
- def _show_systray(self):
- """
- Sets up the systray icon
- """
- if self._systray is not None:
- self._systray.setVisible(True)
- return
-
- # Placeholder actions
- # They are temporary to display the tray as designed
- preferences_action = QtGui.QAction(self.tr("Preferences"), self)
- preferences_action.setEnabled(False)
- help_action = QtGui.QAction(self.tr("Help"), self)
- help_action.setEnabled(False)
-
- systrayMenu = QtGui.QMenu(self)
- systrayMenu.addAction(self._action_visible)
- systrayMenu.addSeparator()
- systrayMenu.addAction(self._action_eip_provider)
- systrayMenu.addAction(self._action_eip_status)
- systrayMenu.addAction(self._action_eip_startstop)
- systrayMenu.addSeparator()
- systrayMenu.addAction(preferences_action)
- systrayMenu.addAction(help_action)
- systrayMenu.addSeparator()
- systrayMenu.addAction(self.ui.action_log_out)
- systrayMenu.addAction(self.ui.action_quit)
- self._systray = QtGui.QSystemTrayIcon(self)
- self._systray.setContextMenu(systrayMenu)
- self._systray.setIcon(self._status_panel.ERROR_ICON_TRAY)
- self._systray.setVisible(True)
- self._systray.activated.connect(self._tray_activated)
-
- self._status_panel.set_systray(self._systray)
-
- def _tray_activated(self, reason=None):
- """
- SLOT
- TRIGGER: self._systray.activated
-
- Displays the context menu from the tray icon
- """
- self._update_hideshow_menu()
-
- context_menu = self._systray.contextMenu()
- if not IS_MAC:
- # for some reason, context_menu.show()
- # is failing in a way beyond my understanding.
- # (not working the first time it's clicked).
- # this works however.
- context_menu.exec_(self._systray.geometry().center())
-
- def _update_hideshow_menu(self):
- """
- Updates the Hide/Show main window menu text based on the
- visibility of the window.
- """
- get_action = lambda visible: (
- self.tr("Show Main Window"),
- self.tr("Hide Main Window"))[int(visible)]
-
- # set labels
- visible = self.isVisible()
- self._action_visible.setText(get_action(visible))
-
- def _toggle_visible(self):
- """
- SLOT
- TRIGGER: self._action_visible.triggered
-
- Toggles the window visibility
- """
- if not self.isVisible():
- self.show()
- self.raise_()
- else:
- self.hide()
-
- self._update_hideshow_menu()
-
- def _center_window(self):
- """
- Centers the mainwindow based on the desktop geometry
- """
- geometry = self._settings.get_geometry()
- state = self._settings.get_windowstate()
-
- if geometry is None:
- app = QtGui.QApplication.instance()
- width = app.desktop().width()
- height = app.desktop().height()
- window_width = self.size().width()
- window_height = self.size().height()
- x = (width / 2.0) - (window_width / 2.0)
- y = (height / 2.0) - (window_height / 2.0)
- self.move(x, y)
- else:
- self.restoreGeometry(geometry)
-
- if state is not None:
- self.restoreState(state)
-
- def _about(self):
- """
- SLOT
- TRIGGERS: self.ui.action_about_leap.triggered
-
- Display the About Bitmask dialog
- """
- QtGui.QMessageBox.about(
- self, self.tr("About Bitmask - %s") % (VERSION,),
- self.tr("Version: <b>%s</b><br>"
- "<br>"
- "Bitmask is the Desktop client application for "
- "the LEAP platform, supporting encrypted internet "
- "proxy, secure email, and secure chat (coming soon).<br>"
- "<br>"
- "LEAP is a non-profit dedicated to giving "
- "all internet users access to secure "
- "communication. Our focus is on adapting "
- "encryption technology to make it easy to use "
- "and widely available. <br>"
- "<br>"
- "<a href='https://leap.se'>More about LEAP"
- "</a>") % (VERSION,))
-
- def changeEvent(self, e):
- """
- Reimplements the changeEvent method to minimize to tray
- """
- if QtGui.QSystemTrayIcon.isSystemTrayAvailable() and \
- e.type() == QtCore.QEvent.WindowStateChange and \
- self.isMinimized():
- self._toggle_visible()
- e.accept()
- return
- QtGui.QMainWindow.changeEvent(self, e)
-
- def closeEvent(self, e):
- """
- Reimplementation of closeEvent to close to tray
- """
- if QtGui.QSystemTrayIcon.isSystemTrayAvailable() and \
- not self._really_quit:
- self._toggle_visible()
- e.ignore()
- return
-
- self._settings.set_geometry(self.saveGeometry())
- self._settings.set_windowstate(self.saveState())
-
- QtGui.QMainWindow.closeEvent(self, e)
-
- def _configured_providers(self):
- """
- Returns the available providers based on the file structure
-
- :rtype: list
- """
-
- # TODO: check which providers have a valid certificate among
- # other things, not just the directories
- providers = []
- try:
- providers = os.listdir(
- os.path.join(self._provider_config.get_path_prefix(),
- "leap",
- "providers"))
- except Exception as e:
- logger.debug("Error listing providers, assume there are none. %r"
- % (e,))
-
- return providers
-
- def _first_run(self):
- """
- Returns True if there are no configured providers. False otherwise
-
- :rtype: bool
- """
- has_provider_on_disk = len(self._configured_providers()) != 0
- is_proper_provider = self._settings.get_properprovider()
- return not (has_provider_on_disk and is_proper_provider)
-
- def _download_provider_config(self):
- """
- Starts the bootstrapping sequence. It will download the
- provider configuration if it's not present, otherwise will
- emit the corresponding signals inmediately
- """
- provider = self._login_widget.get_selected_provider()
-
- pb = self._provider_bootstrapper
- d = pb.run_provider_select_checks(provider, download_if_needed=True)
- self._download_provider_defer = d
-
- def _load_provider_config(self, data):
- """
- SLOT
- TRIGGER: self._provider_bootstrapper.download_provider_info
-
- Once the provider config has been downloaded, this loads the
- self._provider_config instance with it and starts the second
- part of the bootstrapping sequence
-
- :param data: result from the last stage of the
- run_provider_select_checks
- :type data: dict
- """
- if data[self._provider_bootstrapper.PASSED_KEY]:
- provider = self._login_widget.get_selected_provider()
-
- # If there's no loaded provider or
- # we want to connect to other provider...
- if (not self._provider_config.loaded() or
- self._provider_config.get_domain() != provider):
- self._provider_config.load(
- os.path.join("leap", "providers",
- provider, "provider.json"))
-
- if self._provider_config.loaded():
- self._provider_bootstrapper.run_provider_setup_checks(
- self._provider_config,
- download_if_needed=True)
- else:
- self._login_widget.set_status(
- self.tr("Unable to login: Problem with provider"))
- logger.error("Could not load provider configuration.")
- self._login_widget.set_enabled(True)
- else:
- self._login_widget.set_status(
- self.tr("Unable to login: Problem with provider"))
- logger.error(data[self._provider_bootstrapper.ERROR_KEY])
- self._login_widget.set_enabled(True)
-
- def _login(self):
- """
- SLOT
- TRIGGERS:
- self._login_widget.login
-
- Starts the login sequence. Which involves bootstrapping the
- selected provider if the selection is valid (not empty), then
- start the SRP authentication, and as the last step
- bootstrapping the EIP service
- """
- leap_assert(self._provider_config, "We need a provider config")
-
- username = self._login_widget.get_user()
- password = self._login_widget.get_password()
- provider = self._login_widget.get_selected_provider()
-
- self._enabled_services = self._settings.get_enabled_services(
- self._login_widget.get_selected_provider())
-
- if len(provider) == 0:
- self._login_widget.set_status(
- self.tr("Please select a valid provider"))
- return
-
- if len(username) == 0:
- self._login_widget.set_status(
- self.tr("Please provide a valid username"))
- return
-
- if len(password) == 0:
- self._login_widget.set_status(
- self.tr("Please provide a valid Password"))
- return
-
- self._login_widget.set_status(self.tr("Logging in..."), error=False)
- self._login_widget.set_enabled(False)
-
- if self._login_widget.get_remember() and has_keyring():
- # in the keyring and in the settings
- # we store the value 'usename@provider'
- username_domain = (username + '@' + provider).encode("utf8")
- try:
- keyring.set_password(self.KEYRING_KEY,
- username_domain,
- password.encode("utf8"))
- # Only save the username if it was saved correctly in
- # the keyring
- self._settings.set_user(username_domain)
- except Exception as e:
- logger.error("Problem saving data to keyring. %r"
- % (e,))
-
- self._download_provider_config()
-
- def _cancel_login(self):
- """
- SLOT
- TRIGGERS:
- self._login_widget.cancel_login
-
- Stops the login sequence.
- """
- logger.debug("Cancelling log in.")
-
- if self._download_provider_defer:
- logger.debug("Cancelling download provider defer.")
- self._download_provider_defer.cancel()
-
- if self._login_defer:
- logger.debug("Cancelling login defer.")
- self._login_defer.cancel()
-
- def _provider_config_loaded(self, data):
- """
- SLOT
- TRIGGER: self._provider_bootstrapper.check_api_certificate
-
- Once the provider configuration is loaded, this starts the SRP
- authentication
- """
- leap_assert(self._provider_config, "We need a provider config!")
-
- if data[self._provider_bootstrapper.PASSED_KEY]:
- username = self._login_widget.get_user().encode("utf8")
- password = self._login_widget.get_password().encode("utf8")
-
- if self._srp_auth is None:
- self._srp_auth = SRPAuth(self._provider_config)
- self._srp_auth.authentication_finished.connect(
- self._authentication_finished)
- self._srp_auth.logout_finished.connect(
- self._done_logging_out)
-
- # TODO: Add errback!
- self._login_defer = self._srp_auth.authenticate(username, password)
- else:
- self._login_widget.set_status(
- "Unable to login: Problem with provider")
- logger.error(data[self._provider_bootstrapper.ERROR_KEY])
- self._login_widget.set_enabled(True)
-
- def _authentication_finished(self, ok, message):
- """
- SLOT
- TRIGGER: self._srp_auth.authentication_finished
-
- Once the user is properly authenticated, try starting the EIP
- service
- """
-
- # In general we want to "filter" likely complicated error
- # messages, but in this case, the messages make more sense as
- # they come. Since they are "Unknown user" or "Unknown
- # password"
- self._login_widget.set_status(message, error=not ok)
-
- if ok:
- self._logged_user = self._login_widget.get_user()
- self.ui.action_log_out.setEnabled(True)
- # We leave a bit of room for the user to see the
- # "Succeeded" message and then we switch to the EIP status
- # panel
- QtCore.QTimer.singleShot(1000, self._switch_to_status)
- self._login_defer = None
- else:
- self._login_widget.set_enabled(True)
-
- def _switch_to_status(self):
- """
- Changes the stackedWidget index to the EIP status one and
- triggers the eip bootstrapping
- """
- if not self._already_started_eip:
- self._status_panel.set_provider(
- "%s@%s" % (self._login_widget.get_user(),
- self._get_best_provider_config().get_domain()))
-
- self.ui.stackedWidget.setCurrentIndex(self.EIP_STATUS_INDEX)
-
- self._soledad_bootstrapper.run_soledad_setup_checks(
- self._provider_config,
- self._login_widget.get_user(),
- self._login_widget.get_password(),
- download_if_needed=True,
- standalone=self._standalone)
-
- self._download_eip_config()
-
- def _soledad_intermediate_stage(self, data):
- """
- SLOT
- TRIGGERS:
- self._soledad_bootstrapper.download_config
-
- If there was a problem, displays it, otherwise it does nothing.
- This is used for intermediate bootstrapping stages, in case
- they fail.
- """
- passed = data[self._soledad_bootstrapper.PASSED_KEY]
- if not passed:
- # TODO: display in the GUI:
- # should pass signal to a slot in status_panel
- # that sets the global status
- logger.warning("Soledad failed to start: %s" %
- (data[self._soledad_bootstrapper.ERROR_KEY],))
-
- def _soledad_bootstrapped_stage(self, data):
- """
- SLOT
- TRIGGERS:
- self._soledad_bootstrapper.gen_key
-
- If there was a problem, displays it, otherwise it does nothing.
- This is used for intermediate bootstrapping stages, in case
- they fail.
-
- :param data: result from the bootstrapping stage for Soledad
- :type data: dict
- """
- passed = data[self._soledad_bootstrapper.PASSED_KEY]
- if not passed:
- logger.error(data[self._soledad_bootstrapper.ERROR_KEY])
- return
-
- logger.debug("Done bootstrapping Soledad")
-
- self._soledad = self._soledad_bootstrapper.soledad
- self._keymanager = self._soledad_bootstrapper.keymanager
-
- # Ok, now soledad is ready, so we can allow other things that
- # depend on soledad to start.
-
- # this will trigger start_imap_service
- self.soledad_ready.emit()
-
- # TODO connect all these activations to the soledad_ready
- # signal so the logic is clearer to follow.
-
- if self._provider_config.provides_mx() and \
- self._enabled_services.count(self.MX_SERVICE) > 0:
- self._smtp_bootstrapper.run_smtp_setup_checks(
- self._provider_config,
- self._smtp_config,
- True)
- else:
- if self._enabled_services.count(self.MX_SERVICE) > 0:
- pass # TODO: show MX status
- #self._status_panel.set_eip_status(
- # self.tr("%s does not support MX") %
- # (self._provider_config.get_domain(),),
- # error=True)
- else:
- pass # TODO: show MX status
- #self._status_panel.set_eip_status(
- # self.tr("MX is disabled"))
-
- # Service control methods: smtp
-
- def _smtp_bootstrapped_stage(self, data):
- """
- SLOT
- TRIGGERS:
- self._smtp_bootstrapper.download_config
-
- If there was a problem, displays it, otherwise it does nothing.
- This is used for intermediate bootstrapping stages, in case
- they fail.
-
- :param data: result from the bootstrapping stage for Soledad
- :type data: dict
- """
- passed = data[self._smtp_bootstrapper.PASSED_KEY]
- if not passed:
- logger.error(data[self._smtp_bootstrapper.ERROR_KEY])
- return
- logger.debug("Done bootstrapping SMTP")
-
- hosts = self._smtp_config.get_hosts()
- # TODO: handle more than one host and define how to choose
- if len(hosts) > 0:
- hostname = hosts.keys()[0]
- logger.debug("Using hostname %s for SMTP" % (hostname,))
- host = hosts[hostname][self.IP_KEY].encode("utf-8")
- port = hosts[hostname][self.PORT_KEY]
- # TODO: pick local smtp port in a better way
- # TODO: Make the encrypted_only configurable
-
- from leap.mail.smtp import setup_smtp_relay
- client_cert = self._eip_config.get_client_cert_path(
- self._provider_config)
- setup_smtp_relay(port=2013,
- keymanager=self._keymanager,
- smtp_host=host,
- smtp_port=port,
- smtp_cert=client_cert,
- smtp_key=client_cert,
- encrypted_only=False)
-
- def _start_imap_service(self):
- """
- SLOT
- TRIGGERS:
- soledad_ready
- """
- logger.debug('Starting imap service')
-
- self._imap_service = imap.start_imap_service(
- self._soledad,
- self._keymanager)
-
- def _get_socket_host(self):
- """
- Returns the socket and port to be used for VPN
-
- :rtype: tuple (str, str) (host, port)
- """
-
- # TODO: make this properly multiplatform
-
- if platform.system() == "Windows":
- host = "localhost"
- port = "9876"
- else:
- host = os.path.join(tempfile.mkdtemp(prefix="leap-tmp"),
- 'openvpn.socket')
- port = "unix"
-
- return host, port
-
- def _start_eip(self):
- """
- SLOT
- TRIGGERS:
- self._status_panel.start_eip
- self._action_eip_startstop.triggered
- or called from _finish_eip_bootstrap
-
- Starts EIP
- """
- self._status_panel.eip_pre_up()
- self.user_stopped_eip = False
- provider_config = self._get_best_provider_config()
-
- try:
- host, port = self._get_socket_host()
- self._vpn.start(eipconfig=self._eip_config,
- providerconfig=provider_config,
- socket_host=host,
- socket_port=port)
-
- self._settings.set_defaultprovider(
- provider_config.get_domain())
-
- provider = provider_config.get_domain()
- if self._logged_user is not None:
- provider = "%s@%s" % (self._logged_user, provider)
-
- self._status_panel.set_provider(provider)
-
- self._action_eip_provider.setText(provider_config.get_domain())
-
- self._status_panel.eip_started()
-
- # XXX refactor into status_panel method?
- self._action_eip_startstop.setText(self.tr("Turn OFF"))
- self._action_eip_startstop.disconnect(self)
- self._action_eip_startstop.triggered.connect(
- self._stop_eip)
- except EIPNoPolkitAuthAgentAvailable:
- self._status_panel.set_global_status(
- # XXX this should change to polkit-kde where
- # applicable.
- self.tr("We could not find any "
- "authentication "
- "agent in your system.<br/>"
- "Make sure you have "
- "<b>polkit-gnome-authentication-"
- "agent-1</b> "
- "running and try again."),
- error=True)
- self._set_eipstatus_off()
- except EIPNoTunKextLoaded:
- self._status_panel.set_global_status(
- self.tr("Encrypted Internet cannot be started because "
- "the tuntap extension is not installed properly "
- "in your system."))
- self._set_eipstatus_off()
- except EIPNoPkexecAvailable:
- self._status_panel.set_global_status(
- self.tr("We could not find <b>pkexec</b> "
- "in your system."),
- error=True)
- self._set_eipstatus_off()
- except OpenVPNNotFoundException:
- self._status_panel.set_global_status(
- self.tr("We could not find openvpn binary."),
- error=True)
- self._set_eipstatus_off()
- except OpenVPNAlreadyRunning as e:
- self._status_panel.set_global_status(
- self.tr("Another openvpn instance is already running, and "
- "could not be stopped."),
- error=True)
- self._set_eipstatus_off()
- except AlienOpenVPNAlreadyRunning as e:
- self._status_panel.set_global_status(
- self.tr("Another openvpn instance is already running, and "
- "could not be stopped because it was not launched by "
- "Bitmask. Please stop it and try again."),
- error=True)
- self._set_eipstatus_off()
- except VPNLauncherException as e:
- # XXX We should implement again translatable exceptions so
- # we can pass a translatable string to the panel (usermessage attr)
- self._status_panel.set_global_status("%s" % (e,), error=True)
- self._set_eipstatus_off()
- else:
- self._already_started_eip = True
-
- def _set_eipstatus_off(self):
- """
- Sets eip status to off
- """
- self._status_panel.set_eip_status(self.tr("OFF"), error=True)
- self._status_panel.set_eip_status_icon("error")
- self._status_panel.set_startstop_enabled(True)
- self._status_panel.eip_stopped()
-
- self._set_action_eipstart_off()
-
- def _set_action_eipstart_off(self):
- """
- Sets eip startstop action to OFF status.
- """
- self._action_eip_startstop.setText(self.tr("Turn ON"))
- self._action_eip_startstop.disconnect(self)
- self._action_eip_startstop.triggered.connect(
- self._start_eip)
-
- def _stop_eip(self, abnormal=False):
- """
- SLOT
- TRIGGERS:
- self._status_panel.stop_eip
- self._action_eip_startstop.triggered
- or called from _eip_finished
-
- Stops vpn process and makes gui adjustments to reflect
- the change of state.
-
- :param abnormal: whether this was an abnormal termination.
- :type abnormal: bool
- """
- if abnormal:
- logger.warning("Abnormal EIP termination.")
-
- self.user_stopped_eip = True
- self._vpn.terminate()
-
- self._set_eipstatus_off()
-
- self._already_started_eip = False
- self._settings.set_defaultprovider(None)
- if self._logged_user:
- self._status_panel.set_provider(
- "%s@%s" % (self._logged_user,
- self._get_best_provider_config().get_domain()))
-
- def _get_best_provider_config(self):
- """
- Returns the best ProviderConfig to use at a moment. We may
- have to use self._provider_config or
- self._provisional_provider_config depending on the start
- status.
-
- :rtype: ProviderConfig
- """
- leap_assert(self._provider_config is not None or
- self._provisional_provider_config is not None,
- "We need a provider config")
-
- provider_config = None
- if self._provider_config.loaded():
- provider_config = self._provider_config
- elif self._provisional_provider_config.loaded():
- provider_config = self._provisional_provider_config
- else:
- leap_assert(False, "We could not find any usable ProviderConfig.")
-
- return provider_config
-
- def _download_eip_config(self):
- """
- Starts the EIP bootstrapping sequence
- """
- leap_assert(self._eip_bootstrapper, "We need an eip bootstrapper!")
-
- provider_config = self._get_best_provider_config()
-
- if provider_config.provides_eip() and \
- self._enabled_services.count(self.OPENVPN_SERVICE) > 0 and \
- not self._already_started_eip:
-
- self._status_panel.set_eip_status(
- self.tr("Starting..."))
- self._eip_bootstrapper.run_eip_setup_checks(
- provider_config,
- download_if_needed=True)
- self._already_started_eip = True
- elif not self._already_started_eip:
- if self._enabled_services.count(self.OPENVPN_SERVICE) > 0:
- self._status_panel.set_eip_status(
- self.tr("Not supported"),
- error=True)
- else:
- self._status_panel.set_eip_status(self.tr("Disabled"))
- self._status_panel.set_startstop_enabled(False)
-
- def _finish_eip_bootstrap(self, data):
- """
- SLOT
- TRIGGER: self._eip_bootstrapper.download_client_certificate
-
- Starts the VPN thread if the eip configuration is properly
- loaded
- """
- leap_assert(self._eip_config, "We need an eip config!")
- passed = data[self._eip_bootstrapper.PASSED_KEY]
-
- if not passed:
- error_msg = self.tr("There was a problem with the provider")
- self._status_panel.set_eip_status(error_msg, error=True)
- logger.error(data[self._eip_bootstrapper.ERROR_KEY])
- self._already_started_eip = False
- return
-
- provider_config = self._get_best_provider_config()
-
- domain = provider_config.get_domain()
-
- loaded = self._eip_config.loaded()
- if not loaded:
- eip_config_path = os.path.join("leap", "providers",
- domain, "eip-service.json")
- api_version = provider_config.get_api_version()
- self._eip_config.set_api_version(api_version)
- loaded = self._eip_config.load(eip_config_path)
-
- if loaded:
- self._start_eip()
- else:
- self._status_panel.set_eip_status(
- self.tr("Could not load Encrypted Internet "
- "Configuration."),
- error=True)
-
- def _logout(self):
- """
- SLOT
- TRIGGER: self.ui.action_log_out.triggered
-
- Starts the logout sequence
- """
- # XXX: If other defers are doing authenticated stuff, this
- # might conflict with those. CHECK!
- threads.deferToThread(self._srp_auth.logout)
-
- def _done_logging_out(self, ok, message):
- """
- SLOT
- TRIGGER: self._srp_auth.logout_finished
-
- Switches the stackedWidget back to the login stage after
- logging out
- """
- self._logged_user = None
- self.ui.action_log_out.setEnabled(False)
- self.ui.stackedWidget.setCurrentIndex(self.LOGIN_INDEX)
- self._login_widget.set_password("")
- self._login_widget.set_enabled(True)
- self._login_widget.set_status("")
-
- def _intermediate_stage(self, data):
- """
- SLOT
- TRIGGERS:
- self._provider_bootstrapper.name_resolution
- self._provider_bootstrapper.https_connection
- self._provider_bootstrapper.download_ca_cert
- self._eip_bootstrapper.download_config
-
- If there was a problem, displays it, otherwise it does nothing.
- This is used for intermediate bootstrapping stages, in case
- they fail.
- """
- passed = data[self._provider_bootstrapper.PASSED_KEY]
- if not passed:
- self._login_widget.set_enabled(True)
- self._login_widget.set_status(
- self.tr("Unable to connect: Problem with provider"))
- logger.error(data[self._provider_bootstrapper.ERROR_KEY])
-
- def _eip_intermediate_stage(self, data):
- """
- SLOT
- TRIGGERS:
- self._eip_bootstrapper.download_config
-
- If there was a problem, displays it, otherwise it does nothing.
- This is used for intermediate bootstrapping stages, in case
- they fail.
- """
- passed = data[self._provider_bootstrapper.PASSED_KEY]
- if not passed:
- self._login_widget.set_status(
- self.tr("Unable to connect: Problem with provider"))
- logger.error(data[self._provider_bootstrapper.ERROR_KEY])
- self._already_started_eip = False
-
- def _eip_finished(self, exitCode):
- """
- SLOT
- TRIGGERS:
- self._vpn.process_finished
-
- Triggered when the EIP/VPN process finishes to set the UI
- accordingly.
- """
- logger.info("VPN process finished with exitCode %s..."
- % (exitCode,))
-
- # Ideally we would have the right exit code here,
- # but the use of different wrappers (pkexec, cocoasudo) swallows
- # the openvpn exit code so we get zero exit in some cases where we
- # shouldn't. As a workaround we just use a flag to indicate
- # a purposeful switch off, and mark everything else as unexpected.
-
- # In the near future we should trigger a native notification from here,
- # since the user really really wants to know she is unprotected asap.
- # And the right thing to do will be to fail-close.
-
- # TODO we should have a way of parsing the latest lines in the vpn
- # log buffer so we can have a more precise idea of which type
- # of error did we have (server side, local problem, etc)
- abnormal = True
-
- # XXX check if these exitCodes are pkexec/cocoasudo specific
- if exitCode in (126, 127):
- self._status_panel.set_global_status(
- self.tr("Encrypted Internet could not be launched "
- "because you did not authenticate properly."),
- error=True)
- self._vpn.killit()
- elif exitCode != 0 or not self.user_stopped_eip:
- self._status_panel.set_global_status(
- self.tr("Encrypted Internet finished in an "
- "unexpected manner!"), error=True)
- else:
- abnormal = False
- if exitCode == 0 and IS_MAC:
- # XXX remove this warning after I fix cocoasudo.
- logger.warning("The above exit code MIGHT BE WRONG.")
- self._stop_eip(abnormal)
-
- def _on_raise_window_event(self, req):
- """
- Callback for the raise window event
- """
- if IS_WIN:
- raise_window_ack()
- self.raise_window.emit()
-
- def _do_raise_mainwindow(self):
- """
- SLOT
- TRIGGERS:
- self._on_raise_window_event
-
- Triggered when we receive a RAISE_WINDOW event.
- """
- TOPFLAG = QtCore.Qt.WindowStaysOnTopHint
- self.setWindowFlags(self.windowFlags() | TOPFLAG)
- self.show()
- self.setWindowFlags(self.windowFlags() & ~TOPFLAG)
- self.show()
- if IS_MAC:
- self.raise_()
-
- def _cleanup_pidfiles(self):
- """
- Removes lockfiles on a clean shutdown.
-
- Triggered after aboutToQuit signal.
- """
- if IS_WIN:
- WindowsLock.release_all_locks()
-
- 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...')
-
- if self._imap_service is not None:
- self._imap_service.stop()
-
- if self._srp_auth is not None:
- if self._srp_auth.get_session_id() is not None or \
- self._srp_auth.get_token() is not None:
- # XXX this can timeout after loong time: See #3368
- self._srp_auth.logout()
-
- if self._soledad:
- logger.debug("Closing soledad...")
- self._soledad.close()
- else:
- logger.error("No instance of soledad was found.")
-
- logger.debug('Terminating vpn')
- self._vpn.terminate(shutdown=True)
-
- if self._login_defer:
- logger.debug("Cancelling login defer.")
- self._login_defer.cancel()
-
- if self._download_provider_defer:
- logger.debug("Cancelling download provider defer.")
- self._download_provider_defer.cancel()
-
- # TODO missing any more cancels?
-
- logger.debug('Cleaning pidfiles')
- self._cleanup_pidfiles()
-
- def quit(self):
- """
- Cleanup and tidely close the main window before quitting.
- """
- # TODO: separate the shutting down of services from the
- # UI stuff.
- self._cleanup_and_quit()
-
- self._really_quit = True
-
- if self._wizard:
- self._wizard.close()
-
- if self._logger_window:
- self._logger_window.close()
-
- self.close()
-
- if self._quit_callback:
- self._quit_callback()
-
- logger.debug('Bye.')
-
-
-if __name__ == "__main__":
- import signal
-
- def sigint_handler(*args, **kwargs):
- logger.debug('SIGINT catched. shutting down...')
- mainwindow = args[0]
- mainwindow.quit()
-
- import sys
-
- logger = logging.getLogger(name='leap')
- logger.setLevel(logging.DEBUG)
- console = logging.StreamHandler()
- console.setLevel(logging.DEBUG)
- formatter = logging.Formatter(
- '%(asctime)s '
- '- %(name)s - %(levelname)s - %(message)s')
- console.setFormatter(formatter)
- logger.addHandler(console)
-
- app = QtGui.QApplication(sys.argv)
- mainwindow = MainWindow()
- mainwindow.show()
-
- timer = QtCore.QTimer()
- timer.start(500)
- timer.timeout.connect(lambda: None)
-
- sigint = partial(sigint_handler, mainwindow)
- signal.signal(signal.SIGINT, sigint)
-
- sys.exit(app.exec_())
diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py
deleted file mode 100644
index f3424c7c..00000000
--- a/src/leap/gui/statuspanel.py
+++ /dev/null
@@ -1,459 +0,0 @@
-# -*- coding: utf-8 -*-
-# statuspanel.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/>.
-
-"""
-Status Panel widget implementation
-"""
-import logging
-
-from datetime import datetime
-from functools import partial
-from PySide import QtCore, QtGui
-
-from ui_statuspanel import Ui_StatusPanel
-
-from leap.common.check import leap_assert_type
-from leap.services.eip.vpnprocess import VPNManager
-from leap.platform_init import IS_WIN, IS_LINUX
-from leap.util import first
-
-logger = logging.getLogger(__name__)
-
-
-class RateMovingAverage(object):
- """
- Moving window average for calculating
- upload and download rates.
- """
- SAMPLE_SIZE = 5
-
- def __init__(self):
- """
- Initializes an empty array of fixed size
- """
- self.reset()
-
- def reset(self):
- self._data = [None for i in xrange(self.SAMPLE_SIZE)]
-
- def append(self, x):
- """
- Appends a new data point to the collection.
-
- :param x: A tuple containing timestamp and traffic points
- in the form (timestamp, traffic)
- :type x: tuple
- """
- self._data.pop(0)
- self._data.append(x)
-
- def get(self):
- """
- Gets the collection.
- """
- return self._data
-
- def get_average(self):
- """
- Gets the moving average.
- """
- data = filter(None, self.get())
- traff = [traffic for (ts, traffic) in data]
- times = [ts for (ts, traffic) in data]
-
- try:
- deltatraffic = traff[-1] - first(traff)
- deltat = (times[-1] - first(times)).seconds
- except IndexError:
- deltatraffic = 0
- deltat = 0
-
- try:
- rate = float(deltatraffic) / float(deltat) / 1024
- except ZeroDivisionError:
- rate = 0
-
- # In some cases we get negative rates
- if rate < 0:
- rate = 0
-
- return rate
-
- def get_total(self):
- """
- Gets the total accumulated throughput.
- """
- try:
- return self._data[-1][1] / 1024
- except TypeError:
- return 0
-
-
-class StatusPanelWidget(QtGui.QWidget):
- """
- Status widget that displays the current state of the LEAP services
- """
-
- start_eip = QtCore.Signal()
- stop_eip = QtCore.Signal()
-
- DISPLAY_TRAFFIC_RATES = True
- RATE_STR = "%14.2f KB/s"
- TOTAL_STR = "%14.2f Kb"
-
- def __init__(self, parent=None):
- QtGui.QWidget.__init__(self, parent)
-
- self._systray = None
- self._action_eip_status = None
-
- self.ui = Ui_StatusPanel()
- self.ui.setupUi(self)
-
- self.ui.btnEipStartStop.setEnabled(False)
- self.ui.btnEipStartStop.clicked.connect(
- self.start_eip)
-
- self.hide_status_box()
-
- # Set the EIP status icons
- self.CONNECTING_ICON = None
- self.CONNECTED_ICON = None
- self.ERROR_ICON = None
- self.CONNECTING_ICON_TRAY = None
- self.CONNECTED_ICON_TRAY = None
- self.ERROR_ICON_TRAY = None
- self._set_eip_icons()
-
- self._set_traffic_rates()
- self._make_status_clickable()
-
- def _make_status_clickable(self):
- """
- Makes upload and download figures clickable.
- """
- onclicked = self._on_VPN_status_clicked
- self.ui.btnUpload.clicked.connect(onclicked)
- self.ui.btnDownload.clicked.connect(onclicked)
-
- def _on_VPN_status_clicked(self):
- """
- SLOT
- TRIGGER: self.ui.btnUpload.clicked
- self.ui.btnDownload.clicked
-
- Toggles between rate and total throughput display for vpn
- status figures.
- """
- self.DISPLAY_TRAFFIC_RATES = not self.DISPLAY_TRAFFIC_RATES
- self.update_vpn_status(None) # refresh
-
- def _set_traffic_rates(self):
- """
- Initializes up and download rates.
- """
- self._up_rate = RateMovingAverage()
- self._down_rate = RateMovingAverage()
-
- self.ui.btnUpload.setText(self.RATE_STR % (0,))
- self.ui.btnDownload.setText(self.RATE_STR % (0,))
-
- def _reset_traffic_rates(self):
- """
- Resets up and download rates, and cleans up the labels.
- """
- self._up_rate.reset()
- self._down_rate.reset()
- self.update_vpn_status(None)
-
- def _update_traffic_rates(self, up, down):
- """
- Updates up and download rates.
-
- :param up: upload total.
- :type up: int
- :param down: download total.
- :type down: int
- """
- ts = datetime.now()
- self._up_rate.append((ts, up))
- self._down_rate.append((ts, down))
-
- def _get_traffic_rates(self):
- """
- Gets the traffic rates (in KB/s).
-
- :returns: a tuple with the (up, down) rates
- :rtype: tuple
- """
- up = self._up_rate
- down = self._down_rate
-
- return (up.get_average(), down.get_average())
-
- def _get_traffic_totals(self):
- """
- Gets the traffic total throughput (in Kb).
-
- :returns: a tuple with the (up, down) totals
- :rtype: tuple
- """
- up = self._up_rate
- down = self._down_rate
-
- return (up.get_total(), down.get_total())
-
- def _set_eip_icons(self):
- """
- Sets the EIP status icons for the main window and for the tray
-
- MAC : dark icons
- LINUX : dark icons in window, light icons in tray
- WIN : light icons
- """
- EIP_ICONS = EIP_ICONS_TRAY = (
- ":/images/conn_connecting-light.png",
- ":/images/conn_connected-light.png",
- ":/images/conn_error-light.png")
-
- if IS_LINUX:
- EIP_ICONS_TRAY = (
- ":/images/conn_connecting.png",
- ":/images/conn_connected.png",
- ":/images/conn_error.png")
- elif IS_WIN:
- EIP_ICONS = EIP_ICONS_TRAY = (
- ":/images/conn_connecting.png",
- ":/images/conn_connected.png",
- ":/images/conn_error.png")
-
- self.CONNECTING_ICON = QtGui.QPixmap(EIP_ICONS[0])
- self.CONNECTED_ICON = QtGui.QPixmap(EIP_ICONS[1])
- self.ERROR_ICON = QtGui.QPixmap(EIP_ICONS[2])
-
- self.CONNECTING_ICON_TRAY = QtGui.QPixmap(EIP_ICONS_TRAY[0])
- self.CONNECTED_ICON_TRAY = QtGui.QPixmap(EIP_ICONS_TRAY[1])
- self.ERROR_ICON_TRAY = QtGui.QPixmap(EIP_ICONS_TRAY[2])
-
- def set_systray(self, systray):
- """
- Sets the systray object to use.
-
- :param systray: Systray object
- :type systray: QtGui.QSystemTrayIcon
- """
- leap_assert_type(systray, QtGui.QSystemTrayIcon)
- self._systray = systray
-
- def set_action_eip_startstop(self, action_eip_startstop):
- """
- Sets the action_eip_startstop to use.
-
- :param action_eip_startstop: action_eip_status to be used
- :type action_eip_startstop: QtGui.QAction
- """
- self._action_eip_startstop = action_eip_startstop
-
- def set_action_eip_status(self, action_eip_status):
- """
- Sets the action_eip_status to use.
-
- :param action_eip_status: action_eip_status to be used
- :type action_eip_status: QtGui.QAction
- """
- leap_assert_type(action_eip_status, QtGui.QAction)
- self._action_eip_status = action_eip_status
-
- def set_global_status(self, status, error=False):
- """
- Sets the global status label.
-
- :param status: status message
- :type status: str or unicode
- :param error: if the status is an erroneous one, then set this
- to True
- :type error: bool
- """
- leap_assert_type(error, bool)
- if error:
- status = "<font color='red'><b>%s</b></font>" % (status,)
- self.ui.lblGlobalStatus.setText(status)
- self.ui.globalStatusBox.show()
-
- def hide_status_box(self):
- """
- Hide global status box.
- """
- self.ui.globalStatusBox.hide()
-
- def set_eip_status(self, status, error=False):
- """
- Sets the status label at the VPN stage to status
-
- :param status: status message
- :type status: str or unicode
- :param error: if the status is an erroneous one, then set this
- to True
- :type error: bool
- """
- leap_assert_type(error, bool)
-
- self._systray.setToolTip(status)
- if error:
- status = "<font color='red'>%s</font>" % (status,)
- self.ui.lblEIPStatus.setText(status)
-
- def set_startstop_enabled(self, value):
- """
- Enable or disable btnEipStartStop and _action_eip_startstop
- based on value
-
- :param value: True for enabled, False otherwise
- :type value: bool
- """
- leap_assert_type(value, bool)
- self.ui.btnEipStartStop.setEnabled(value)
- self._action_eip_startstop.setEnabled(value)
-
- def eip_pre_up(self):
- """
- Triggered when the app activates eip.
- Hides the status box and disables the start/stop button.
- """
- self.hide_status_box()
- self.set_startstop_enabled(False)
-
- def eip_started(self):
- """
- Sets the state of the widget to how it should look after EIP
- has started
- """
- self.ui.btnEipStartStop.setText(self.tr("Turn OFF"))
- self.ui.btnEipStartStop.disconnect(self)
- self.ui.btnEipStartStop.clicked.connect(
- self.stop_eip)
-
- def eip_stopped(self):
- """
- Sets the state of the widget to how it should look after EIP
- has stopped
- """
- self._reset_traffic_rates()
- self.ui.btnEipStartStop.setText(self.tr("Turn ON"))
- self.ui.btnEipStartStop.disconnect(self)
- self.ui.btnEipStartStop.clicked.connect(
- self.start_eip)
-
- def set_icon(self, icon):
- """
- Sets the icon to display for EIP
-
- :param icon: icon to display
- :type icon: QPixmap
- """
- self.ui.lblVPNStatusIcon.setPixmap(icon)
-
- def update_vpn_status(self, data):
- """
- SLOT
- TRIGGER: VPN.status_changed
-
- Updates the download/upload labels based on the data provided
- by the VPN thread.
-
- :param data: a dictionary with the tcp/udp write and read totals.
- If data is None, we just will refresh the display based
- on the previous data.
- :type data: dict
- """
- if data:
- upload = float(data[VPNManager.TCPUDP_WRITE_KEY] or "0")
- download = float(data[VPNManager.TCPUDP_READ_KEY] or "0")
- self._update_traffic_rates(upload, download)
-
- if self.DISPLAY_TRAFFIC_RATES:
- uprate, downrate = self._get_traffic_rates()
- upload_str = self.RATE_STR % (uprate,)
- download_str = self.RATE_STR % (downrate,)
-
- else: # display total throughput
- uptotal, downtotal = self._get_traffic_totals()
- upload_str = self.TOTAL_STR % (uptotal,)
- download_str = self.TOTAL_STR % (downtotal,)
-
- self.ui.btnUpload.setText(upload_str)
- self.ui.btnDownload.setText(download_str)
-
- def update_vpn_state(self, data):
- """
- SLOT
- TRIGGER: VPN.state_changed
-
- Updates the displayed VPN state based on the data provided by
- the VPN thread
- """
- status = data[VPNManager.STATUS_STEP_KEY]
- self.set_eip_status_icon(status)
- if status == "CONNECTED":
- self.set_eip_status(self.tr("ON"))
- # Only now we can properly enable the button.
- self.set_startstop_enabled(True)
- elif status == "AUTH":
- self.set_eip_status(self.tr("Authenticating..."))
- elif status == "GET_CONFIG":
- self.set_eip_status(self.tr("Retrieving configuration..."))
- elif status == "WAIT":
- self.set_eip_status(self.tr("Waiting to start..."))
- elif status == "ASSIGN_IP":
- self.set_eip_status(self.tr("Assigning IP"))
- elif status == "ALREADYRUNNING":
- # Put the following calls in Qt's event queue, otherwise
- # the UI won't update properly
- QtCore.QTimer.singleShot(0, self.stop_eip)
- QtCore.QTimer.singleShot(0, partial(self.set_global_status,
- self.tr("Unable to start VPN, "
- "it's already "
- "running.")))
- else:
- self.set_eip_status(status)
-
- def set_eip_status_icon(self, status):
- """
- Given a status step from the VPN thread, set the icon properly
-
- :param status: status step
- :type status: str
- """
- selected_pixmap = self.ERROR_ICON
- selected_pixmap_tray = self.ERROR_ICON_TRAY
- tray_message = self.tr("Encryption is OFF")
- if status in ("WAIT", "AUTH", "GET_CONFIG",
- "RECONNECTING", "ASSIGN_IP"):
- selected_pixmap = self.CONNECTING_ICON
- selected_pixmap_tray = self.CONNECTING_ICON_TRAY
- tray_message = self.tr("Turning ON")
- elif status in ("CONNECTED"):
- tray_message = self.tr("Encryption is ON")
- selected_pixmap = self.CONNECTED_ICON
- selected_pixmap_tray = self.CONNECTED_ICON_TRAY
-
- self.set_icon(selected_pixmap)
- self._systray.setIcon(QtGui.QIcon(selected_pixmap_tray))
- self._action_eip_status.setText(tray_message)
-
- def set_provider(self, provider):
- self.ui.lblProvider.setText(provider)
diff --git a/src/leap/gui/twisted_main.py b/src/leap/gui/twisted_main.py
deleted file mode 100644
index c7add3ee..00000000
--- a/src/leap/gui/twisted_main.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# -*- 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/gui/ui/loggerwindow.ui b/src/leap/gui/ui/loggerwindow.ui
deleted file mode 100644
index b08428a9..00000000
--- a/src/leap/gui/ui/loggerwindow.ui
+++ /dev/null
@@ -1,155 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>LoggerWindow</class>
- <widget class="QWidget" name="LoggerWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>648</width>
- <height>469</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Logs</string>
- </property>
- <property name="windowIcon">
- <iconset resource="../../../../data/resources/mainwindow.qrc">
- <normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="2" column="0" colspan="2">
- <widget class="QTextBrowser" name="txtLogHistory"/>
- </item>
- <item row="0" column="0" colspan="2">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QPushButton" name="btnDebug">
- <property name="text">
- <string>Debug</string>
- </property>
- <property name="icon">
- <iconset resource="../../../../data/resources/loggerwindow.qrc">
- <normaloff>:/images/oxygen-icons/script-error.png</normaloff>:/images/oxygen-icons/script-error.png</iconset>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnInfo">
- <property name="text">
- <string>Info</string>
- </property>
- <property name="icon">
- <iconset resource="../../../../data/resources/loggerwindow.qrc">
- <normaloff>:/images/oxygen-icons/dialog-information.png</normaloff>:/images/oxygen-icons/dialog-information.png</iconset>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnWarning">
- <property name="text">
- <string>Warning</string>
- </property>
- <property name="icon">
- <iconset resource="../../../../data/resources/loggerwindow.qrc">
- <normaloff>:/images/oxygen-icons/dialog-warning.png</normaloff>:/images/oxygen-icons/dialog-warning.png</iconset>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnError">
- <property name="text">
- <string>Error</string>
- </property>
- <property name="icon">
- <iconset resource="../../../../data/resources/loggerwindow.qrc">
- <normaloff>:/images/oxygen-icons/dialog-error.png</normaloff>:/images/oxygen-icons/dialog-error.png</iconset>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnCritical">
- <property name="text">
- <string>Critical</string>
- </property>
- <property name="icon">
- <iconset resource="../../../../data/resources/loggerwindow.qrc">
- <normaloff>:/images/oxygen-icons/edit-bomb.png</normaloff>:/images/oxygen-icons/edit-bomb.png</iconset>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnSave">
- <property name="text">
- <string>Save to file</string>
- </property>
- <property name="icon">
- <iconset resource="../../../../data/resources/loggerwindow.qrc">
- <normaloff>:/images/oxygen-icons/document-save-as.png</normaloff>:/images/oxygen-icons/document-save-as.png</iconset>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <tabstops>
- <tabstop>btnDebug</tabstop>
- <tabstop>btnInfo</tabstop>
- <tabstop>btnWarning</tabstop>
- <tabstop>btnError</tabstop>
- <tabstop>btnCritical</tabstop>
- <tabstop>btnSave</tabstop>
- <tabstop>txtLogHistory</tabstop>
- </tabstops>
- <resources>
- <include location="../../../../data/resources/loggerwindow.qrc"/>
- <include location="../../../../data/resources/mainwindow.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/src/leap/gui/ui/login.ui b/src/leap/gui/ui/login.ui
deleted file mode 100644
index 42a6897a..00000000
--- a/src/leap/gui/ui/login.ui
+++ /dev/null
@@ -1,132 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>LoginWidget</class>
- <widget class="QWidget" name="LoginWidget">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>356</width>
- <height>223</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="5" column="2">
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="1" colspan="2">
- <widget class="QComboBox" name="cmbProviders"/>
- </item>
- <item row="5" column="0">
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="6" column="1">
- <widget class="QPushButton" name="btnCreateAccount">
- <property name="text">
- <string>Create a new account</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>&lt;b&gt;Provider:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="3" column="1" colspan="2">
- <widget class="QLineEdit" name="lnPassword">
- <property name="inputMask">
- <string/>
- </property>
- </widget>
- </item>
- <item row="2" column="1" colspan="2">
- <widget class="QLineEdit" name="lnUser"/>
- </item>
- <item row="4" column="1" colspan="2">
- <widget class="QCheckBox" name="chkRemember">
- <property name="text">
- <string>Remember username and password</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>&lt;b&gt;Username:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>&lt;b&gt;Password:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QPushButton" name="btnLogin">
- <property name="text">
- <string>Log In</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0" colspan="3">
- <widget class="QLabel" name="lblStatus">
- <property name="text">
- <string/>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <tabstops>
- <tabstop>cmbProviders</tabstop>
- <tabstop>lnUser</tabstop>
- <tabstop>lnPassword</tabstop>
- <tabstop>chkRemember</tabstop>
- <tabstop>btnLogin</tabstop>
- <tabstop>btnCreateAccount</tabstop>
- </tabstops>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/leap/gui/ui/mainwindow.ui b/src/leap/gui/ui/mainwindow.ui
deleted file mode 100644
index ecd3cbe9..00000000
--- a/src/leap/gui/ui/mainwindow.ui
+++ /dev/null
@@ -1,315 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>429</width>
- <height>579</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Bitmask</string>
- </property>
- <property name="windowIcon">
- <iconset resource="../../../../data/resources/mainwindow.qrc">
- <normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset>
- </property>
- <property name="inputMethodHints">
- <set>Qt::ImhHiddenText</set>
- </property>
- <property name="iconSize">
- <size>
- <width>128</width>
- <height>128</height>
- </size>
- </property>
- <widget class="QWidget" name="centralwidget">
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="5">
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="2" column="0">
- <spacer name="horizontalSpacer_8">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="1">
- <spacer name="horizontalSpacer_7">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="lblNewUpdates">
- <property name="text">
- <string>There are new updates available, please restart.</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QPushButton" name="btnMore">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>More...</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <spacer name="horizontalSpacer_9">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="6" column="2">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="10" column="0" colspan="5">
- <widget class="QStackedWidget" name="stackedWidget">
- <property name="currentIndex">
- <number>1</number>
- </property>
- <widget class="QWidget" name="loginPage">
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="1">
- <layout class="QHBoxLayout" name="loginLayout"/>
- </item>
- <item row="0" column="2">
- <spacer name="horizontalSpacer_4">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="0">
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="page_2">
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="statusLayout"/>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item row="7" column="2">
- <widget class="QLabel" name="label">
- <property name="autoFillBackground">
- <bool>false</bool>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/mask-launcher.png</pixmap>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item row="7" column="3" colspan="2">
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="17" column="2">
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="7" column="0" colspan="2">
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="18" column="2">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <spacer name="horizontalSpacer_10">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="btnShowLog">
- <property name="text">
- <string>Show Log</string>
- </property>
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="checked">
- <bool>false</bool>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <widget class="QMenuBar" name="menubar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>429</width>
- <height>21</height>
- </rect>
- </property>
- <widget class="QMenu" name="menuSession">
- <property name="title">
- <string>&amp;Session</string>
- </property>
- <addaction name="action_log_out"/>
- <addaction name="separator"/>
- <addaction name="action_quit"/>
- </widget>
- <widget class="QMenu" name="menuHelp">
- <property name="title">
- <string>Help</string>
- </property>
- <addaction name="action_help"/>
- <addaction name="separator"/>
- <addaction name="action_about_leap"/>
- </widget>
- <addaction name="menuSession"/>
- <addaction name="menuHelp"/>
- </widget>
- <widget class="QStatusBar" name="statusbar"/>
- <action name="action_log_out">
- <property name="text">
- <string>Log &amp;out</string>
- </property>
- </action>
- <action name="action_quit">
- <property name="text">
- <string>&amp;Quit</string>
- </property>
- </action>
- <action name="action_about_leap">
- <property name="text">
- <string>About &amp;Bitmask</string>
- </property>
- </action>
- <action name="action_help">
- <property name="text">
- <string>&amp;Help</string>
- </property>
- </action>
- <action name="action_wizard">
- <property name="text">
- <string>&amp;Wizard</string>
- </property>
- </action>
- <action name="action_show_logs">
- <property name="text">
- <string>Show &amp;logs</string>
- </property>
- </action>
- </widget>
- <resources>
- <include location="../../../../data/resources/mainwindow.qrc"/>
- <include location="../../../../data/resources/locale.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/src/leap/gui/ui/statuspanel.ui b/src/leap/gui/ui/statuspanel.ui
deleted file mode 100644
index 3482ac7c..00000000
--- a/src/leap/gui/ui/statuspanel.ui
+++ /dev/null
@@ -1,289 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>StatusPanel</class>
- <widget class="QWidget" name="StatusPanel">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>384</width>
- <height>477</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Form</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QLabel" name="lblProvider">
- <property name="styleSheet">
- <string notr="true">font: bold;</string>
- </property>
- <property name="text">
- <string>user@domain.org</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QWidget" name="status_rows" native="true">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="1">
- <layout class="QHBoxLayout" name="eip_controls">
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Encrypted Internet: </string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="lblEIPStatus">
- <property name="styleSheet">
- <string notr="true">font: bold;</string>
- </property>
- <property name="text">
- <string>Off</string>
- </property>
- <property name="textFormat">
- <enum>Qt::AutoText</enum>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <property name="wordWrap">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="btnEipStartStop">
- <property name="text">
- <string>Turn On</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item row="2" column="0">
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Preferred</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>0</width>
- <height>11</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="0" rowspan="2">
- <widget class="QLabel" name="lblVPNStatusIcon">
- <property name="maximumSize">
- <size>
- <width>64</width>
- <height>64</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/icons.qrc">:/images/light/64/network-eip-down.png</pixmap>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <layout class="QHBoxLayout" name="eip_bandwidth">
- <property name="spacing">
- <number>4</number>
- </property>
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/icons.qrc">:/images/light/16/down-arrow.png</pixmap>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnDownload">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>120</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="cursor">
- <cursorShape>PointingHandCursor</cursorShape>
- </property>
- <property name="text">
- <string>0.0 KB/s</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/icons.qrc">:/images/light/16/up-arrow.png</pixmap>
- </property>
- </widget>
- </item>
- <item alignment="Qt::AlignLeft">
- <widget class="QPushButton" name="btnUpload">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>100</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>120</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="cursor">
- <cursorShape>PointingHandCursor</cursorShape>
- </property>
- <property name="text">
- <string>0.0 KB/s</string>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="3" column="0" colspan="2">
- <widget class="QGroupBox" name="globalStatusBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0">
- <widget class="QLabel" name="lblGlobalStatus">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>...</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <resources>
- <include location="../../../../data/resources/icons.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/src/leap/gui/ui/wizard.ui b/src/leap/gui/ui/wizard.ui
deleted file mode 100644
index a8f66bbc..00000000
--- a/src/leap/gui/ui/wizard.ui
+++ /dev/null
@@ -1,846 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Wizard</class>
- <widget class="QWizard" name="Wizard">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>536</width>
- <height>452</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Bitmask first run</string>
- </property>
- <property name="windowIcon">
- <iconset resource="../../../../data/resources/mainwindow.qrc">
- <normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset>
- </property>
- <property name="modal">
- <bool>true</bool>
- </property>
- <property name="wizardStyle">
- <enum>QWizard::ModernStyle</enum>
- </property>
- <property name="options">
- <set>QWizard::IndependentPages</set>
- </property>
- <widget class="QWizardPage" name="introduction_page">
- <property name="title">
- <string>Welcome</string>
- </property>
- <property name="subTitle">
- <string>This is the Bitmask first run wizard</string>
- </property>
- <attribute name="pageId">
- <string notr="true">0</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout">
- <item row="3" column="0">
- <widget class="QRadioButton" name="rdoLogin">
- <property name="text">
- <string>Log In with my credentials</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Now we will guide you through some configuration that is needed before you can connect for the first time.&lt;/p&gt;&lt;p&gt;If you ever need to modify these options again, you can find the wizard in the &lt;span style=&quot; font-style:italic;&quot;&gt;'Settings'&lt;/span&gt; menu from the main window.&lt;/p&gt;&lt;p&gt;Do you want to &lt;span style=&quot; font-weight:600;&quot;&gt;sign up&lt;/span&gt; for a new account, or &lt;span style=&quot; font-weight:600;&quot;&gt;log in&lt;/span&gt; with an already existing username?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- <property name="textFormat">
- <enum>Qt::RichText</enum>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QRadioButton" name="rdoRegister">
- <property name="text">
- <string>Sign up for a new account</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <spacer name="verticalSpacer_11">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="4" column="0">
- <spacer name="verticalSpacer_12">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <widget class="WizardPage" name="select_provider_page">
- <property name="title">
- <string>Provider selection</string>
- </property>
- <property name="subTitle">
- <string>Please enter the domain of the provider you want to use for your connection</string>
- </property>
- <attribute name="pageId">
- <string notr="true">1</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="1">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>60</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="lnProvider"/>
- </item>
- <item row="1" column="2">
- <widget class="QPushButton" name="btnCheck">
- <property name="text">
- <string>Check</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>https://</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="4" column="0" colspan="3">
- <widget class="QGroupBox" name="grpCheckProvider">
- <property name="title">
- <string>Checking for a valid provider</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="3" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>Getting provider information</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Can we stablish a secure connection?</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLabel" name="lblProviderInfo">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="lblHTTPS">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="lblNameResolution">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Can we reach this provider?</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- </item>
- <item row="2" column="1" colspan="2">
- <widget class="QLabel" name="lblProviderSelectStatus">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QWizardPage" name="provider_info_page">
- <property name="title">
- <string>Provider Information</string>
- </property>
- <property name="subTitle">
- <string>Description of services offered by this provider</string>
- </property>
- <attribute name="pageId">
- <string notr="true">2</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="1" column="0" colspan="2">
- <widget class="QLabel" name="lblProviderName">
- <property name="text">
- <string>Name</string>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <spacer name="verticalSpacer_15">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="3" column="1" colspan="2">
- <widget class="QLabel" name="lblProviderDesc">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="baseSize">
- <size>
- <width>200</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string>Desc</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="lblServ">
- <property name="text">
- <string>&lt;b&gt;Services offered:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QLabel" name="lblServicesOffered">
- <property name="text">
- <string>services</string>
- </property>
- </widget>
- </item>
- <item row="4" column="2">
- <spacer name="horizontalSpacer_6">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="5" column="0">
- <widget class="QLabel" name="label_12">
- <property name="text">
- <string>&lt;b&gt;Enrollment policy:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QLabel" name="lblProviderPolicy">
- <property name="text">
- <string>policy</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <spacer name="verticalSpacer_5">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>&lt;b&gt;URL:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="2" column="1" colspan="2">
- <widget class="QLabel" name="lblProviderURL">
- <property name="text">
- <string>URL</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>&lt;b&gt;Description:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="WizardPage" name="setup_provider_page">
- <property name="title">
- <string>Provider setup</string>
- </property>
- <property name="subTitle">
- <string>Gathering configuration options for this provider</string>
- </property>
- <attribute name="pageId">
- <string notr="true">3</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <spacer name="verticalSpacer_3">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>60</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QLabel" name="lblSetupProviderExpl">
- <property name="text">
- <string>We are downloading some bits that we need to establish a secure connection with the provider for the first time.</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_6">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_2">
- <property name="title">
- <string>Setting up provider</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_6">
- <item row="2" column="1">
- <widget class="QLabel" name="lblCheckCaFpr">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="lblDownloadCaCert">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_9">
- <property name="text">
- <string>Getting info from the Certificate Authority</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_10">
- <property name="text">
- <string>Do we trust this Certificate Authority?</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_11">
- <property name="text">
- <string>Establishing a trust relationship with this provider</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLabel" name="lblCheckApiCert">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>24</width>
- <height>24</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_8">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <widget class="WizardPage" name="register_user_page">
- <property name="title">
- <string>Register new user</string>
- </property>
- <property name="subTitle">
- <string>Register a new user with provider</string>
- </property>
- <attribute name="pageId">
- <string notr="true">4</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_7">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <property name="leftMargin">
- <number>4</number>
- </property>
- <item row="3" column="0">
- <widget class="QLabel" name="label_16">
- <property name="text">
- <string>&lt;b&gt;Password:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="3" column="1" colspan="2">
- <widget class="QLineEdit" name="lblPassword"/>
- </item>
- <item row="4" column="1" colspan="2">
- <widget class="QLineEdit" name="lblPassword2"/>
- </item>
- <item row="2" column="1" colspan="2">
- <widget class="QLineEdit" name="lblUser"/>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_17">
- <property name="text">
- <string>&lt;b&gt;Re-enter password:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QPushButton" name="btnRegister">
- <property name="text">
- <string>Register</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <spacer name="verticalSpacer_4">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>60</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="7" column="1">
- <spacer name="verticalSpacer_7">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_15">
- <property name="text">
- <string>&lt;b&gt;Username:&lt;/b&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item row="5" column="1" colspan="2">
- <widget class="QCheckBox" name="chkRemember">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Remember my username and password</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1" colspan="2">
- <widget class="QLabel" name="lblRegisterStatus">
- <property name="text">
- <string/>
- </property>
- <property name="textFormat">
- <enum>Qt::AutoText</enum>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QWizardPage" name="service_selection">
- <property name="title">
- <string>Service selection</string>
- </property>
- <property name="subTitle">
- <string>Please select the services you would like to have</string>
- </property>
- <attribute name="pageId">
- <string notr="true">5</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_8">
- <item row="0" column="0">
- <widget class="QGroupBox" name="grpServices">
- <property name="title">
- <string notr="true">Services by PROVIDER</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_9">
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="serviceListLayout"/>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QWizardPage" name="finish_page">
- <property name="title">
- <string>Congratulations!</string>
- </property>
- <property name="subTitle">
- <string>You have successfully configured Bitmask.</string>
- </property>
- <attribute name="pageId">
- <string notr="true">6</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_10">
- <item row="1" column="0">
- <spacer name="horizontalSpacer_4">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="1">
- <spacer name="verticalSpacer_9">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="label_23">
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/leap-color-big.png</pixmap>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QLabel" name="label_25">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Globe.png</pixmap>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <spacer name="verticalSpacer_10">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="3">
- <spacer name="horizontalSpacer_5">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- </widget>
- <customwidgets>
- <customwidget>
- <class>WizardPage</class>
- <extends>QWizardPage</extends>
- <header>wizardpage.h</header>
- <container>1</container>
- </customwidget>
- </customwidgets>
- <tabstops>
- <tabstop>lblUser</tabstop>
- <tabstop>lblPassword</tabstop>
- <tabstop>lblPassword2</tabstop>
- <tabstop>btnRegister</tabstop>
- <tabstop>rdoRegister</tabstop>
- <tabstop>rdoLogin</tabstop>
- <tabstop>lnProvider</tabstop>
- <tabstop>btnCheck</tabstop>
- </tabstops>
- <resources>
- <include location="../../../../data/resources/mainwindow.qrc"/>
- <include location="../../../../data/resources/locale.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/src/leap/gui/wizard.py b/src/leap/gui/wizard.py
deleted file mode 100644
index 2b48fc81..00000000
--- a/src/leap/gui/wizard.py
+++ /dev/null
@@ -1,626 +0,0 @@
-# -*- coding: utf-8 -*-
-# wizard.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/>.
-
-"""
-First run wizard
-"""
-import os
-import logging
-import json
-
-from PySide import QtCore, QtGui
-from functools import partial
-from twisted.internet import threads
-
-from ui_wizard import Ui_Wizard
-from leap.config.providerconfig import ProviderConfig
-from leap.crypto.srpregister import SRPRegister
-from leap.util.privilege_policies import is_missing_policy_permissions
-from leap.util.request_helpers import get_content
-from leap.util.keyring_helpers import has_keyring
-from leap.services.eip.providerbootstrapper import ProviderBootstrapper
-from leap.services import get_supported
-
-logger = logging.getLogger(__name__)
-
-
-class Wizard(QtGui.QWizard):
- """
- First run wizard to register a user and setup a provider
- """
-
- INTRO_PAGE = 0
- SELECT_PROVIDER_PAGE = 1
- PRESENT_PROVIDER_PAGE = 2
- SETUP_PROVIDER_PAGE = 3
- REGISTER_USER_PAGE = 4
- SERVICES_PAGE = 5
- FINISH_PAGE = 6
-
- WEAK_PASSWORDS = ("123456", "qweasd", "qwerty",
- "password")
-
- BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$"
-
- def __init__(self, standalone=False, bypass_checks=False):
- """
- Constructor for the main Wizard.
-
- :param standalone: If True, the application is running as standalone
- and the wizard should display some messages according to this.
- :type standalone: bool
- :param bypass_checks: Set to true if the app should bypass
- first round of checks for CA certificates at bootstrap
- :type bypass_checks: bool
- """
- QtGui.QWizard.__init__(self)
-
- self.standalone = standalone
-
- self.ui = Ui_Wizard()
- self.ui.setupUi(self)
-
- self.setPixmap(QtGui.QWizard.LogoPixmap,
- QtGui.QPixmap(":/images/leap-color-small.png"))
-
- self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png")
- self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png")
- self.OK_ICON = QtGui.QPixmap(":/images/Dialog-accept.png")
-
- # Correspondence for services and their name to display
- EIP_LABEL = self.tr("Encrypted Internet")
- MX_LABEL = self.tr("Encrypted Mail")
-
- if self._is_need_eip_password_warning():
- EIP_LABEL += " " + self.tr(
- "(will need admin password to start)")
-
- self.SERVICE_DISPLAY = [
- EIP_LABEL,
- MX_LABEL
- ]
- self.SERVICE_CONFIG = [
- "openvpn",
- "mx"
- ]
-
- self._selected_services = set()
- self._shown_services = set()
-
- self._show_register = False
-
- self.ui.grpCheckProvider.setVisible(False)
- self.ui.btnCheck.clicked.connect(self._check_provider)
- self.ui.lnProvider.returnPressed.connect(self._check_provider)
-
- self._provider_bootstrapper = ProviderBootstrapper(bypass_checks)
- self._provider_bootstrapper.name_resolution.connect(
- self._name_resolution)
- self._provider_bootstrapper.https_connection.connect(
- self._https_connection)
- self._provider_bootstrapper.download_provider_info.connect(
- self._download_provider_info)
-
- self._provider_bootstrapper.download_ca_cert.connect(
- self._download_ca_cert)
- self._provider_bootstrapper.check_ca_fingerprint.connect(
- self._check_ca_fingerprint)
- self._provider_bootstrapper.check_api_certificate.connect(
- self._check_api_certificate)
-
- self._domain = None
- self._provider_config = ProviderConfig()
-
- # We will store a reference to the defers for eventual use
- # (eg, to cancel them) but not doing anything with them right now.
- self._provider_select_defer = None
- self._provider_setup_defer = None
-
- self.currentIdChanged.connect(self._current_id_changed)
-
- self.ui.lblPassword.setEchoMode(QtGui.QLineEdit.Password)
- self.ui.lblPassword2.setEchoMode(QtGui.QLineEdit.Password)
-
- self.ui.lnProvider.textChanged.connect(
- self._enable_check)
-
- self.ui.lblUser.returnPressed.connect(
- self._focus_password)
- self.ui.lblPassword.returnPressed.connect(
- self._focus_second_password)
- self.ui.lblPassword2.returnPressed.connect(
- self._register)
- self.ui.btnRegister.clicked.connect(
- self._register)
-
- usernameRe = QtCore.QRegExp(self.BARE_USERNAME_REGEX)
- self.ui.lblUser.setValidator(
- QtGui.QRegExpValidator(usernameRe, self))
-
- self.page(self.REGISTER_USER_PAGE).setCommitPage(True)
-
- self._username = None
- self._password = None
-
- self.page(self.REGISTER_USER_PAGE).setButtonText(
- QtGui.QWizard.CommitButton, self.tr("&Next >"))
- self.page(self.FINISH_PAGE).setButtonText(
- QtGui.QWizard.FinishButton, self.tr("Connect"))
-
- # XXX: Temporary removal for enrollment policy
- # https://leap.se/code/issues/2922
- self.ui.label_12.setVisible(False)
- self.ui.lblProviderPolicy.setVisible(False)
-
- def get_domain(self):
- return self._domain
-
- def get_username(self):
- return self._username
-
- def get_password(self):
- return self._password
-
- def get_remember(self):
- return has_keyring() and self.ui.chkRemember.isChecked()
-
- def get_services(self):
- return self._selected_services
-
- def _enable_check(self, text):
- self.ui.btnCheck.setEnabled(len(self.ui.lnProvider.text()) != 0)
- self._reset_provider_check()
-
- def _focus_password(self):
- """
- Focuses at the password lineedit for the registration page
- """
- self.ui.lblPassword.setFocus()
-
- def _focus_second_password(self):
- """
- Focuses at the second password lineedit for the registration page
- """
- self.ui.lblPassword2.setFocus()
-
- def _basic_password_checks(self, username, password, password2):
- """
- Performs basic password checks to avoid really easy passwords.
-
- :param username: username provided at the registrarion form
- :type username: str
- :param password: password from the registration form
- :type password: str
- :param password2: second password from the registration form
- :type password: str
-
- :return: returns True if all the checks pass, False otherwise
- :rtype: bool
- """
- message = None
-
- if message is None and password != password2:
- message = self.tr("Passwords don't match")
-
- if message is None and len(password) < 6:
- message = self.tr("Password too short")
-
- if message is None and password in self.WEAK_PASSWORDS:
- message = self.tr("Password too easy")
-
- if message is None and username == password:
- message = self.tr("Password equal to username")
-
- if message is not None:
- self._set_register_status(message, error=True)
- self._focus_password()
- return False
-
- return True
-
- def _register(self):
- """
- Performs the registration based on the values provided in the form
- """
- self.ui.btnRegister.setEnabled(False)
-
- username = self.ui.lblUser.text()
- password = self.ui.lblPassword.text()
- password2 = self.ui.lblPassword2.text()
-
- if self._basic_password_checks(username, password, password2):
- register = SRPRegister(provider_config=self._provider_config)
- register.registration_finished.connect(
- self._registration_finished)
-
- threads.deferToThread(
- partial(register.register_user,
- username.encode("utf8"),
- password.encode("utf8")))
-
- self._username = username
- self._password = password
- self._set_register_status(self.tr("Starting registration..."))
- else:
- self.ui.btnRegister.setEnabled(True)
-
- def _set_registration_fields_visibility(self, visible):
- """
- This method hides the username and password labels and inputboxes.
-
- :param visible: sets the visibility of the widgets
- True: widgets are visible or False: are not
- :type visible: bool
- """
- # username and password inputs
- self.ui.lblUser.setVisible(visible)
- self.ui.lblPassword.setVisible(visible)
- self.ui.lblPassword2.setVisible(visible)
-
- # username and password labels
- self.ui.label_15.setVisible(visible)
- self.ui.label_16.setVisible(visible)
- self.ui.label_17.setVisible(visible)
-
- # register button
- self.ui.btnRegister.setVisible(visible)
-
- def _registration_finished(self, ok, req):
- if ok:
- user_domain = self._username + "@" + self._domain
- message = "<font color='green'><h3>"
- message += self.tr("User %s successfully registered.") % (
- user_domain, )
- message += "</h3></font>"
- self._set_register_status(message)
-
- self.ui.lblPassword2.clearFocus()
- self._set_registration_fields_visibility(False)
-
- # Allow the user to remember his password
- if has_keyring():
- self.ui.chkRemember.setVisible(True)
- self.ui.chkRemember.setEnabled(True)
-
- self.page(self.REGISTER_USER_PAGE).set_completed()
- self.button(QtGui.QWizard.BackButton).setEnabled(False)
- else:
- old_username = self._username
- self._username = None
- self._password = None
- error_msg = self.tr("Unknown error")
- try:
- content, _ = get_content(req)
- json_content = json.loads(content)
- error_msg = json_content.get("errors").get("login")[0]
- if not error_msg.istitle():
- error_msg = "%s %s" % (old_username, error_msg)
- except Exception as e:
- logger.error("Unknown error: %r" % (e,))
-
- self._set_register_status(error_msg, error=True)
- self.ui.btnRegister.setEnabled(True)
-
- def _set_register_status(self, status, error=False):
- """
- Sets the status label in the registration page to status
-
- :param status: status message to display, can be HTML
- :type status: str
- """
- if error:
- status = "<font color='red'><b>%s</b></font>" % (status,)
- self.ui.lblRegisterStatus.setText(status)
-
- def _reset_provider_check(self):
- """
- Resets the UI for checking a provider. Also resets the domain
- in this object.
- """
- self.ui.lblNameResolution.setPixmap(None)
- self.ui.lblHTTPS.setPixmap(None)
- self.ui.lblProviderInfo.setPixmap(None)
- self.ui.lblProviderSelectStatus.setText("")
- self._domain = None
- self.button(QtGui.QWizard.NextButton).setEnabled(False)
- self.page(self.SELECT_PROVIDER_PAGE).set_completed(False)
-
- def _reset_provider_setup(self):
- """
- Resets the UI for setting up a provider.
- """
- self.ui.lblDownloadCaCert.setPixmap(None)
- self.ui.lblCheckCaFpr.setPixmap(None)
- self.ui.lblCheckApiCert.setPixmap(None)
-
- def _check_provider(self):
- """
- SLOT
- TRIGGERS:
- self.ui.btnCheck.clicked
- self.ui.lnProvider.returnPressed
-
- Starts the checks for a given provider
- """
- if len(self.ui.lnProvider.text()) == 0:
- return
-
- self.ui.grpCheckProvider.setVisible(True)
- self.ui.btnCheck.setEnabled(False)
- self.ui.lnProvider.setEnabled(False)
- self.button(QtGui.QWizard.BackButton).clearFocus()
- self._domain = self.ui.lnProvider.text()
-
- self.ui.lblNameResolution.setPixmap(self.QUESTION_ICON)
- self._provider_select_defer = self._provider_bootstrapper.\
- run_provider_select_checks(self._domain)
-
- def _complete_task(self, data, label, complete=False, complete_page=-1):
- """
- Checks a task and completes a page if specified
-
- :param data: data as it comes from the bootstrapper thread for
- a specific check
- :type data: dict
- :param label: label that displays the status icon for a
- specific check that corresponds to the data
- :type label: QtGui.QLabel
- :param complete: if True, it completes the page specified,
- which must be of type WizardPage
- :type complete: bool
- :param complete_page: page id to complete
- :type complete_page: int
- """
- passed = data[self._provider_bootstrapper.PASSED_KEY]
- error = data[self._provider_bootstrapper.ERROR_KEY]
- if passed:
- label.setPixmap(self.OK_ICON)
- if complete:
- self.page(complete_page).set_completed()
- self.button(QtGui.QWizard.NextButton).setFocus()
- else:
- label.setPixmap(self.ERROR_ICON)
- logger.error(error)
-
- def _name_resolution(self, data):
- """
- SLOT
- TRIGGER: self._provider_bootstrapper.name_resolution
-
- Sets the status for the name resolution check
- """
- self._complete_task(data, self.ui.lblNameResolution)
- status = ""
- passed = data[self._provider_bootstrapper.PASSED_KEY]
- if not passed:
- status = self.tr("<font color='red'><b>Non-existent "
- "provider</b></font>")
- else:
- self.ui.lblHTTPS.setPixmap(self.QUESTION_ICON)
- self.ui.lblProviderSelectStatus.setText(status)
- self.ui.btnCheck.setEnabled(not passed)
- self.ui.lnProvider.setEnabled(not passed)
-
- def _https_connection(self, data):
- """
- SLOT
- TRIGGER: self._provider_bootstrapper.https_connection
-
- Sets the status for the https connection check
- """
- self._complete_task(data, self.ui.lblHTTPS)
- status = ""
- passed = data[self._provider_bootstrapper.PASSED_KEY]
- if not passed:
- status = self.tr("<font color='red'><b>%s</b></font>") \
- % (data[self._provider_bootstrapper.ERROR_KEY])
- self.ui.lblProviderSelectStatus.setText(status)
- else:
- self.ui.lblProviderInfo.setPixmap(self.QUESTION_ICON)
- self.ui.btnCheck.setEnabled(not passed)
- self.ui.lnProvider.setEnabled(not passed)
-
- def _download_provider_info(self, data):
- """
- SLOT
- TRIGGER: self._provider_bootstrapper.download_provider_info
-
- Sets the status for the provider information download
- check. Since this check is the last of this set, it also
- completes the page if passed
- """
- if self._provider_config.load(os.path.join("leap",
- "providers",
- self._domain,
- "provider.json")):
- self._complete_task(data, self.ui.lblProviderInfo,
- True, self.SELECT_PROVIDER_PAGE)
- else:
- new_data = {
- self._provider_bootstrapper.PASSED_KEY: False,
- self._provider_bootstrapper.ERROR_KEY:
- self.tr("Unable to load provider configuration")
- }
- self._complete_task(new_data, self.ui.lblProviderInfo)
-
- status = ""
- if not data[self._provider_bootstrapper.PASSED_KEY]:
- status = self.tr("<font color='red'><b>Not a valid provider"
- "</b></font>")
- self.ui.lblProviderSelectStatus.setText(status)
- self.ui.btnCheck.setEnabled(True)
- self.ui.lnProvider.setEnabled(True)
-
- def _download_ca_cert(self, data):
- """
- SLOT
- TRIGGER: self._provider_bootstrapper.download_ca_cert
-
- Sets the status for the download of the CA certificate check
- """
- self._complete_task(data, self.ui.lblDownloadCaCert)
- passed = data[self._provider_bootstrapper.PASSED_KEY]
- if passed:
- self.ui.lblCheckCaFpr.setPixmap(self.QUESTION_ICON)
-
- def _check_ca_fingerprint(self, data):
- """
- SLOT
- TRIGGER: self._provider_bootstrapper.check_ca_fingerprint
-
- Sets the status for the CA fingerprint check
- """
- self._complete_task(data, self.ui.lblCheckCaFpr)
- passed = data[self._provider_bootstrapper.PASSED_KEY]
- if passed:
- self.ui.lblCheckApiCert.setPixmap(self.QUESTION_ICON)
-
- def _check_api_certificate(self, data):
- """
- SLOT
- TRIGGER: self._provider_bootstrapper.check_api_certificate
-
- Sets the status for the API certificate check. Also finishes
- the provider bootstrapper thread since it's not needed anymore
- from this point on, unless the whole check chain is restarted
- """
- self._complete_task(data, self.ui.lblCheckApiCert,
- True, self.SETUP_PROVIDER_PAGE)
-
- def _service_selection_changed(self, service, state):
- """
- SLOT
- TRIGGER: service_checkbox.stateChanged
- Adds the service to the state if the state is checked, removes
- it otherwise
-
- :param service: service to handle
- :type service: str
- :param state: state of the checkbox
- :type state: int
- """
- if state == QtCore.Qt.Checked:
- self._selected_services = \
- self._selected_services.union(set([service]))
- else:
- self._selected_services = \
- self._selected_services.difference(set([service]))
-
- def _populate_services(self):
- """
- Loads the services that the provider provides into the UI for
- the user to enable or disable.
- """
- self.ui.grpServices.setTitle(
- self.tr("Services by %s") %
- (self._provider_config.get_name(),))
-
- services = get_supported(
- self._provider_config.get_services())
-
- for service in services:
- try:
- if service not in self._shown_services:
- checkbox = QtGui.QCheckBox(self)
- service_index = self.SERVICE_CONFIG.index(service)
- checkbox.setText(self.SERVICE_DISPLAY[service_index])
- self.ui.serviceListLayout.addWidget(checkbox)
- checkbox.stateChanged.connect(
- partial(self._service_selection_changed, service))
- checkbox.setChecked(True)
- self._shown_services.add(service)
- except ValueError:
- logger.error(
- self.tr("Something went wrong while trying to "
- "load service %s" % (service,)))
-
- def _current_id_changed(self, pageId):
- """
- SLOT
- TRIGGER: self.currentIdChanged
-
- Prepares the pages when they appear
- """
- if pageId == self.SELECT_PROVIDER_PAGE:
- self._reset_provider_check()
- self._enable_check("")
-
- if pageId == self.SETUP_PROVIDER_PAGE:
- self._reset_provider_setup()
- self.page(pageId).setSubTitle(self.tr("Gathering configuration "
- "options for %s") %
- (self._provider_config
- .get_name(),))
- self.ui.lblDownloadCaCert.setPixmap(self.QUESTION_ICON)
- self._provider_setup_defer = self._provider_bootstrapper.\
- run_provider_setup_checks(self._provider_config)
-
- if pageId == self.PRESENT_PROVIDER_PAGE:
- self.page(pageId).setSubTitle(self.tr("Description of services "
- "offered by %s") %
- (self._provider_config
- .get_name(),))
-
- lang = QtCore.QLocale.system().name()
- self.ui.lblProviderName.setText(
- "<b>%s</b>" %
- (self._provider_config.get_name(lang=lang),))
- self.ui.lblProviderURL.setText(
- "https://%s" % (self._provider_config.get_domain(),))
- self.ui.lblProviderDesc.setText(
- "<i>%s</i>" %
- (self._provider_config.get_description(lang=lang),))
-
- self.ui.lblServicesOffered.setText(self._provider_config
- .get_services_string())
- self.ui.lblProviderPolicy.setText(self._provider_config
- .get_enrollment_policy())
-
- if pageId == self.REGISTER_USER_PAGE:
- self.page(pageId).setSubTitle(self.tr("Register a new user with "
- "%s") %
- (self._provider_config
- .get_name(),))
- self.ui.chkRemember.setVisible(False)
-
- if pageId == self.SERVICES_PAGE:
- self._populate_services()
-
- def _is_need_eip_password_warning(self):
- """
- Returns True if we need to add a warning about eip needing
- administrative permissions to start. That can be either
- because we are running in standalone mode, or because we could
- not find the needed privilege escalation mechanisms being operative.
- """
- return self.standalone or is_missing_policy_permissions()
-
- def nextId(self):
- """
- Sets the next page id for the wizard based on wether the user
- wants to register a new identity or uses an existing one
- """
- if self.currentPage() == self.page(self.INTRO_PAGE):
- self._show_register = self.ui.rdoRegister.isChecked()
-
- if self.currentPage() == self.page(self.SETUP_PROVIDER_PAGE):
- if self._show_register:
- return self.REGISTER_USER_PAGE
- else:
- return self.SERVICES_PAGE
-
- return QtGui.QWizard.nextId(self)
diff --git a/src/leap/gui/wizardpage.py b/src/leap/gui/wizardpage.py
deleted file mode 100644
index b2a00028..00000000
--- a/src/leap/gui/wizardpage.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-# wizardpage.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/>.
-
-from PySide import QtGui
-
-
-class WizardPage(QtGui.QWizardPage):
- """
- Simple wizard page helper
- """
-
- def __init__(self):
- QtGui.QWizardPage.__init__(self)
- self._completed = False
-
- def set_completed(self, val=True):
- self._completed = val
- if val:
- self.completeChanged.emit()
-
- def isComplete(self):
- return self._completed
-
- def cleanupPage(self):
- self._completed = False
- QtGui.QWizardPage.cleanupPage(self)