From cfd60d6e47a351e1ce52709a497e5a0b03319dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 13 Jun 2013 15:14:15 -0300 Subject: Refactor the status bits out of the MainWindow to StatusPanelWidget --- src/leap/gui/statuspanel.py | 216 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 src/leap/gui/statuspanel.py (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py new file mode 100644 index 00000000..53c19e86 --- /dev/null +++ b/src/leap/gui/statuspanel.py @@ -0,0 +1,216 @@ +# -*- 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 . + +""" +Status Panel widget implementation +""" +import logging + +from functools import partial +from PySide import QtCore, QtGui + +from ui_statuspanel import Ui_StatusPanel +from leap.services.eip.vpnprocess import VPNManager +from leap.platform_init import IS_MAC +from leap.common.check import leap_assert_type + +logger = logging.getLogger(__name__) + + +class StatusPanelWidget(QtGui.QWidget): + """ + Status widget that displays the current state of the LEAP services + """ + + start_eip = QtCore.Signal() + stop_eip = QtCore.Signal() + + 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) + + if IS_MAC: + EIP_ICONS = ( + ":/images/conn_connecting-light.png", + ":/images/conn_connected-light.png", + ":/images/conn_error-light.png") + else: + EIP_ICONS = ( + ":/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]) + + 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_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_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 = "%s" % (status,) + self.ui.lblEIPStatus.setText(status) + + def set_startstop_enabled(self, value): + """ + Enable or disable btnEipStartStop based on value + + :param value: True for enabled, False otherwise + :type value: bool + """ + leap_assert_type(value, bool) + self.ui.btnEipStartStop.setEnabled(value) + + 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.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 + """ + upload = float(data[VPNManager.TUNTAP_WRITE_KEY]) + upload = upload / 1000.0 + upload_str = "%12.2f Kb" % (upload,) + self.ui.lblUpload.setText(upload_str) + download = float(data[VPNManager.TUNTAP_READ_KEY]) + download = download / 1000.0 + download_str = "%12.2f Kb" % (download,) + self.ui.lblDownload.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 == "AUTH": + self.set_eip_status(self.tr("Authenticating...")) + elif status == "GET_CONFIG": + self.set_eip_status(self.tr("Retrieving configuration...")) + elif status == "CONNECTED": + self.set_eip_status(self.tr("On")) + 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_eip_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 + tray_message = self.tr("Encryption is OFF") + if status in ("WAIT", "AUTH", "GET_CONFIG", + "RECONNECTING", "ASSIGN_IP"): + selected_pixmap = self.CONNECTING_ICON + tray_message = self.tr("Turning ON") + elif status in ("CONNECTED"): + tray_message = self.tr("Encryption is ON") + selected_pixmap = self.CONNECTED_ICON + + self.set_icon(selected_pixmap) + self._systray.setIcon(QtGui.QIcon(selected_pixmap)) + self._action_eip_status.setText(tray_message) + + def set_provider(self, provider): + self.ui.lblProvider.setText(provider) -- cgit v1.2.3 From a573f046165aa8f28498021939b40286ab96befe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 14 Jun 2013 10:06:46 -0300 Subject: Fix set_eip_status wrong call --- src/leap/gui/statuspanel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index 53c19e86..554903d8 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -189,7 +189,7 @@ class StatusPanelWidget(QtGui.QWidget): "it's already " "running."))) else: - self._set_eip_status(status) + self.set_eip_status(status) def set_eip_status_icon(self, status): """ -- cgit v1.2.3 From 8fe9b31ba750ca6e0396b6330640efeccacb4ced Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 14 Jun 2013 16:24:01 -0300 Subject: Set EIP different status icons depending on OS. Closes bug #2643 --- src/leap/gui/statuspanel.py | 47 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index 554903d8..19f84d4c 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -25,7 +25,7 @@ from PySide import QtCore, QtGui from ui_statuspanel import Ui_StatusPanel from leap.services.eip.vpnprocess import VPNManager -from leap.platform_init import IS_MAC +from leap.platform_init import IS_WIN, IS_LINUX from leap.common.check import leap_assert_type logger = logging.getLogger(__name__) @@ -52,13 +52,35 @@ class StatusPanelWidget(QtGui.QWidget): self.ui.btnEipStartStop.clicked.connect( self.start_eip) - if IS_MAC: - EIP_ICONS = ( - ":/images/conn_connecting-light.png", - ":/images/conn_connected-light.png", - ":/images/conn_error-light.png") - else: - EIP_ICONS = ( + # 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() + + 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") @@ -67,6 +89,10 @@ class StatusPanelWidget(QtGui.QWidget): 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 @@ -199,17 +225,20 @@ class StatusPanelWidget(QtGui.QWidget): :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)) + self._systray.setIcon(QtGui.QIcon(selected_pixmap_tray)) self._action_eip_status.setText(tray_message) def set_provider(self, provider): -- cgit v1.2.3 From 9a725220c393f28c3be5bb0f894b9eb7cf9af2ad Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 20 Jun 2013 03:19:57 +0900 Subject: fix for empty data --- src/leap/gui/statuspanel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index 19f84d4c..62a22725 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -177,11 +177,11 @@ class StatusPanelWidget(QtGui.QWidget): Updates the download/upload labels based on the data provided by the VPN thread """ - upload = float(data[VPNManager.TUNTAP_WRITE_KEY]) + upload = float(data[VPNManager.TUNTAP_WRITE_KEY] or "0") upload = upload / 1000.0 upload_str = "%12.2f Kb" % (upload,) self.ui.lblUpload.setText(upload_str) - download = float(data[VPNManager.TUNTAP_READ_KEY]) + download = float(data[VPNManager.TUNTAP_READ_KEY] or "0") download = download / 1000.0 download_str = "%12.2f Kb" % (download,) self.ui.lblDownload.setText(download_str) -- cgit v1.2.3 From 63bc283c90a80ddc030e24fcc38c533b1e7c551d Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 24 Jun 2013 02:21:34 +0900 Subject: let errors go in their own panel --- src/leap/gui/statuspanel.py | 47 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index 62a22725..de913f09 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -52,6 +52,8 @@ class StatusPanelWidget(QtGui.QWidget): 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 @@ -95,7 +97,7 @@ class StatusPanelWidget(QtGui.QWidget): def set_systray(self, systray): """ - Sets the systray object to use + Sets the systray object to use. :param systray: Systray object :type systray: QtGui.QSystemTrayIcon @@ -105,7 +107,7 @@ class StatusPanelWidget(QtGui.QWidget): def set_action_eip_status(self, action_eip_status): """ - Sets the action_eip_status to use + Sets the action_eip_status to use. :param action_eip_status: action_eip_status to be used :type action_eip_status: QtGui.QAction @@ -113,6 +115,28 @@ class StatusPanelWidget(QtGui.QWidget): 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 = "%s" % (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 @@ -140,6 +164,15 @@ class StatusPanelWidget(QtGui.QWidget): leap_assert_type(value, bool) self.ui.btnEipStartStop.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) + logger.debug('disabling buton.....................') + def eip_started(self): """ Sets the state of the widget to how it should look after EIP @@ -196,12 +229,14 @@ class StatusPanelWidget(QtGui.QWidget): """ status = data[VPNManager.STATUS_STEP_KEY] self.set_eip_status_icon(status) - if status == "AUTH": + 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 == "CONNECTED": - self.set_eip_status(self.tr("On")) elif status == "WAIT": self.set_eip_status(self.tr("Waiting to start...")) elif status == "ASSIGN_IP": @@ -210,7 +245,7 @@ class StatusPanelWidget(QtGui.QWidget): # 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_eip_status, + QtCore.QTimer.singleShot(0, partial(self.set_global_status, self.tr("Unable to start VPN, " "it's already " "running."))) -- cgit v1.2.3 From 19c90e02a65d1d6fe30e6915cd2a9440878aef83 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 24 Jun 2013 02:57:26 +0900 Subject: Improve OpenVPN Process Control * Disable toggle button until we get "connected" status. #2956 * Catch abnormal termination and update UI accordingly. #2890 --- src/leap/gui/statuspanel.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index de913f09..3e5a5093 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -171,7 +171,6 @@ class StatusPanelWidget(QtGui.QWidget): """ self.hide_status_box() self.set_startstop_enabled(False) - logger.debug('disabling buton.....................') def eip_started(self): """ -- cgit v1.2.3 From cc1d8f31071bb99690a355c244b945aa753918a9 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 10 Jul 2013 15:06:45 -0300 Subject: Bugfix: Systray Turn ON action fails. Closes #3125 --- src/leap/gui/statuspanel.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index 3e5a5093..dcb6e802 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -105,6 +105,15 @@ class StatusPanelWidget(QtGui.QWidget): 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. @@ -156,13 +165,15 @@ class StatusPanelWidget(QtGui.QWidget): def set_startstop_enabled(self, value): """ - Enable or disable btnEipStartStop based on 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): """ -- cgit v1.2.3 From a5c91b4711f9b4e13b9cc32d0fef3ea0b61b0e9f Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 22 Jul 2013 21:35:21 +0200 Subject: use rates in display --- src/leap/gui/statuspanel.py | 99 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 6 deletions(-) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index dcb6e802..04fc6818 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -20,17 +20,68 @@ 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.common.check import leap_assert_type +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._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] + + deltatraffic = traff[-1] - first(traff) + deltat = (times[-1] - first(times)).seconds + + try: + rate = float(deltatraffic) / float(deltat) / 1024 + except ZeroDivisionError: + rate = 0 + return rate + + class StatusPanelWidget(QtGui.QWidget): """ Status widget that displays the current state of the LEAP services @@ -63,6 +114,40 @@ class StatusPanelWidget(QtGui.QWidget): self.ERROR_ICON_TRAY = None self._set_eip_icons() + self._set_traffic_rates() + + def _set_traffic_rates(self): + """ + Initializes up and download rates. + """ + self._up_rate = RateMovingAverage() + self._down_rate = RateMovingAverage() + + 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. + + :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 _set_eip_icons(self): """ Sets the EIP status icons for the main window and for the tray @@ -221,12 +306,14 @@ class StatusPanelWidget(QtGui.QWidget): by the VPN thread """ upload = float(data[VPNManager.TUNTAP_WRITE_KEY] or "0") - upload = upload / 1000.0 - upload_str = "%12.2f Kb" % (upload,) - self.ui.lblUpload.setText(upload_str) download = float(data[VPNManager.TUNTAP_READ_KEY] or "0") - download = download / 1000.0 - download_str = "%12.2f Kb" % (download,) + self._update_traffic_rates(upload, download) + uprate, downrate = self._get_traffic_rates() + + upload_str = "%14.2f KB/s" % (uprate,) + self.ui.lblUpload.setText(upload_str) + + download_str = "%14.2f KB/s" % (downrate,) self.ui.lblDownload.setText(download_str) def update_vpn_state(self, data): -- cgit v1.2.3 From 69a0abef027c040b6daee1ba4c22f3d249139e7a Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 22 Jul 2013 18:30:25 +0200 Subject: try to terminate already running openvpn instance --- src/leap/gui/statuspanel.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index 04fc6818..ac0f5162 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -45,6 +45,9 @@ class RateMovingAverage(object): """ 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): -- cgit v1.2.3 From db18ad67d4149b5f5a6f68db1f52abd91f6f9373 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 25 Jul 2013 11:41:15 +0200 Subject: reset rates when disconnecting --- src/leap/gui/statuspanel.py | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index ac0f5162..3e0377f9 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -126,6 +126,16 @@ class StatusPanelWidget(QtGui.QWidget): self._up_rate = RateMovingAverage() self._down_rate = RateMovingAverage() + def _reset_traffic_rates(self): + """ + Resets up and download rates, and cleans up the labels. + """ + self._up_rate.reset() + self._down_rate.reset() + zeroed = {VPNManager.TUNTAP_WRITE_KEY: 0, + VPNManager.TUNTAP_READ_KEY: 0} + self.update_vpn_status(zeroed) + def _update_traffic_rates(self, up, down): """ Updates up and download rates. @@ -286,6 +296,7 @@ class StatusPanelWidget(QtGui.QWidget): 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( -- cgit v1.2.3 From b9c3fcd9ea6469185f7e7f483eeffb7b346e9dad Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 25 Jul 2013 17:38:28 +0200 Subject: Make the rates clickable to alternate between rates and totals. Closes: #3249, #3232 --- src/leap/gui/statuspanel.py | 99 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 18 deletions(-) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index 3e0377f9..7c824e01 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -75,8 +75,12 @@ class RateMovingAverage(object): traff = [traffic for (ts, traffic) in data] times = [ts for (ts, traffic) in data] - deltatraffic = traff[-1] - first(traff) - deltat = (times[-1] - first(times)).seconds + 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 @@ -84,6 +88,15 @@ class RateMovingAverage(object): 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): """ @@ -93,6 +106,10 @@ class StatusPanelWidget(QtGui.QWidget): 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) @@ -118,6 +135,27 @@ class StatusPanelWidget(QtGui.QWidget): 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): """ @@ -126,15 +164,16 @@ class StatusPanelWidget(QtGui.QWidget): 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() - zeroed = {VPNManager.TUNTAP_WRITE_KEY: 0, - VPNManager.TUNTAP_READ_KEY: 0} - self.update_vpn_status(zeroed) + self.update_vpn_status(None) def _update_traffic_rates(self, up, down): """ @@ -151,7 +190,7 @@ class StatusPanelWidget(QtGui.QWidget): def _get_traffic_rates(self): """ - Gets the traffic rates. + Gets the traffic rates (in KB/s). :returns: a tuple with the (up, down) rates :rtype: tuple @@ -161,6 +200,18 @@ class StatusPanelWidget(QtGui.QWidget): 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 @@ -317,18 +368,30 @@ class StatusPanelWidget(QtGui.QWidget): TRIGGER: VPN.status_changed Updates the download/upload labels based on the data provided - by the VPN thread - """ - upload = float(data[VPNManager.TUNTAP_WRITE_KEY] or "0") - download = float(data[VPNManager.TUNTAP_READ_KEY] or "0") - self._update_traffic_rates(upload, download) - uprate, downrate = self._get_traffic_rates() - - upload_str = "%14.2f KB/s" % (uprate,) - self.ui.lblUpload.setText(upload_str) - - download_str = "%14.2f KB/s" % (downrate,) - self.ui.lblDownload.setText(download_str) + 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): """ -- cgit v1.2.3 From 9bc0b0b8508da85b90cb3390b0bc92410a53acfe Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 2 Aug 2013 14:33:58 -0300 Subject: Bugfix, avoid getting negative rates. Closes #3274 --- src/leap/gui/statuspanel.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/leap/gui/statuspanel.py') diff --git a/src/leap/gui/statuspanel.py b/src/leap/gui/statuspanel.py index 7c824e01..f3424c7c 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/gui/statuspanel.py @@ -86,6 +86,11 @@ class RateMovingAverage(object): 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): -- cgit v1.2.3