diff --git a/README.md b/README.md
index 75b172d2..e050db9a 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,20 @@
## fpakman
-Graphical interface for Flatpak application management. It has also a tray icon to let the user known when new updates are available.
-Wriiten in Python for QT5.
+Graphical interface for Flatpak application management. It is a tray icon to let the user known when new updates are available.
+It has also a management window allowing the user to see all installed apllications and update them.
+
+### Technologies:
+- Python3 and QT 5.
+
+## Settings
+You can change some application settings via environment variables:
+- **FPAKMAN_UPDATE_NOTIFICATION: enable or disable system updates notifications. Use 0 (disable) or 1 (enable, default).
+- **FPAKMAN_CHECK_INTERVAL**: define the updates check interval in seconds. Default: 60.
+
+## Installation script
+You can install the application without compromising your system via the provided installation script called 'sandbox_installer.py'.
+Type in the terminal: sudo python3 sandbox_installer.py. If you want to uninstall the application, just call the script the same way.
### Roadmap
- Test installer for Ubuntu
- Locales
-- System notification whe new updates
- Search and install applications.
\ No newline at end of file
diff --git a/app.py b/app.py
index 7e9c272f..e1d42cab 100755
--- a/app.py
+++ b/app.py
@@ -1,5 +1,6 @@
#!env/bin/python
import argparse
+import os
import sys
from PyQt5.QtWidgets import QApplication, QWidget
@@ -18,7 +19,7 @@ manager = FlatpakManager()
manager.load_database_async()
controller = FlatpakController(manager)
hidden_widget = QWidget()
-trayIcon = TrayIcon(parent=hidden_widget, controller=controller, check_interval=30)
+trayIcon = TrayIcon(parent=hidden_widget, controller=controller, check_interval=int(os.getenv('FPAKMAN_CHECK_INTERVAL', 30)))
trayIcon.show()
sys.exit(app.exec_())
diff --git a/core/model.py b/core/model.py
index b8be52b6..95e55b2f 100755
--- a/core/model.py
+++ b/core/model.py
@@ -21,7 +21,7 @@ class FlatpakManager:
self.lock_db_read = Lock()
def load_database_async(self):
- Thread(target=self.load_database).start()
+ Thread(target=self.load_database, daemon=True).start()
def load_database(self):
diff --git a/resources/img/flathub_25.svg b/resources/img/flathub_10.svg
similarity index 97%
rename from resources/img/flathub_25.svg
rename to resources/img/flathub_10.svg
index 15e46ff5..2311083c 100644
--- a/resources/img/flathub_25.svg
+++ b/resources/img/flathub_10.svg
@@ -9,13 +9,13 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="24.856121"
- height="24.071226"
- viewBox="0 0 6.5765152 6.3688453"
+ width="9.6111898"
+ height="8.805685"
+ viewBox="0 0 2.5429606 2.3298375"
version="1.1"
id="svg3871"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
- sodipodi:docname="flathub_25.svg">
+ sodipodi:docname="flathub_5.svg">
+ transform="translate(-12.162843,-177.89043)">
image/svg+xml
-
+
@@ -62,19 +62,19 @@
+ style="fill:#ff2a2a;stroke:#800000;stroke-width:0.77710575">
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff2a2a;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:9.3252697;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
@@ -92,7 +92,7 @@
inkscape:connector-curvature="0"
id="path10650"
d="m 783.00003,824.92983 5e-5,68.99997 66.46803,42.90055 -5e-5,-68.99997 z"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff2a2a;fill-opacity:1;fill-rule:nonzero;stroke:#aa0000;stroke-width:2.34915853;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff2a2a;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:2.34915853;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff2a2a;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:2.4608953;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff2a2a;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:2.4608953;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff2a2a;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:2.34915853;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff2a2a;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:2.4608953;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
@@ -172,7 +172,7 @@
inkscape:connector-curvature="0"
id="path10670"
d="m 783.00003,824.92983 5e-5,68.99997 66.46803,42.90055 -5e-5,-68.99997 z"
- style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff2a2a;fill-opacity:1;fill-rule:nonzero;stroke:#aa0000;stroke-width:2.34915853;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff2a2a;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:2.34915853;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
diff --git a/view/qt/systray.py b/view/qt/systray.py
index 8c438d51..76ebf5e0 100755
--- a/view/qt/systray.py
+++ b/view/qt/systray.py
@@ -1,3 +1,4 @@
+import os
import time
from PyQt5.QtCore import QThread, pyqtSignal, QCoreApplication
@@ -6,7 +7,6 @@ from PyQt5.QtWidgets import QSystemTrayIcon, QMenu
from core import resource
-
# to update
from core.controller import FlatpakController
from view.qt.window import ManageWindow
@@ -57,12 +57,18 @@ class TrayIcon(QSystemTrayIcon):
def notify_updates(self, updates: int):
if updates > 0:
- if self.icon() != self.icon_update:
+ if self.icon().cacheKey() != self.icon_update.cacheKey():
self.setIcon(self.icon_update)
- self.setToolTip('Updates found: {}'.format(updates))
- if self.manage_window:
+ msg = 'Updates found: {}'.format(updates)
+ self.setToolTip(msg)
+
+ if bool(os.getenv('FPAKMAN_UPDATE_NOTIFICATION', 1)):
+ os.system("notify-send -i {} '{}'".format(resource.get_path('img/flathub_10.svg'), msg))
+
+ if self.manage_window and not self.manage_window.isHidden():
self.manage_window.refresh()
+
else:
self.setIcon(self.icon_default)
self.setToolTip(None)