diff --git a/src/nexus/GUI.py b/src/nexus/GUI.py
index 503adc6..0ba625e 100644
--- a/src/nexus/GUI.py
+++ b/src/nexus/GUI.py
@@ -1,11 +1,13 @@
import argparse
+import os
from threading import Thread
from pathlib import Path
from typing import Literal
from PySide6.QtCore import Qt, QTranslator, QLocale
from PySide6.QtWidgets import QApplication, QPushButton, QStatusBar, QTableWidget, QTableWidgetItem, QMainWindow, \
- QDialog, QFileDialog, QDialogButtonBox, QVBoxLayout, QLabel, QMenu
+ QDialog, QFileDialog, QDialogButtonBox, QVBoxLayout, QLabel, QMenu, QSystemTrayIcon
+from PySide6.QtGui import QIcon, QAction
from nexus.Freqlog import Freqlog
from nexus.ui.BanlistDialog import Ui_BanlistDialog
@@ -74,12 +76,31 @@ def __init__(self, args: argparse.Namespace):
self.app = QApplication([])
self.window = MainWindow()
+ script_parent_path = str(Path(__file__).resolve().parent)
+
# Translation
self.translator = Translator(self.app)
- if self.translator.load(QLocale.system(), 'i18n', '_', str(Path(__file__).resolve().parent) + '/translations'):
+ if self.translator.load(QLocale.system(), 'i18n', '_', os.path.join(script_parent_path, 'translations')):
self.app.installTranslator(self.translator)
self.tr = self.translator.translate
+ # System tray
+ self.tray_icon = QIcon(os.path.join(script_parent_path, 'assets', 'images', 'icon.ico'))
+ self.tray = QSystemTrayIcon()
+ self.tray.activated.connect(self.show_hide)
+ self.tray.setIcon(self.tray_icon)
+ self.tray.setVisible(True)
+
+ # System tray menu
+ self.tray_menu = QMenu()
+ self.start_stop_tray_menu_action = QAction(self.tr("GUI", "Start/stop logging"))
+ self.quit_tray_menu_action = QAction(self.tr("GUI", "Quit"))
+ self.start_stop_tray_menu_action.triggered.connect(self.start_stop)
+ self.quit_tray_menu_action.triggered.connect(self.app.quit)
+ self.tray_menu.addAction(self.start_stop_tray_menu_action)
+ self.tray_menu.addAction(self.quit_tray_menu_action)
+ self.tray.setContextMenu(self.tray_menu)
+
# Components
self.start_stop_button: QPushButton = self.window.startStopButton
self.chentry_table: QTableWidget = self.window.chentryTable
@@ -165,6 +186,13 @@ def __init__(self, args: argparse.Namespace):
self.window.entries_input.valueChanged.connect(self.refresh)
self.window.search_input.textChanged.connect(self.refresh)
+ def show_hide(self, reason):
+ if reason == QSystemTrayIcon.ActivationReason.Trigger:
+ if not self.window.isVisible():
+ self.window.show()
+ else:
+ self.window.hide()
+
def set_style(self, style: Literal['Nexus_Dark', 'Fusion', 'Default']):
self.app.setStyleSheet('')
if style == 'Default':
diff --git a/src/nexus/assets/images/icon.ico b/src/nexus/assets/images/icon.ico
new file mode 100644
index 0000000..a037718
Binary files /dev/null and b/src/nexus/assets/images/icon.ico differ
diff --git a/src/nexus/assets/images/icon.svg b/src/nexus/assets/images/icon.svg
new file mode 100644
index 0000000..a7aee9b
--- /dev/null
+++ b/src/nexus/assets/images/icon.svg
@@ -0,0 +1,54 @@
+
+
+
diff --git a/translations/i18n_en.ts b/translations/i18n_en.ts
index 61fe220..5b24bea 100644
--- a/translations/i18n_en.ts
+++ b/translations/i18n_en.ts
@@ -70,140 +70,152 @@
GUI
-
+
Start logging
-
+
Starting...
-
+
+ Start/stop logging
-
+
+
+ Quit
+
+
+
+
+
+
+
+
+
Ban and delete
-
+
Stop logging
-
+
Logging started
-
+
Logging stopped
-
+
Loaded {}/{} freqlogged words
-
-
+
+
Banned '{}'
-
-
+
+
'{}' already banned
-
+
Unban {} words?
-
+
Unban '{}'?
-
+
Unbanned '{}'
-
+
'{}' not banned
-
+
None of the selected words were banned
-
+
Unbanned {}/{} selected words
-
+
Exported {} entries to {}
-
+
Ban and delete {} words?
-
+
Ban and delete '{}'?
-
+
All of the selected words were already banned
-
+
Banned and deleted {}/{} selected words
-
+
Confirm ban
-
+
Confirm unban