summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2014-09-03 15:50:08 -0700
committerelijah <elijah@riseup.net>2014-09-19 14:23:14 -0700
commitc7304e54e40cd9151e6d00a8441aaf48b68c9bcc (patch)
tree7b35347e71be860fa9ed44cdac25d32453c380c2
parentdb044d01432e8c78fcd266308aec0edbee990ab3 (diff)
single pref win: move eip preferences to new combined preference window.
-rw-r--r--Makefile16
-rw-r--r--data/resources/flags.qrc1
-rw-r--r--src/leap/bitmask/gui/mainwindow.py38
-rw-r--r--src/leap/bitmask/gui/preferences_account_page.py165
-rw-r--r--src/leap/bitmask/gui/preferences_email_page.py38
-rw-r--r--src/leap/bitmask/gui/preferences_vpn_page.py150
-rw-r--r--src/leap/bitmask/gui/preferenceswindow.py419
-rw-r--r--src/leap/bitmask/gui/ui/eippreferences.ui102
-rw-r--r--src/leap/bitmask/gui/ui/mainwindow.ui8
-rw-r--r--src/leap/bitmask/gui/ui/preferences.ui234
-rw-r--r--src/leap/bitmask/gui/ui/preferences_account_page.ui95
-rw-r--r--src/leap/bitmask/gui/ui/preferences_email_page.ui32
-rw-r--r--src/leap/bitmask/gui/ui/preferences_vpn_page.ui89
-rw-r--r--src/leap/bitmask/services/eip/eipconfig.py43
14 files changed, 760 insertions, 670 deletions
diff --git a/Makefile b/Makefile
index bbeebc36..e7173c80 100644
--- a/Makefile
+++ b/Makefile
@@ -19,9 +19,19 @@ TRANSLAT_DIR = data/translations
#Project file, used for translations
PROJFILE = data/bitmask.pro
-#UI files to compile
-UI_FILES = loggerwindow.ui mainwindow.ui wizard.ui login.ui preferences.ui eip_status.ui mail_status.ui eippreferences.ui advanced_key_management.ui
-#Qt resource files to compile
+# UI files to compile
+UI_FILES = \
+ loggerwindow.ui \
+ wizard.ui \
+ mainwindow.ui login.ui eip_status.ui mail_status.ui \
+ preferences.ui \
+ preferences_account_page.ui \
+ preferences_vpn_page.ui \
+ preferences_email_page.ui \
+ password_change.ui \
+ advanced_key_management.ui
+
+# Qt resource files to compile
RESOURCES = icons.qrc flags.qrc locale.qrc loggerwindow.qrc
#pyuic4 and pyrcc4 binaries
diff --git a/data/resources/flags.qrc b/data/resources/flags.qrc
index 8bdc9c4c..aeecc54f 100644
--- a/data/resources/flags.qrc
+++ b/data/resources/flags.qrc
@@ -58,6 +58,7 @@
<file>../images/countries/us.png</file>
<file>../images/countries/ve.png</file>
<file>../images/countries/vn.png</file>
+ <file>../images/countries/xx.png</file>
<file>../images/countries/za.png</file>
</qresource>
</RCC> \ No newline at end of file
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 916e7c1f..243fe117 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -37,7 +37,6 @@ from leap.bitmask.config import flags
from leap.bitmask.config.leapsettings import LeapSettings
from leap.bitmask.gui.advanced_key_management import AdvancedKeyManagement
-from leap.bitmask.gui.eip_preferenceswindow import EIPPreferencesWindow
from leap.bitmask.gui.eip_status import EIPStatusWidget
from leap.bitmask.gui.loggerwindow import LoggerWindow
from leap.bitmask.gui.login import LoginWidget
@@ -97,6 +96,9 @@ class MainWindow(QtGui.QMainWindow):
# We give the services some time to a halt before forcing quit.
SERVICES_STOP_TIMEOUT = 3000 # in milliseconds
+ # Preferences window
+ preferences = None
+
def __init__(self, start_hidden=False, backend_pid=None):
"""
Constructor for the client main window
@@ -213,8 +215,6 @@ class MainWindow(QtGui.QMainWindow):
self._backend_connect()
self.ui.action_preferences.triggered.connect(self._show_preferences)
- self.ui.action_eip_preferences.triggered.connect(
- self._show_eip_preferences)
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)
@@ -247,7 +247,6 @@ class MainWindow(QtGui.QMainWindow):
# disable buttons for now, may come back later.
# self.ui.btnPreferences.clicked.connect(self._show_preferences)
- # self.ui.btnEIPPreferences.clicked.connect(self._show_eip_preferences)
self._enabled_services = []
self._ui_mx_visible = True
@@ -601,16 +600,13 @@ class MainWindow(QtGui.QMainWindow):
"""
user = self._logged_user
domain = self._providers.get_selected_provider()
- mx_provided = False
- if self._provider_details is not None:
- mx_provided = MX_SERVICE in self._provider_details['services']
- preferences = PreferencesWindow(self, user, domain, self._backend,
- self._soledad_started, mx_provided,
- self._leap_signaler)
-
- self.soledad_ready.connect(preferences.set_soledad_ready)
- preferences.show()
- preferences.preferences_saved.connect(self._update_eip_enabled_status)
+ if self.preferences is not None:
+ self.preferences.close()
+ self.preferences = PreferencesWindow(self, user, domain,
+ self._backend,
+ self._soledad_started,
+ self._leap_signaler)
+ self.preferences.show()
@QtCore.Slot()
def _update_eip_enabled_status(self):
@@ -718,20 +714,6 @@ class MainWindow(QtGui.QMainWindow):
"""
self._eip_status.missing_helpers = True
- @QtCore.Slot()
- def _show_eip_preferences(self):
- """
- TRIGGERS:
- self.ui.btnEIPPreferences.clicked
- self.ui.action_eip_preferences (disabled for now)
-
- Display the EIP preferences window.
- """
- domain = self._providers.get_selected_provider()
- pref = EIPPreferencesWindow(self, domain,
- self._backend, self._leap_signaler)
- pref.show()
-
#
# updates
#
diff --git a/src/leap/bitmask/gui/preferences_account_page.py b/src/leap/bitmask/gui/preferences_account_page.py
new file mode 100644
index 00000000..9cc94482
--- /dev/null
+++ b/src/leap/bitmask/gui/preferences_account_page.py
@@ -0,0 +1,165 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2014 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/>.
+"""
+Widget for "account" preferences
+"""
+import logging
+
+from functools import partial
+
+from PySide import QtCore, QtGui
+from ui_preferences_account_page import Ui_PreferencesAccountPage
+
+logger = logging.getLogger(__name__)
+
+class PreferencesAccountPage(QtGui.QWidget):
+ """
+
+ """
+
+ def __init__(self, parent):
+ """
+ """
+ QtGui.QWidget.__init__(self, parent)
+ self.ui = Ui_PreferencesAccountPage()
+ self.ui.setupUi(self)
+ self.show()
+
+ self._selected_services = set()
+ #self._leap_signaler.prov_get_supported_services.connect(self._load_services)
+
+ @QtCore.Slot()
+ def set_soledad_ready(self):
+ """
+ TRIGGERS:
+ parent.soledad_ready
+
+ It notifies when the soledad object as ready to use.
+ """
+ #self.ui.lblPasswordChangeStatus.setVisible(False)
+ #self.ui.gbPasswordChange.setEnabled(True)
+
+ @QtCore.Slot(str, int)
+ def _service_selection_changed(self, service, state):
+ """
+ TRIGGERS:
+ 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]))
+
+ # We hide the maybe-visible status label after a change
+ self.ui.lblProvidersServicesStatus.setVisible(False)
+
+ @QtCore.Slot(str)
+ def _populate_services(self, domain):
+ """
+ TRIGGERS:
+ self.ui.cbProvidersServices.currentIndexChanged[unicode]
+
+ Fill the services list with the selected provider's services.
+
+ :param domain: the domain of the provider to load services from.
+ :type domain: str
+ """
+ # We hide the maybe-visible status label after a change
+ self.ui.lblProvidersServicesStatus.setVisible(False)
+
+ if not domain:
+ return
+
+ # set the proper connection for the 'save' button
+ try:
+ self.ui.pbSaveServices.clicked.disconnect()
+ except RuntimeError:
+ pass # Signal was not connected
+
+ save_services = partial(self._save_enabled_services, domain)
+ self.ui.pbSaveServices.clicked.connect(save_services)
+
+ self._backend.provider_get_supported_services(domain=domain)
+
+ @QtCore.Slot(str)
+ def _load_services(self, services):
+ """
+ TRIGGERS:
+ self.ui.cbProvidersServices.currentIndexChanged[unicode]
+
+ Loads the services that the provider provides into the UI for
+ the user to enable or disable.
+
+ :param domain: the domain of the provider to load services from.
+ :type domain: str
+ """
+ domain = self.ui.cbProvidersServices.currentText()
+ services_conf = self._settings.get_enabled_services(domain)
+
+ # discard changes if other provider is selected
+ self._selected_services = set()
+
+ # from: http://stackoverflow.com/a/13103617/687989
+ # remove existing checkboxes
+ layout = self.ui.vlServices
+ for i in reversed(range(layout.count())):
+ layout.itemAt(i).widget().setParent(None)
+
+ # add one checkbox per service and set the current configured value
+ for service in services:
+ try:
+ checkbox = QtGui.QCheckBox(self)
+ service_label = get_service_display_name(service)
+ checkbox.setText(service_label)
+
+ self.ui.vlServices.addWidget(checkbox)
+ checkbox.stateChanged.connect(
+ partial(self._service_selection_changed, service))
+
+ checkbox.setChecked(service in services_conf)
+ except ValueError:
+ logger.error("Something went wrong while trying to "
+ "load service %s" % (service,))
+
+ @QtCore.Slot(str)
+ def _save_enabled_services(self, provider):
+ """
+ TRIGGERS:
+ self.ui.pbSaveServices.clicked
+
+ Saves the new enabled services settings to the configuration file.
+
+ :param provider: the provider config that we need to save.
+ :type provider: str
+ """
+ services = list(self._selected_services)
+ self._settings.set_enabled_services(provider, services)
+
+ msg = self.tr(
+ "Services settings for provider '{0}' saved.".format(provider))
+ logger.debug(msg)
+ self._set_providers_services_status(msg, success=True)
+ self.preferences_saved.emit()
diff --git a/src/leap/bitmask/gui/preferences_email_page.py b/src/leap/bitmask/gui/preferences_email_page.py
new file mode 100644
index 00000000..08ff5463
--- /dev/null
+++ b/src/leap/bitmask/gui/preferences_email_page.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2014 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/>.
+"""
+Widget for "email" preferences
+"""
+import logging
+
+from PySide import QtCore, QtGui
+from ui_preferences_email_page import Ui_PreferencesEmailPage
+
+logger = logging.getLogger(__name__)
+
+class PreferencesEmailPage(QtGui.QWidget):
+ """
+
+ """
+
+ def __init__(self, parent):
+ """
+ """
+ QtGui.QWidget.__init__(self, parent)
+ self.ui = Ui_PreferencesEmailPage()
+ self.ui.setupUi(self)
+ self.show()
+
diff --git a/src/leap/bitmask/gui/preferences_vpn_page.py b/src/leap/bitmask/gui/preferences_vpn_page.py
new file mode 100644
index 00000000..ba1366e4
--- /dev/null
+++ b/src/leap/bitmask/gui/preferences_vpn_page.py
@@ -0,0 +1,150 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2014 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/>.
+"""
+Widget for "vpn" preferences
+"""
+
+from PySide import QtCore, QtGui
+from ui_preferences_vpn_page import Ui_PreferencesVpnPage
+
+from leap.bitmask.config.leapsettings import LeapSettings
+
+
+class PreferencesVpnPage(QtGui.QWidget):
+ """
+ Page in the preferences window that shows VPN settings
+ """
+
+ def __init__(self, parent, domain, backend, leap_signaler):
+ """
+ :param parent: parent object of the EIPPreferencesWindow.
+ :type parent: QWidget
+
+ :param domain: the selected by default domain.
+ :type domain: unicode
+
+ :param backend: Backend being used
+ :type backend: Backend
+ """
+ QtGui.QWidget.__init__(self, parent)
+ self.AUTOMATIC_GATEWAY_LABEL = self.tr("Automatic")
+
+ self._settings = LeapSettings()
+ self._leap_signaler = leap_signaler
+ self._backend = backend
+
+ # Load UI
+ self.ui = Ui_PreferencesVpnPage()
+ self.ui.setupUi(self)
+ self.ui.flash_label.setVisible(False)
+
+ # Connections
+ self.ui.gateways_list.clicked.connect(self._save_selected_gateway)
+
+ self._domain = domain
+ self._backend_connect()
+ self._backend.eip_get_gateways_list(domain=domain)
+
+ def _flash_error(self, message):
+ """
+ Sets string for the flash message.
+
+ :param message: the text to be displayed
+ :type message: str
+ """
+ message = "<font color='red'><b>%s</b></font>" % (message,)
+ self.ui.flash_label.setVisible(True)
+ self.ui.flash_label.setText(message)
+
+ # def _flash_success(self, message):
+ # """
+ # Sets string for the flash message.
+ #
+ # :param message: the text to be displayed
+ # :type message: str
+ # """
+ # message = "<font color='green'><b>%s</b></font>" % (message,)
+ # self.ui.flash_label.setVisible(True)
+ # self.ui.flash_label.setText(message)
+
+ @QtCore.Slot(str)
+ def _save_selected_gateway(self, index):
+ """
+ TRIGGERS:
+ self.ui.gateways_list.clicked
+
+ Saves the new gateway setting to the configuration file.
+
+ :param index: the current index of the selection.
+ :type current_item: QModelIndex
+ """
+ item = self.ui.gateways_list.currentItem()
+
+ if item.text() == self.AUTOMATIC_GATEWAY_LABEL:
+ gateway = self._settings.GATEWAY_AUTOMATIC
+ else:
+ gateway = item.data(QtCore.Qt.UserRole)
+ self._settings.set_selected_gateway(self._domain, gateway)
+ self._backend.settings_set_selected_gateway(provider=self._domain,
+ gateway=gateway)
+
+ @QtCore.Slot(list)
+ def _update_gateways_list(self, gateways):
+ """
+ TRIGGERS:
+ Signaler.eip_get_gateways_list
+
+ :param gateways: a list of gateways
+ :type gateways: list of unicode
+
+ Add the available gateways and select the one stored in
+ configuration file.
+ """
+ self.ui.gateways_list.clear()
+ self.ui.gateways_list.addItem(self.AUTOMATIC_GATEWAY_LABEL)
+
+ selected_gateway = self._settings.get_selected_gateway(
+ self._domain)
+
+ index = 0
+ for idx, (gw_name, gw_ip, gw_country) in enumerate(gateways):
+ gateway_text = "{0} ({1})".format(gw_name, gw_ip)
+ item = QtGui.QListWidgetItem(self.ui.gateways_list)
+ item.setText(gateway_text)
+ item.setIcon(QtGui.QIcon(
+ ":/images/countries/%s.png" % (gw_country.lower(),)))
+ item.setData(QtCore.Qt.UserRole, gw_ip)
+ if gw_ip == selected_gateway:
+ index = idx + 1
+ self.ui.gateways_list.setCurrentRow(index)
+
+ @QtCore.Slot()
+ def _gateways_list_error(self):
+ """
+ TRIGGERS:
+ Signaler.eip_get_gateways_list_error
+
+ An error has occurred retrieving the gateway list
+ so we inform the user.
+ """
+ self._flash_error(
+ self.tr("Error loading configuration file."))
+ self.ui.gateways_list.setEnabled(False)
+
+ def _backend_connect(self):
+ sig = self._leap_signaler
+ sig.eip_get_gateways_list.connect(self._update_gateways_list)
+ sig.eip_get_gateways_list_error.connect(self._gateways_list_error)
diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py
index 3c9cd5d0..a9c301c4 100644
--- a/src/leap/bitmask/gui/preferenceswindow.py
+++ b/src/leap/bitmask/gui/preferenceswindow.py
@@ -20,13 +20,16 @@ Preferences window
"""
import logging
-from functools import partial
-
from PySide import QtCore, QtGui
from leap.bitmask.config.leapsettings import LeapSettings
+
from leap.bitmask.gui.ui_preferences import Ui_Preferences
-from leap.bitmask.util.credentials import password_checks
+
+from leap.bitmask.gui.preferences_account_page import PreferencesAccountPage
+from leap.bitmask.gui.preferences_vpn_page import PreferencesVpnPage
+from leap.bitmask.gui.preferences_email_page import PreferencesEmailPage
+
from leap.bitmask.services import get_service_display_name, MX_SERVICE
logger = logging.getLogger(__name__)
@@ -38,8 +41,7 @@ class PreferencesWindow(QtGui.QDialog):
"""
preferences_saved = QtCore.Signal()
- def __init__(self, parent, username, domain, backend, soledad_started, mx,
- leap_signaler):
+ def __init__(self, parent, username, domain, backend, soledad_started, leap_signaler):
"""
:param parent: parent object of the PreferencesWindow.
:parent type: QWidget
@@ -51,397 +53,94 @@ class PreferencesWindow(QtGui.QDialog):
:type backend: Backend
:param soledad_started: whether soledad has started or not
:type soledad_started: bool
- :param mx: whether the current provider provides mx or not.
- :type mx: bool
+ :param leap_signaler: signal server
+ :type leap_signaler: LeapSignaler
"""
QtGui.QDialog.__init__(self, parent)
- self.AUTOMATIC_GATEWAY_LABEL = self.tr("Automatic")
+ self._parent = parent
self._username = username
self._domain = domain
self._leap_signaler = leap_signaler
self._backend = backend
self._soledad_started = soledad_started
- self._mx_provided = mx
self._settings = LeapSettings()
- self._backend_connect()
# Load UI
self.ui = Ui_Preferences()
self.ui.setupUi(self)
- self.ui.lblPasswordChangeStatus.setVisible(False)
- self.ui.lblProvidersServicesStatus.setVisible(False)
-
- self._selected_services = set()
-
- # Connections
- self.ui.pbChangePassword.clicked.connect(self._change_password)
- self.ui.cbProvidersServices.currentIndexChanged[unicode].connect(
- self._populate_services)
-
- if not self._settings.get_configured_providers():
- self.ui.gbEnabledServices.setEnabled(False)
- else:
- self._add_configured_providers()
- if self._username is None:
- self._not_logged_in()
- else:
- self.ui.gbPasswordChange.setEnabled(True)
- if self._mx_provided:
- self._provides_mx()
+ self.ui.close_button.clicked.connect(self.close)
- self._select_provider_by_name(domain)
+ self._add_icons()
+ self._add_pages()
- def _not_logged_in(self):
+ def _add_icons(self):
"""
- Actions to perform if the user is not logged in.
- """
- msg = self.tr(
- "In order to change your password you need to be logged in.")
- self._set_password_change_status(msg)
- self.ui.gbPasswordChange.setEnabled(False)
+ Adds all the icons for the different configuration categories.
+ Icons are QListWidgetItems added to the nav_widget on the side
+ of the preferences window.
- def _provides_mx(self):
- """
- Actions to perform if the provider provides MX.
+ A note on sizing of QListWidgetItems
+ icon_width = list_widget.width - (2 x nav_widget.spacing) - 2
+ icon_height = 56 seems to look ok
"""
- pw_enabled = True
- enabled_services = self._settings.get_enabled_services(self._domain)
- mx_name = get_service_display_name(MX_SERVICE)
+ account_button = QtGui.QListWidgetItem(self.ui.nav_widget)
+ account_button.setIcon(QtGui.QIcon(":/images/black/32/user.png"))
+ account_button.setText(self.tr("Account"))
+ account_button.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
+ account_button.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
+ account_button.setSizeHint(QtCore.QSize(98,56))
- if MX_SERVICE not in enabled_services:
- msg = self.tr("You need to enable {0} in order to change "
- "the password.".format(mx_name))
- self._set_password_change_status(msg, error=True)
- pw_enabled = False
- else:
- # check if Soledad is bootstrapped
- if not self._soledad_started:
- msg = self.tr(
- "You need to wait until {0} is ready in "
- "order to change the password.".format(mx_name))
- self._set_password_change_status(msg)
- pw_enabled = False
+ vpn_button = QtGui.QListWidgetItem(self.ui.nav_widget)
+ vpn_button.setIcon(QtGui.QIcon(":/images/black/32/earth.png"))
+ vpn_button.setText(self.tr("VPN"))
+ vpn_button.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
+ vpn_button.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
+ vpn_button.setSizeHint(QtCore.QSize(98,56))
- self.ui.gbPasswordChange.setEnabled(pw_enabled)
+ email_button = QtGui.QListWidgetItem(self.ui.nav_widget)
+ email_button.setIcon(QtGui.QIcon(":/images/black/32/email.png"))
+ email_button.setText(self.tr("Email"))
+ email_button.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
+ email_button.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
+ email_button.setSizeHint(QtCore.QSize(98,56))
- @QtCore.Slot()
- def set_soledad_ready(self):
- """
- TRIGGERS:
- parent.soledad_ready
+ self.ui.nav_widget.currentItemChanged.connect(self._change_page)
+ self.ui.nav_widget.setCurrentRow(0)
- It notifies when the soledad object as ready to use.
+ def _add_pages(self):
"""
- self.ui.lblPasswordChangeStatus.setVisible(False)
- self.ui.gbPasswordChange.setEnabled(True)
-
- def _set_password_change_status(self, status, error=False, success=False):
+ Adds the pages for the different configuration categories.
"""
- Sets the status label for the password change.
+ self.ui.pages_widget.addWidget(PreferencesAccountPage(self))
+ self.ui.pages_widget.addWidget(PreferencesVpnPage(self, self._domain, self._backend, self._leap_signaler))
+ self.ui.pages_widget.addWidget(PreferencesEmailPage(self))
- :param status: status message to display, can be HTML
- :type status: str
- """
- if error:
- status = "<font color='red'><b>%s</b></font>" % (status,)
- elif success:
- status = "<font color='green'><b>%s</b></font>" % (status,)
-
- if not self.ui.gbPasswordChange.isEnabled():
- status = "<font color='black'>%s</font>" % (status,)
-
- self.ui.lblPasswordChangeStatus.setVisible(True)
- self.ui.lblPasswordChangeStatus.setText(status)
-
- def _set_changing_password(self, disable):
- """
- Enables or disables the widgets in the password change group box.
-
- :param disable: True if the widgets should be disabled and
- it displays the status label that shows that is
- changing the password.
- False if they should be enabled.
- :type disable: bool
- """
- if disable:
- self._set_password_change_status(self.tr("Changing password..."))
-
- self.ui.leCurrentPassword.setEnabled(not disable)
- self.ui.leNewPassword.setEnabled(not disable)
- self.ui.leNewPassword2.setEnabled(not disable)
- self.ui.pbChangePassword.setEnabled(not disable)
+ #
+ # Slots
+ #
@QtCore.Slot()
- def _change_password(self):
+ def close(self):
"""
TRIGGERS:
- self.ui.pbChangePassword.clicked
+ self.ui.close_button.clicked
- Changes the user's password if the inputboxes are correctly filled.
+ Close this dialog
"""
- username = self._username
- current_password = self.ui.leCurrentPassword.text()
- new_password = self.ui.leNewPassword.text()
- new_password2 = self.ui.leNewPassword2.text()
-
- ok, msg = password_checks(username, new_password, new_password2)
-
- if not ok:
- self._set_changing_password(False)
- self._set_password_change_status(msg, error=True)
- self.ui.leNewPassword.setFocus()
- return
-
- self._set_changing_password(True)
- self._backend.user_change_password(current_password=current_password,
- new_password=new_password)
+ self._parent.preferences = None
+ self.hide()
@QtCore.Slot()
- def _srp_change_password_ok(self):
- """
- TRIGGERS:
- self._backend.signaler.srp_password_change_ok
-
- Callback used to display a successfully changed password.
- """
- new_password = self.ui.leNewPassword.text()
- logger.debug("SRP password changed successfully.")
-
- if self._mx_provided:
- self._backend.soledad_change_password(new_password=new_password)
- else:
- self._change_password_success()
-
- @QtCore.Slot(unicode)
- def _srp_change_password_problem(self, msg):
- """
- TRIGGERS:
- self._backend.signaler.srp_password_change_error
- self._backend.signaler.srp_password_change_badpw
-
- Callback used to display an error on changing password.
-
- :param msg: the message to show to the user.
- :type msg: unicode
- """
- logger.error("Error changing password")
- self._set_password_change_status(msg, error=True)
- self._set_changing_password(False)
-
- @QtCore.Slot()
- def _soledad_change_password_ok(self):
- """
- TRIGGERS:
- Signaler.soledad_password_change_ok
-
- Soledad password change went OK.
- """
- logger.debug("Soledad password changed successfully.")
- self._change_password_success()
-
- def _change_password_success(self):
- """
- Callback used to display a successfully changed password.
- """
- logger.debug("Soledad password changed successfully.")
-
- self._set_password_change_status(
- self.tr("Password changed successfully."), success=True)
- self._clear_password_inputs()
- self._set_changing_password(False)
-
- @QtCore.Slot(unicode)
- def _soledad_change_password_problem(self, msg):
- """
- TRIGGERS:
- Signaler.soledad_password_change_error
-
- Callback used to display an error on changing password.
-
- :param msg: the message to show to the user.
- :type msg: unicode
- """
- logger.error("Error changing soledad password")
- self._set_password_change_status(msg, error=True)
- self._set_changing_password(False)
-
- def _clear_password_inputs(self):
- """
- Clear the contents of the inputs.
- """
- self.ui.leCurrentPassword.setText("")
- self.ui.leNewPassword.setText("")
- self.ui.leNewPassword2.setText("")
-
- def _set_providers_services_status(self, status, success=False):
- """
- Sets the status label for the password change.
-
- :param status: status message to display, can be HTML
- :type status: str
- :param success: is set to True if we should display the
- message as green
- :type success: bool
- """
- if success:
- status = "<font color='green'><b>%s</b></font>" % (status,)
-
- self.ui.lblProvidersServicesStatus.setVisible(True)
- self.ui.lblProvidersServicesStatus.setText(status)
-
- def _add_configured_providers(self):
- """
- Add the client's configured providers to the providers combo boxes.
- """
- self.ui.cbProvidersServices.clear()
- for provider in self._settings.get_configured_providers():
- self.ui.cbProvidersServices.addItem(provider)
-
- def _select_provider_by_name(self, name):
- """
- Given a provider name/domain, selects it in the combobox.
-
- :param name: name or domain for the provider
- :type name: str
- """
- provider_index = self.ui.cbProvidersServices.findText(name)
- self.ui.cbProvidersServices.setCurrentIndex(provider_index)
-
- @QtCore.Slot(str, int)
- def _service_selection_changed(self, service, state):
+ def _change_page(self, current, previous):
"""
TRIGGERS:
- service_checkbox.stateChanged
+ self.ui.nav_widget.currentItemChanged
- 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]))
-
- # We hide the maybe-visible status label after a change
- self.ui.lblProvidersServicesStatus.setVisible(False)
-
- @QtCore.Slot(str)
- def _populate_services(self, domain):
+ Changes what page is displayed.
"""
- TRIGGERS:
- self.ui.cbProvidersServices.currentIndexChanged[unicode]
-
- Fill the services list with the selected provider's services.
-
- :param domain: the domain of the provider to load services from.
- :type domain: str
- """
- # We hide the maybe-visible status label after a change
- self.ui.lblProvidersServicesStatus.setVisible(False)
-
- if not domain:
- return
-
- # set the proper connection for the 'save' button
- try:
- self.ui.pbSaveServices.clicked.disconnect()
- except RuntimeError:
- pass # Signal was not connected
-
- save_services = partial(self._save_enabled_services, domain)
- self.ui.pbSaveServices.clicked.connect(save_services)
-
- self._backend.provider_get_supported_services(domain=domain)
-
- @QtCore.Slot(str)
- def _load_services(self, services):
- """
- TRIGGERS:
- self.ui.cbProvidersServices.currentIndexChanged[unicode]
-
- Loads the services that the provider provides into the UI for
- the user to enable or disable.
-
- :param domain: the domain of the provider to load services from.
- :type domain: str
- """
- domain = self.ui.cbProvidersServices.currentText()
- services_conf = self._settings.get_enabled_services(domain)
-
- # discard changes if other provider is selected
- self._selected_services = set()
-
- # from: http://stackoverflow.com/a/13103617/687989
- # remove existing checkboxes
- layout = self.ui.vlServices
- for i in reversed(range(layout.count())):
- layout.itemAt(i).widget().setParent(None)
-
- # add one checkbox per service and set the current configured value
- for service in services:
- try:
- checkbox = QtGui.QCheckBox(self)
- service_label = get_service_display_name(service)
- checkbox.setText(service_label)
-
- self.ui.vlServices.addWidget(checkbox)
- checkbox.stateChanged.connect(
- partial(self._service_selection_changed, service))
-
- checkbox.setChecked(service in services_conf)
- except ValueError:
- logger.error("Something went wrong while trying to "
- "load service %s" % (service,))
-
- @QtCore.Slot(str)
- def _save_enabled_services(self, provider):
- """
- TRIGGERS:
- self.ui.pbSaveServices.clicked
-
- Saves the new enabled services settings to the configuration file.
-
- :param provider: the provider config that we need to save.
- :type provider: str
- """
- services = list(self._selected_services)
- self._settings.set_enabled_services(provider, services)
-
- msg = self.tr(
- "Services settings for provider '{0}' saved.".format(provider))
- logger.debug(msg)
- self._set_providers_services_status(msg, success=True)
- self.preferences_saved.emit()
-
- def _backend_connect(self):
- """
- Helper to connect to backend signals
- """
- sig = self._leap_signaler
-
- sig.prov_get_supported_services.connect(self._load_services)
-
- sig.srp_password_change_ok.connect(self._srp_change_password_ok)
-
- pwd_change_error = lambda: self._srp_change_password_problem(
- self.tr("There was a problem changing the password."))
- sig.srp_password_change_error.connect(pwd_change_error)
-
- pwd_change_badpw = lambda: self._srp_change_password_problem(
- self.tr("You did not enter a correct current password."))
- sig.srp_password_change_badpw.connect(pwd_change_badpw)
-
- sig.soledad_password_change_ok.connect(
- self._soledad_change_password_ok)
-
- sig.soledad_password_change_error.connect(
- self._soledad_change_password_problem)
+ if not current:
+ current = previous
+ self.ui.pages_widget.setCurrentIndex(self.ui.nav_widget.row(current))
diff --git a/src/leap/bitmask/gui/ui/eippreferences.ui b/src/leap/bitmask/gui/ui/eippreferences.ui
deleted file mode 100644
index 1a5fcd24..00000000
--- a/src/leap/bitmask/gui/ui/eippreferences.ui
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>EIPPreferences</class>
- <widget class="QDialog" name="EIPPreferences">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>435</width>
- <height>144</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Encrypted Internet Preferences</string>
- </property>
- <property name="windowIcon">
- <iconset resource="../../../../../data/resources/icons.qrc">
- <normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset>
- </property>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0">
- <widget class="QGroupBox" name="gbGatewaySelector">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="title">
- <string>Select gateway for provider</string>
- </property>
- <property name="checkable">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="lblSelectProvider">
- <property name="text">
- <string>Select &amp;provider:</string>
- </property>
- <property name="buddy">
- <cstring>cbProvidersGateway</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="1" colspan="2">
- <widget class="QComboBox" name="cbProvidersGateway">
- <item>
- <property name="text">
- <string>&lt;Select provider&gt;</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="7" column="2">
- <widget class="QPushButton" name="pbSaveGateway">
- <property name="text">
- <string>&amp;Save this provider settings</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0" colspan="3">
- <widget class="QLabel" name="lblProvidersGatewayStatus">
- <property name="text">
- <string>&lt; Providers Gateway Status &gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Select &amp;gateway:</string>
- </property>
- <property name="buddy">
- <cstring>cbGateways</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="1" colspan="2">
- <widget class="QComboBox" name="cbGateways">
- <item>
- <property name="text">
- <string>Automatic</string>
- </property>
- </item>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- <tabstops>
- <tabstop>cbProvidersGateway</tabstop>
- <tabstop>cbGateways</tabstop>
- <tabstop>pbSaveGateway</tabstop>
- </tabstops>
- <resources>
- <include location="../../../../../data/resources/icons.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui
index f7570ee6..2e8aea8c 100644
--- a/src/leap/bitmask/gui/ui/mainwindow.ui
+++ b/src/leap/bitmask/gui/ui/mainwindow.ui
@@ -317,7 +317,6 @@
<addaction name="action_advanced_key_management"/>
<addaction name="separator"/>
<addaction name="action_preferences"/>
- <addaction name="action_eip_preferences"/>
<addaction name="separator"/>
<addaction name="action_quit"/>
</widget>
@@ -338,12 +337,7 @@
<bool>true</bool>
</property>
<property name="text">
- <string>Account Preferences...</string>
- </property>
- </action>
- <action name="action_eip_preferences">
- <property name="text">
- <string>Internet Preferences...</string>
+ <string>Preferences...</string>
</property>
</action>
<action name="action_quit">
diff --git a/src/leap/bitmask/gui/ui/preferences.ui b/src/leap/bitmask/gui/ui/preferences.ui
index cd4d3a77..5e30ea57 100644
--- a/src/leap/bitmask/gui/ui/preferences.ui
+++ b/src/leap/bitmask/gui/ui/preferences.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>503</width>
- <height>401</height>
+ <width>520</width>
+ <height>439</height>
</rect>
</property>
<property name="windowTitle">
@@ -17,159 +17,97 @@
<iconset resource="../../../../../data/resources/icons.qrc">
<normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset>
</property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="4" column="0">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1,0">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="account_label">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
</property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
+ <property name="text">
+ <string>user@example.org</string>
</property>
- </spacer>
+ </widget>
</item>
- <item row="0" column="0">
- <widget class="QGroupBox" name="gbPasswordChange">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="title">
- <string>Password Change</string>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::ExpandingFieldsGrow</enum>
- </property>
- <item row="0" column="0">
- <widget class="QLabel" name="lblCurrentPassword">
- <property name="text">
- <string>&amp;Current password:</string>
- </property>
- <property name="buddy">
- <cstring>leCurrentPassword</cstring>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="leCurrentPassword">
- <property name="echoMode">
- <enum>QLineEdit::Password</enum>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="lblNewPassword">
- <property name="text">
- <string>&amp;New password:</string>
- </property>
- <property name="buddy">
- <cstring>leNewPassword</cstring>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="leNewPassword">
- <property name="echoMode">
- <enum>QLineEdit::Password</enum>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="lblNewPassword2">
- <property name="text">
- <string>&amp;Re-enter new password:</string>
- </property>
- <property name="buddy">
- <cstring>leNewPassword2</cstring>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="leNewPassword2">
- <property name="echoMode">
- <enum>QLineEdit::Password</enum>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QPushButton" name="pbChangePassword">
- <property name="text">
- <string>Change</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0" colspan="2">
- <widget class="QLabel" name="lblPasswordChangeStatus">
- <property name="text">
- <string>&lt;Password change status&gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- </layout>
</widget>
</item>
- <item row="3" column="0">
- <widget class="QGroupBox" name="gbEnabledServices">
- <property name="title">
- <string>Enabled services</string>
+ <item>
+ <layout class="QHBoxLayout" name="horizontal_layout" stretch="0,0">
+ <property name="spacing">
+ <number>12</number>
</property>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="3" column="1">
- <widget class="QPushButton" name="pbSaveServices">
- <property name="text">
- <string>Save this provider settings</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0" colspan="2">
- <widget class="QGroupBox" name="gbServices">
- <property name="title">
- <string>Services</string>
- </property>
- <property name="flat">
- <bool>false</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="0" column="0">
- <layout class="QVBoxLayout" name="vlServices"/>
- </item>
- </layout>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="cbProvidersServices">
- <item>
- <property name="text">
- <string>&lt;Select provider&gt;</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Select provider:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0" colspan="2">
- <widget class="QLabel" name="lblProvidersServicesStatus">
- <property name="text">
- <string>&lt; Providers Services Status &gt;</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
+ <item>
+ <widget class="QListWidget" name="nav_widget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>120</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="movement">
+ <enum>QListView::Static</enum>
+ </property>
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <property name="viewMode">
+ <enum>QListView::IconMode</enum>
+ </property>
+ <property name="uniformItemSizes">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QStackedWidget" name="pages_widget"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="button_layout" stretch="0,0">
+ <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="close_button">
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
</layout>
</widget>
diff --git a/src/leap/bitmask/gui/ui/preferences_account_page.ui b/src/leap/bitmask/gui/ui/preferences_account_page.ui
new file mode 100644
index 00000000..4e58b2ab
--- /dev/null
+++ b/src/leap/bitmask/gui/ui/preferences_account_page.ui
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreferencesAccountPage</class>
+ <widget class="QWidget" name="PreferencesAccountPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>462</width>
+ <height>371</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="btnChangePassword">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Change Password</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblChangePasswordStatus">
+ <property name="text">
+ <string>&lt;change password status&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Preferred</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>15</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="gbServices">
+ <property name="title">
+ <string>Services</string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="1" column="0">
+ <layout class="QVBoxLayout" name="vlServices"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="lblProvidersServicesStatus">
+ <property name="text">
+ <string>&lt; Providers Services Status &gt;</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <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>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/leap/bitmask/gui/ui/preferences_email_page.ui b/src/leap/bitmask/gui/ui/preferences_email_page.ui
new file mode 100644
index 00000000..41b3c28d
--- /dev/null
+++ b/src/leap/bitmask/gui/ui/preferences_email_page.ui
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreferencesEmailPage</class>
+ <widget class="QWidget" name="PreferencesEmailPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <widget class="QPushButton" name="pushButton">
+ <property name="geometry">
+ <rect>
+ <x>250</x>
+ <y>210</y>
+ <width>98</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/leap/bitmask/gui/ui/preferences_vpn_page.ui b/src/leap/bitmask/gui/ui/preferences_vpn_page.ui
new file mode 100644
index 00000000..85a0dc60
--- /dev/null
+++ b/src/leap/bitmask/gui/ui/preferences_vpn_page.ui
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreferencesVpnPage</class>
+ <widget class="QWidget" name="PreferencesVpnPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>362</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="flash_label">
+ <property name="text">
+ <string>&lt;flash_label&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="heading_label">
+ <property name="text">
+ <string>Default VPN Gateway:</string>
+ </property>
+ <property name="buddy">
+ <cstring>gateways_list</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="gateways_list">
+ <item>
+ <property name="text">
+ <string>New Item</string>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normalon>:/images/countries/us.png</normalon>
+ </iconset>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>New Item</string>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normalon>:/images/countries/br.png</normalon>
+ </iconset>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="tip_label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>You must reconnect for changes to take effect.</string>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="buddy">
+ <cstring>gateways_list</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../../../../data/resources/flags.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/leap/bitmask/services/eip/eipconfig.py b/src/leap/bitmask/services/eip/eipconfig.py
index 37c0c8ae..5b51d12e 100644
--- a/src/leap/bitmask/services/eip/eipconfig.py
+++ b/src/leap/bitmask/services/eip/eipconfig.py
@@ -113,39 +113,38 @@ class VPNGatewaySelector(object):
"""
Return the existing gateways, sorted by timezone proximity.
- :rtype: list of tuples (location, ip)
- (str, IPv4Address or IPv6Address object)
+ :rtype: list of tuples (label, ip, country_code)
+ (str, IPv4Address or IPv6Address object, str)
"""
gateways_timezones = []
locations = self._eipconfig.get_locations()
gateways = self._eipconfig.get_gateways()
for idx, gateway in enumerate(gateways):
- gateway_location = gateway.get('location')
- gateway_distance = 99 # if hasn't location -> should go last
-
- if gateway_location is not None:
- timezone = locations[gateway['location']]['timezone']
- gateway_name = locations[gateway['location']].get('name', None)
- if gateway_name is not None:
- gateway_location = gateway_name
-
- gw_offset = int(timezone)
- if gw_offset in self.equivalent_timezones:
- gw_offset = self.equivalent_timezones[gw_offset]
-
- gateway_distance = self._get_timezone_distance(gw_offset)
+ distance = 99 # if hasn't location -> should go last
+ location = locations.get(gateway.get('location'))
+ label = gateway.get('location', 'Unknown')
+ country = 'XX'
+ if location is not None:
+ country = location.get('country_code', 'XX')
+ label = location.get('name', label)
+ timezone = location.get('timezone')
+ if timezone is not None:
+ offset = int(timezone)
+ if offset in self.equivalent_timezones:
+ offset = self.equivalent_timezones[offset]
+ distance = self._get_timezone_distance(offset)
ip = self._eipconfig.get_gateway_ip(idx)
- gateways_timezones.append((ip, gateway_distance, gateway_location))
+ gateways_timezones.append((ip, distance, label, country))
gateways_timezones = sorted(gateways_timezones, key=lambda gw: gw[1])
- gateways = []
- for ip, distance, location in gateways_timezones:
- gateways.append((location, ip))
+ result = []
+ for ip, distance, label, country in gateways_timezones:
+ result.append((label, ip, country))
- return gateways
+ return result
def get_gateways(self):
"""
@@ -153,7 +152,7 @@ class VPNGatewaySelector(object):
:rtype: list of IPv4Address or IPv6Address object.
"""
- gateways = [ip for location, ip in self.get_gateways_list()][:4]
+ gateways = [gateway[1] for gateway in self.get_gateways_list()][:4]
return gateways
def get_gateways_country_code(self):