summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/gui/mainwindow.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/bitmask/gui/mainwindow.py')
-rw-r--r--src/leap/bitmask/gui/mainwindow.py186
1 files changed, 107 insertions, 79 deletions
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 389ff172..0518350e 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -237,8 +237,8 @@ class MainWindow(QtGui.QMainWindow):
self._action_eip_startstop = QtGui.QAction("", self)
self._eip_status.set_action_eip_startstop(self._action_eip_startstop)
- self._action_visible = QtGui.QAction(self.tr("Hide Main Window"), self)
- self._action_visible.triggered.connect(self._toggle_visible)
+ self._action_visible = QtGui.QAction(self.tr("Show Main Window"), self)
+ self._action_visible.triggered.connect(self._ensure_visible)
# disable buttons for now, may come back later.
# self.ui.btnPreferences.clicked.connect(self._show_preferences)
@@ -285,14 +285,8 @@ class MainWindow(QtGui.QMainWindow):
self.logout.connect(self._mail_conductor.stop_mail_services)
- # Eip machine is a public attribute where the state machine for
- # the eip connection will be available to the different components.
- # Remember that this will not live in the +1600LOC mainwindow for
- # all the eternity, so at some point we will be moving this to
- # the EIPConductor or some other clever component that we will
- # instantiate from here.
+ # start event machines from within the eip and mail conductors
- # start event machines
# TODO should encapsulate all actions into one object
self._eip_conductor.start_eip_machine(
action=self._action_eip_startstop)
@@ -963,8 +957,6 @@ class MainWindow(QtGui.QMainWindow):
Display 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()
@@ -973,50 +965,38 @@ class MainWindow(QtGui.QMainWindow):
# this works however.
context_menu.exec_(self._systray.geometry().center())
- def _update_hideshow_menu(self):
- """
- Update the Hide/Show main window menu text based on the
- visibility of the window.
+ @QtCore.Slot()
+ def _ensure_visible(self):
"""
- get_action = lambda visible: (
- self.tr("Show Main Window"),
- self.tr("Hide Main Window"))[int(visible)]
+ TRIGGERS:
+ self._action_visible.triggered
- # set labels
- visible = self.isVisible() and self.isActiveWindow()
- self._action_visible.setText(get_action(visible))
+ Ensure that the window is visible and raised.
+ """
+ QtGui.QApplication.setQuitOnLastWindowClosed(True)
+ self.show()
+ if IS_LINUX:
+ # On ubuntu, activateWindow doesn't work reliably, so
+ # we do the following as a workaround. See
+ # https://bugreports.qt-project.org/browse/QTBUG-24932
+ # for more details
+ QtGui.QX11Info.setAppUserTime(0)
+ self.activateWindow()
+ self.raise_()
@QtCore.Slot()
- def _toggle_visible(self):
+ def _ensure_invisible(self):
"""
TRIGGERS:
self._action_visible.triggered
- Toggle the window visibility
+ Ensure that the window is hidden.
"""
- visible = self.isVisible() and self.isActiveWindow()
-
- if not visible:
- QtGui.QApplication.setQuitOnLastWindowClosed(True)
- self.show()
- if IS_LINUX:
- # On ubuntu, activateWindow doesn't work reliably, so
- # we do the following as a workaround. See
- # https://bugreports.qt-project.org/browse/QTBUG-24932
- # for more details
- QtGui.QX11Info.setAppUserTime(0)
- self.activateWindow()
- self.raise_()
- else:
- # We set this in order to avoid dialogs shutting down the
- # app on close, as they will be the only visible window.
- # e.g.: PreferencesWindow, LoggerWindow
- QtGui.QApplication.setQuitOnLastWindowClosed(False)
- self.hide()
-
- # Wait a bit until the window visibility has changed so
- # the menu is set with the correct value.
- QtDelayedCall(500, self._update_hideshow_menu)
+ # We set this in order to avoid dialogs shutting down the
+ # app on close, as they will be the only visible window.
+ # e.g.: PreferencesWindow, LoggerWindow
+ QtGui.QApplication.setQuitOnLastWindowClosed(False)
+ self.hide()
def _center_window(self):
"""
@@ -1079,22 +1059,38 @@ class MainWindow(QtGui.QMainWindow):
# TODO: don't hardcode!
smtp_port = 2013
- url = ("<a href='https://addons.mozilla.org/es/thunderbird/"
- "addon/bitmask/'>bitmask addon</a>")
-
- msg = self.tr(
- "<strong>Instructions to use mail:</strong><br>"
- "If you use Thunderbird you can use the Bitmask extension helper. "
- "Search for 'Bitmask' in the add-on manager or download it "
- "from: {0}.<br><br>"
- "You can configure Bitmask manually with these options:<br>"
- "<em>"
- " Incoming -> IMAP, port: {1}<br>"
- " Outgoing -> SMTP, port: {2}<br>"
- " Username -> your bitmask username.<br>"
- " Password -> does not matter, use any text. "
- " Just don't leave it empty and don't use your account's password."
- "</em>").format(url, IMAP_PORT, smtp_port)
+ help_url = "<p><a href='https://{0}'>{0}</a></p>".format(
+ self.tr("bitmask.net/help"))
+
+ lang = QtCore.QLocale.system().name().replace('_','-')
+ thunderbird_extension_url = \
+ "https://addons.mozilla.org/{0}/" \
+ "thunderbird/addon/bitmask/".format(lang)
+
+ email_quick_reference = self.tr("Email quick reference")
+ thunderbird_text = self.tr("For Thunderbird, you can use the "
+ "Bitmask extension. Search for \"Bitmask\" in the add-on "
+ "manager or download it from <a href='{0}'>"
+ "addons.mozilla.org</a>.".format(thunderbird_extension_url))
+ manual_text = self.tr("Alternately, you can manually configure "
+ "your mail client to use Bitmask Email with these options:")
+ manual_imap = self.tr("IMAP: localhost, port {0}".format(IMAP_PORT))
+ manual_smtp = self.tr("SMTP: localhost, port {0}".format(smtp_port))
+ manual_username = self.tr("Username: your full email address")
+ manual_password = self.tr("Password: any non-empty text")
+
+ msg = help_url + self.tr(
+ "<p><strong>{0}</strong></p>"
+ "<p>{1}</p>"
+ "<p>{2}"
+ "<ul>"
+ "<li>&nbsp;{3}</li>"
+ "<li>&nbsp;{4}</li>"
+ "<li>&nbsp;{5}</li>"
+ "<li>&nbsp;{6}</li>"
+ "</ul></p>").format(email_quick_reference, thunderbird_text,
+ manual_text, manual_imap, manual_smtp,
+ manual_username, manual_password)
QtGui.QMessageBox.about(self, self.tr("Bitmask Help"), msg)
def _needs_update(self):
@@ -1120,19 +1116,6 @@ class MainWindow(QtGui.QMainWindow):
"Error: API version incompatible.")
QtGui.QMessageBox.warning(self, self.tr("Incompatible Provider"), msg)
- def changeEvent(self, e):
- """
- Reimplementation of changeEvent method to minimize to tray
- """
- if not IS_MAC and \
- 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
@@ -1145,7 +1128,7 @@ class MainWindow(QtGui.QMainWindow):
if QtGui.QSystemTrayIcon.isSystemTrayAvailable() and \
not self._really_quit:
- self._toggle_visible()
+ self._ensure_invisible()
e.ignore()
return
@@ -1165,12 +1148,14 @@ class MainWindow(QtGui.QMainWindow):
skip_first_run = self._settings.get_skip_first_run()
return not (has_provider_on_disk and skip_first_run)
+ @QtCore.Slot()
def _download_provider_config(self):
"""
Start the bootstrapping sequence. It will download the
provider configuration if it's not present, otherwise will
emit the corresponding signals inmediately
"""
+ self._disconnect_scheduled_login()
domain = self._login_widget.get_selected_provider()
self._backend.provider_setup(provider=domain)
@@ -1204,6 +1189,40 @@ class MainWindow(QtGui.QMainWindow):
self.tr("Unable to login: Problem with provider"))
self._login_widget.set_enabled(True)
+ def _schedule_login(self):
+ """
+ Schedule the login sequence to go after the EIP started.
+
+ The login sequence is connected to all finishing status of EIP
+ (connected, disconnected, aborted or died) to continue with the login
+ after EIP.
+ """
+ logger.debug('Login scheduled when eip_connected is triggered')
+ eip_sigs = self._eip_conductor.qtsigs
+ eip_sigs.connected_signal.connect(self._download_provider_config)
+ eip_sigs.disconnected_signal.connect(self._download_provider_config)
+ eip_sigs.connection_aborted_signal.connect(self._download_provider_config)
+ eip_sigs.connection_died_signal.connect(self._download_provider_config)
+
+ def _disconnect_scheduled_login(self):
+ """
+ Disconnect scheduled login signals if exists
+ """
+ try:
+ eip_sigs = self._eip_conductor.qtsigs
+ eip_sigs.connected_signal.disconnect(
+ self._download_provider_config)
+ eip_sigs.disconnected_signal.disconnect(
+ self._download_provider_config)
+ eip_sigs.connection_aborted_signal.disconnect(
+ self._download_provider_config)
+ eip_sigs.connection_died_signal.disconnect(
+ self._download_provider_config)
+ except Exception:
+ # signal not connected
+ pass
+
+
@QtCore.Slot()
def _login(self):
"""
@@ -1229,7 +1248,10 @@ class MainWindow(QtGui.QMainWindow):
else:
self.ui.action_create_new_account.setEnabled(False)
if self._login_widget.start_login():
- self._download_provider_config()
+ if self._trying_to_start_eip:
+ self._schedule_login()
+ else:
+ self._download_provider_config()
@QtCore.Slot(unicode)
def _authentication_error(self, msg):
@@ -1258,8 +1280,13 @@ class MainWindow(QtGui.QMainWindow):
Stop the login sequence.
"""
logger.debug("Cancelling log in.")
+ self._disconnect_scheduled_login()
+
self._cancel_ongoing_defers()
+ # Needed in case of EIP starting and login deferer never set
+ self._set_login_cancelled()
+
def _cancel_ongoing_defers(self):
"""
Cancel the running defers to avoid app blocking.
@@ -1673,8 +1700,9 @@ class MainWindow(QtGui.QMainWindow):
"""
passed = data[PASSED_KEY]
if not passed:
- self._login_widget.set_status(
- self.tr("Unable to connect: Problem with provider"))
+ self._eip_status.set_eip_status(
+ self.tr("Unable to connect: Problem with provider"),
+ error=True)
logger.error(data[ERROR_KEY])
self._already_started_eip = False
self._eip_status.aborted()