This commit is contained in:
Vinícius Moreira
2020-04-13 11:49:28 -03:00
parent 83aab1ff55
commit 01a60ea686
165 changed files with 12778 additions and 6171 deletions

View File

@@ -1,48 +1,82 @@
import json
import os
import sys
import time
import traceback
from io import StringIO
from subprocess import Popen
from threading import Lock, Thread
from typing import List
from PyQt5.QtCore import QThread, pyqtSignal, QCoreApplication, Qt, QSize
from PyQt5.QtCore import QThread, pyqtSignal, QCoreApplication, QSize
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QSystemTrayIcon, QMenu, QWidget, QSizePolicy
from PyQt5.QtWidgets import QSystemTrayIcon, QMenu
from bauh import __app_name__
from bauh.api.abstract.controller import SoftwareManager
from bauh import __app_name__, ROOT_DIR
from bauh.api.abstract.model import PackageUpdate
from bauh.view.qt import qt_utils
from bauh.commons.system import run_cmd
from bauh.context import generate_i18n
from bauh.view.core.tray_client import TRAY_CHECK_FILE
from bauh.view.qt.about import AboutDialog
from bauh.view.qt.settings import SettingsWindow
from bauh.view.qt.view_utils import load_resource_icon
from bauh.view.qt.window import ManageWindow
from bauh.view.util import util
from bauh.view.util.translation import I18n
from bauh.view.util import util, resource
def list_updates() -> List[PackageUpdate]:
if run_cmd('which bauh-cli', print_error=False):
output = run_cmd('bauh-cli updates -f json')
if output:
return [PackageUpdate(pkg_id=o['id'], name=o['name'], version=o['version'], pkg_type=o['type']) for o in json.loads(output)]
return []
class UpdateCheck(QThread):
signal = pyqtSignal(list)
def __init__(self, manager: SoftwareManager, check_interval: int, parent=None):
def __init__(self, check_interval: int, lock: Lock, check_file: bool, parent=None):
super(UpdateCheck, self).__init__(parent)
self.check_interval = check_interval
self.manager = manager
self.lock = lock
self.check_file = check_file
def _notify_updates(self):
self.lock.acquire()
try:
updates = list_updates()
if updates is not None:
self.signal.emit(updates)
finally:
self.lock.release()
time.sleep(self.check_interval)
def run(self):
while True:
updates = self.manager.list_updates()
self.signal.emit(updates)
time.sleep(self.check_interval)
if self.check_file:
if os.path.exists(TRAY_CHECK_FILE):
self._notify_updates()
try:
os.remove(TRAY_CHECK_FILE)
except:
traceback.print_exc()
else:
time.sleep(self.check_interval)
else:
self._notify_updates()
class TrayIcon(QSystemTrayIcon):
def __init__(self, i18n: I18n, manager: SoftwareManager, manage_window: ManageWindow, config: dict, screen_size: QSize):
def __init__(self, config: dict, screen_size: QSize, manage_process: Popen = None, settings_process: Popen = None):
super(TrayIcon, self).__init__()
self.i18n = i18n
self.manager = manager
self.i18n = generate_i18n(config, resource.get_path('locale/tray'))
self.screen_size = screen_size
self.manage_process = manage_process
self.settings_process = settings_process
if config['ui']['tray']['default_icon']:
self.icon_default = QIcon(config['ui']['tray']['default_icon'])
@@ -67,7 +101,7 @@ class TrayIcon(QSystemTrayIcon):
self.action_manage = self.menu.addAction(self.i18n['tray.action.manage'])
self.action_manage.triggered.connect(self.show_manage_window)
self.action_settings = self.menu.addAction(self.i18n['settings'].capitalize())
self.action_settings = self.menu.addAction(self.i18n['tray.settings'].capitalize())
self.action_settings.triggered.connect(self.show_settings_window)
self.action_about = self.menu.addAction(self.i18n['tray.action.about'])
@@ -82,10 +116,15 @@ class TrayIcon(QSystemTrayIcon):
self.dialog_about = None
self.settings_window = None
self.check_thread = UpdateCheck(check_interval=int(config['updates']['check_interval']), manager=self.manager)
self.check_lock = Lock()
self.check_thread = UpdateCheck(check_interval=int(config['updates']['check_interval']), check_file=False, lock=self.check_lock)
self.check_thread.signal.connect(self.notify_updates)
self.check_thread.start()
self.recheck_thread = UpdateCheck(check_interval=2, check_file=True, lock=self.check_lock)
self.recheck_thread.signal.connect(self.notify_updates)
self.recheck_thread.start()
self.last_updates = set()
self.update_notification = bool(config['system']['notifications'])
self.lock_notify = Lock()
@@ -93,10 +132,8 @@ class TrayIcon(QSystemTrayIcon):
self.activated.connect(self.handle_click)
self.set_default_tooltip()
self.manage_window = manage_window
def set_default_tooltip(self):
self.setToolTip('{} ({})'.format(self.i18n['manage_window.title'], __app_name__).lower())
self.setToolTip('{} ({})'.format(self.i18n['tray.action.manage'], __app_name__).lower())
def handle_click(self, reason):
if reason == self.Trigger:
@@ -109,7 +146,6 @@ class TrayIcon(QSystemTrayIcon):
self.notify_updates(self.manager.list_updates(), notify_user=notify_user)
def notify_updates(self, updates: List[PackageUpdate], notify_user: bool = True):
self.lock_notify.acquire()
try:
@@ -133,8 +169,8 @@ class TrayIcon(QSystemTrayIcon):
msg.write(self.i18n['notification.update{}'.format('' if n_updates == 1 else 's')].format(n_updates))
if len(ups_by_type) > 1:
for ptype, count in ups_by_type.items():
msg.write('\n * {} ( {} )'.format(ptype.capitalize(), count))
for ptype in sorted(ups_by_type):
msg.write('\n * {} ( {} )'.format(ptype, ups_by_type[ptype]))
msg.seek(0)
msg = msg.read()
@@ -155,25 +191,18 @@ class TrayIcon(QSystemTrayIcon):
self.lock_notify.release()
def show_manage_window(self):
if self.manage_window.isMinimized():
self.manage_window.setWindowState(Qt.WindowNoState)
elif not self.manage_window.isVisible():
self.manage_window.refresh_apps()
self.manage_window.show()
if self.manage_process is None:
self.manage_process = Popen([sys.executable, '{}/app.py'.format(ROOT_DIR)])
elif self.manage_process.poll() is not None: # it means it has finished
self.manage_process = None
self.show_manage_window()
def show_settings_window(self):
if self.settings_window:
self.settings_window.handle_display()
else:
self.settings_window = SettingsWindow(manager=self.manager,
i18n=self.i18n,
screen_size=self.screen_size,
tray=self,
window=self.manage_window)
self.settings_window.setMinimumWidth(int(self.screen_size.width() / 4))
self.settings_window.adjustSize()
qt_utils.centralize(self.settings_window)
self.settings_window.show()
if self.settings_process is None:
self.settings_process = Popen([sys.executable, '{}/app.py'.format(ROOT_DIR), '--settings'])
elif self.settings_process.poll() is not None: # it means it has finished
self.settings_process = None
self.show_settings_window()
def show_about(self):
if self.dialog_about is None: