diff --git a/ui/opensnitch/config.py b/ui/opensnitch/config.py
index 168c680b8b..f5cc1f9cd0 100644
--- a/ui/opensnitch/config.py
+++ b/ui/opensnitch/config.py
@@ -119,6 +119,7 @@ class Config:
NOTIFICATION_TYPE_SYSTEM = 0
NOTIFICATION_TYPE_QT = 1
+ STATS_UPDATE_INTERVAL = "statsDialog/update_interval"
STATS_GEOMETRY = "statsDialog/geometry"
STATS_LAST_TAB = "statsDialog/last_tab"
STATS_FILTER_TEXT = "statsDialog/general_filter_text"
diff --git a/ui/opensnitch/dialogs/preferences.py b/ui/opensnitch/dialogs/preferences.py
index 94f1d2dd2f..0e1b5a1eb1 100644
--- a/ui/opensnitch/dialogs/preferences.py
+++ b/ui/opensnitch/dialogs/preferences.py
@@ -88,6 +88,8 @@ def __init__(self, parent=None, appicon=None):
self.comboUITheme.currentIndexChanged.connect(self._cb_combo_themes_changed)
self.cmdTimeoutUp.clicked.connect(lambda: self._cb_cmd_spin_clicked(self.spinUITimeout, self.SUM))
self.cmdTimeoutDown.clicked.connect(lambda: self._cb_cmd_spin_clicked(self.spinUITimeout, self.REST))
+ self.cmdRefreshUIUp.clicked.connect(lambda: self._cb_cmd_spin_clicked(self.spinUIRefresh, self.SUM))
+ self.cmdRefreshUIDown.clicked.connect(lambda: self._cb_cmd_spin_clicked(self.spinUIRefresh, self.REST))
self.cmdDBMaxDaysUp.clicked.connect(lambda: self._cb_cmd_spin_clicked(self.spinDBMaxDays, self.SUM))
self.cmdDBMaxDaysDown.clicked.connect(lambda: self._cb_cmd_spin_clicked(self.spinDBMaxDays, self.REST))
self.cmdDBPurgesUp.clicked.connect(lambda: self._cb_cmd_spin_clicked(self.spinDBPurgeInterval, self.SUM))
@@ -133,6 +135,8 @@ def __init__(self, parent=None, appicon=None):
self.cmdTimeoutUp.setIcon(addIcon)
self.cmdTimeoutDown.setIcon(delIcon)
+ self.cmdRefreshUIUp.setIcon(addIcon)
+ self.cmdRefreshUIDown.setIcon(delIcon)
self.cmdDBMaxDaysUp.setIcon(addIcon)
self.cmdDBMaxDaysDown.setIcon(delIcon)
self.cmdDBPurgesUp.setIcon(addIcon)
@@ -260,6 +264,9 @@ def _load_settings(self):
self.comboUIDuration.setCurrentIndex(self._default_duration)
self.comboUIDialogPos.setCurrentIndex(self._cfg.getInt(self._cfg.DEFAULT_POPUP_POSITION))
+ self._ui_refresh_interval = self._cfg.getInt(self._cfg.STATS_REFRESH_INTERVAL, 0)
+ self.spinUIRefresh.setValue(self._ui_refresh_interval)
+
self.checkAutostart.setChecked(self._autostart.isEnabled())
maxmsgsize = self._cfg.getSettings(Config.DEFAULT_SERVER_MAX_MESSAGE_LENGTH)
@@ -581,6 +588,7 @@ def _save_ui_config(self):
if self.checkUIRules.isChecked():
self._nodes.delete_rule_by_field(Config.DURATION_FIELD, Config.RULES_DURATION_FILTER)
+ self._cfg.setSettings(self._cfg.STATS_REFRESH_INTERVAL, int(self.spinUIRefresh.value()))
self._cfg.setSettings(self._cfg.DEFAULT_ACTION_KEY, self.comboUIAction.currentIndex())
self._cfg.setSettings(self._cfg.DEFAULT_DURATION_KEY, int(self.comboUIDuration.currentIndex()))
self._cfg.setSettings(self._cfg.DEFAULT_TARGET_KEY, self.comboUITarget.currentIndex())
diff --git a/ui/opensnitch/dialogs/stats.py b/ui/opensnitch/dialogs/stats.py
index 83e04e2c4f..69b2c24025 100644
--- a/ui/opensnitch/dialogs/stats.py
+++ b/ui/opensnitch/dialogs/stats.py
@@ -339,6 +339,7 @@ def __init__(self, parent=None, address=None, db=None, dbname="db", appicon=None
self._rules.updated.connect(self._cb_app_rules_updated)
self._actions = Actions().instance()
self._actions.loadAll()
+ self._last_update = datetime.datetime.now()
# TODO: allow to display multiples dialogs
self._proc_details_dialog = ProcessDetailsDialog(appicon=appicon)
@@ -718,6 +719,7 @@ def _configure_buttons_icons(self):
self.TABLES[idx]['cmdCleanStats'].setIcon(clearIcon)
def _load_settings(self):
+ self._ui_refresh_interval = self._cfg.getInt(Config.STATS_REFRESH_INTERVAL, 0)
dialog_geometry = self._cfg.getSettings(Config.STATS_GEOMETRY)
dialog_last_tab = self._cfg.getSettings(Config.STATS_LAST_TAB)
dialog_general_filter_text = self._cfg.getSettings(Config.STATS_FILTER_TEXT)
@@ -2517,6 +2519,7 @@ def _get_indetail_filter_query(self, lastQuery, text):
@QtCore.pyqtSlot()
def _on_settings_saved(self):
+ self._ui_refresh_interval = self._cfg.getInt(Config.STATS_REFRESH_INTERVAL, 0)
self._show_columns()
self.settings_saved.emit()
@@ -2699,6 +2702,13 @@ def update_interception_status(self, enabled):
else:
self._update_status_label(running=False, text=self.FIREWALL_DISABLED)
+ def _needs_refresh(self):
+ diff = datetime.datetime.now() - self._last_update
+ if diff.seconds < self._ui_refresh_interval:
+ return False
+
+ return True
+
# launched from a thread
def update(self, is_local=True, stats=None, need_query_update=True):
# lock mandatory when there're multiple clients
@@ -2706,8 +2716,9 @@ def update(self, is_local=True, stats=None, need_query_update=True):
if stats is not None:
self._stats = stats
# do not update any tab if the window is not visible
- if self.isVisible() and self.isMinimized() == False:
+ if self.isVisible() and self.isMinimized() == False and self._needs_refresh():
self._trigger.emit(is_local, need_query_update)
+ self._last_update = datetime.datetime.now()
def update_status(self):
self.startButton.setDown(self.daemon_connected)
diff --git a/ui/opensnitch/res/preferences.ui b/ui/opensnitch/res/preferences.ui
index a2577e8ce7..74ea72e818 100644
--- a/ui/opensnitch/res/preferences.ui
+++ b/ui/opensnitch/res/preferences.ui
@@ -14,13 +14,6 @@
Preferences
- -
-
-
- true
-
-
-
-
-
@@ -564,7 +557,7 @@
UI
-
-
+
-
0
@@ -581,37 +574,37 @@
General
-
-
-
-
+
+
-
+
-
+
0
0
- Language
+ Refresh interval (seconds)
+
+
+ true
- -
-
+
-
+
-
+
0
0
-
+ Theme
- -
-
-
- -
+
-
-
@@ -620,8 +613,21 @@
- -
-
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
0
@@ -629,11 +635,14 @@
- Theme
+ Language
- -
+
-
+
+
+ -
By default the GUI is started when login
@@ -646,6 +655,78 @@
+ -
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ ../../../../../../../../../../../../../../.designer/backup../../../../../../../../../../../../../../.designer/backup
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::AlignCenter
+
+
+ QAbstractSpinBox::NoButtons
+
+
+ true
+
+
+ 100
+
+
+ 1
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ ../../../../../../../../../../../../../../.designer/backup../../../../../../../../../../../../../../.designer/backup
+
+
+ true
+
+
+
+
+
@@ -737,7 +818,9 @@
-
- <p>Simple: no authentication, TLS simple/mutual: use SSL certificates to authenticate nodes.</p><p>Visit the wiki for more information.</p>
+ <p>Simple: no authentication</p>
+<p>TLS simple/mutual: use SSL certificates to authenticate nodes.</p>
+<p>Visit the wiki for more information.</p>
Authentication type
@@ -759,7 +842,7 @@
0
0
586
- 209
+ 264
@@ -855,7 +938,7 @@
0
0
586
- 209
+ 264
@@ -1602,6 +1685,86 @@ Temporary rules will still be valid, and you can use them when prompted to allow
+
+
+ true
+
+
+
+ 0
+ 0
+ 226
+ 101
+
+
+
+ Rules
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
-
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+ sha1
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+ md5
+
+
+ true
+
+
+
+
+
+ -
+
+
+ Compute and verify binaries checksums when they try to establish new connections
+
+
+ Enable checksums verification
+
+
+
+
+
-
@@ -1932,6 +2095,13 @@ Temporary rules will still be valid, and you can use them when prompted to allow
+ -
+
+
+ true
+
+
+