mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 04:44:15 +02:00
refactoring async work
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
import time
|
||||
from abc import ABC, abstractmethod
|
||||
from argparse import Namespace
|
||||
from threading import Lock
|
||||
from typing import List, Dict
|
||||
|
||||
from fpakman.core.disk import DiskCacheLoader, DiskCacheLoaderFactory
|
||||
from fpakman.core.model import Application
|
||||
from fpakman.core.model import Application, ApplicationUpdate
|
||||
from fpakman.core.system import FpakmanProcess
|
||||
|
||||
|
||||
@@ -82,6 +80,10 @@ class ApplicationManager(ABC):
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def list_updates(self) -> List[ApplicationUpdate]:
|
||||
pass
|
||||
|
||||
|
||||
class GenericApplicationManager(ApplicationManager):
|
||||
|
||||
@@ -90,7 +92,6 @@ class GenericApplicationManager(ApplicationManager):
|
||||
self.managers = managers
|
||||
self.map = {m.get_app_type(): m for m in self.managers}
|
||||
self.disk_loader_factory = disk_loader_factory
|
||||
self.lock_read = Lock()
|
||||
self._enabled_map = {} if app_args.check_packaging_once else None
|
||||
self.prepare()
|
||||
|
||||
@@ -131,57 +132,48 @@ class GenericApplicationManager(ApplicationManager):
|
||||
return man.is_enabled()
|
||||
|
||||
def search(self, word: str, disk_loader: DiskCacheLoader = None) -> Dict[str, List[Application]]:
|
||||
self.lock_read.acquire()
|
||||
try:
|
||||
res = {'installed': [], 'new': []}
|
||||
res = {'installed': [], 'new': []}
|
||||
|
||||
norm_word = word.strip().lower()
|
||||
disk_loader = None
|
||||
norm_word = word.strip().lower()
|
||||
disk_loader = None
|
||||
|
||||
for man in self.managers:
|
||||
if self._is_enabled(man):
|
||||
if not disk_loader:
|
||||
disk_loader = self.disk_loader_factory.new()
|
||||
disk_loader.start()
|
||||
for man in self.managers:
|
||||
if self._is_enabled(man):
|
||||
if not disk_loader:
|
||||
disk_loader = self.disk_loader_factory.new()
|
||||
disk_loader.start()
|
||||
|
||||
apps_found = man.search(word=norm_word, disk_loader=disk_loader)
|
||||
res['installed'].extend(apps_found['installed'])
|
||||
res['new'].extend(apps_found['new'])
|
||||
apps_found = man.search(word=norm_word, disk_loader=disk_loader)
|
||||
res['installed'].extend(apps_found['installed'])
|
||||
res['new'].extend(apps_found['new'])
|
||||
|
||||
disk_loader.stop = True
|
||||
disk_loader.join()
|
||||
disk_loader.stop = True
|
||||
disk_loader.join()
|
||||
|
||||
for key in res:
|
||||
res[key] = self._sort(res[key], norm_word)
|
||||
for key in res:
|
||||
res[key] = self._sort(res[key], norm_word)
|
||||
|
||||
return res
|
||||
finally:
|
||||
self.lock_read.release()
|
||||
return res
|
||||
|
||||
def read_installed(self, disk_loader: DiskCacheLoader = None) -> List[Application]:
|
||||
self.lock_read.acquire()
|
||||
installed = []
|
||||
|
||||
try:
|
||||
installed = []
|
||||
disk_loader = None
|
||||
|
||||
disk_loader = None
|
||||
for man in self.managers:
|
||||
if self._is_enabled(man):
|
||||
if not disk_loader:
|
||||
disk_loader = self.disk_loader_factory.new()
|
||||
disk_loader.start()
|
||||
|
||||
for man in self.managers:
|
||||
if self._is_enabled(man):
|
||||
if not disk_loader:
|
||||
disk_loader = self.disk_loader_factory.new()
|
||||
disk_loader.start()
|
||||
installed.extend(man.read_installed(disk_loader=disk_loader))
|
||||
|
||||
installed.extend(man.read_installed(disk_loader=disk_loader))
|
||||
disk_loader.stop = True
|
||||
disk_loader.join()
|
||||
|
||||
disk_loader.stop = True
|
||||
disk_loader.join()
|
||||
installed.sort(key=lambda a: a.base_data.name.lower())
|
||||
|
||||
installed.sort(key=lambda a: a.base_data.name.lower())
|
||||
|
||||
return installed
|
||||
finally:
|
||||
self.lock_read.release()
|
||||
return installed
|
||||
|
||||
def can_downgrade(self):
|
||||
return True
|
||||
@@ -260,8 +252,17 @@ class GenericApplicationManager(ApplicationManager):
|
||||
return man.refresh(app, root_password)
|
||||
|
||||
def prepare(self):
|
||||
|
||||
if self.managers:
|
||||
for man in self.managers:
|
||||
if self._is_enabled(man):
|
||||
man.prepare()
|
||||
|
||||
def list_updates(self) -> List[ApplicationUpdate]:
|
||||
updates = []
|
||||
|
||||
if self.managers:
|
||||
for man in self.managers:
|
||||
if self._is_enabled(man):
|
||||
updates.extend(man.list_updates())
|
||||
|
||||
return updates
|
||||
|
||||
@@ -9,8 +9,8 @@ from fpakman.core.controller import ApplicationManager
|
||||
from fpakman.core.disk import DiskCacheLoader
|
||||
from fpakman.core.flatpak import flatpak
|
||||
from fpakman.core.flatpak.model import FlatpakApplication
|
||||
from fpakman.core.flatpak.worker import FlatpakAsyncDataLoader
|
||||
from fpakman.core.model import ApplicationData
|
||||
from fpakman.core.flatpak.worker import FlatpakAsyncDataLoader, FlatpakUpdateLoader
|
||||
from fpakman.core.model import ApplicationData, ApplicationUpdate
|
||||
from fpakman.core.system import FpakmanProcess
|
||||
from fpakman.util.cache import Cache
|
||||
|
||||
@@ -148,3 +148,33 @@ class FlatpakManager(ApplicationManager):
|
||||
|
||||
def prepare(self):
|
||||
flatpak.set_default_remotes()
|
||||
|
||||
def list_updates(self) -> List[ApplicationUpdate]:
|
||||
updates = []
|
||||
installed = flatpak.list_installed(extra_fields=False)
|
||||
|
||||
if installed:
|
||||
available_updates = flatpak.list_updates_as_str()
|
||||
|
||||
if available_updates:
|
||||
loaders = None
|
||||
|
||||
for app_json in installed:
|
||||
if app_json['id'] in available_updates:
|
||||
loader = FlatpakUpdateLoader(app=app_json, http_session=self.http_session)
|
||||
loader.start()
|
||||
|
||||
if loaders is None:
|
||||
loaders = []
|
||||
|
||||
loaders.append(loader)
|
||||
|
||||
if loaders:
|
||||
for loader in loaders:
|
||||
loader.join()
|
||||
app = loader.app
|
||||
updates.append(ApplicationUpdate(app_id='{}:{}'.format(app['id'], app['branch']),
|
||||
app_type='flatpak',
|
||||
version=app.get('version')))
|
||||
|
||||
return updates
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import re
|
||||
import subprocess
|
||||
from typing import List
|
||||
from typing import List, Set
|
||||
|
||||
from fpakman.core import system
|
||||
from fpakman.core.exception import NoInternetException
|
||||
@@ -8,7 +8,7 @@ from fpakman.core.exception import NoInternetException
|
||||
BASE_CMD = 'flatpak'
|
||||
|
||||
|
||||
def app_str_to_json(line: str, version: str) -> dict:
|
||||
def app_str_to_json(line: str, version: str, extra_fields: bool = True) -> dict:
|
||||
|
||||
app_array = line.split('\t')
|
||||
|
||||
@@ -17,18 +17,21 @@ def app_str_to_json(line: str, version: str) -> dict:
|
||||
'id': app_array[1],
|
||||
'version': app_array[2],
|
||||
'branch': app_array[3]}
|
||||
elif '1.0' <= version < '1.1':
|
||||
app = {'ref': app_array[0], 'options': app_array[1]}
|
||||
|
||||
ref_data = app['ref'].split('/')
|
||||
app['id'] = ref_data[0]
|
||||
app['arch'] = ref_data[1]
|
||||
app['branch'] = ref_data[2]
|
||||
app['name'] = ref_data[0].split('.')[-1]
|
||||
app['version'] = None
|
||||
elif '1.0' <= version < '1.1':
|
||||
|
||||
ref_data = app_array[0].split('/')
|
||||
|
||||
app = {'id': ref_data[0],
|
||||
'arch': ref_data[1],
|
||||
'name': ref_data[0].split('.')[-1],
|
||||
'ref': app_array[0],
|
||||
'options': app_array[1],
|
||||
'branch': ref_data[2],
|
||||
'version': None}
|
||||
elif '1.2' <= version < '1.3':
|
||||
app = {'name': app_array[1].strip().split('.')[-1],
|
||||
'id': app_array[1],
|
||||
app = {'id': app_array[1],
|
||||
'name': app_array[1].strip().split('.')[-1],
|
||||
'version': app_array[2],
|
||||
'branch': app_array[3],
|
||||
'arch': app_array[4],
|
||||
@@ -36,8 +39,9 @@ def app_str_to_json(line: str, version: str) -> dict:
|
||||
else:
|
||||
raise Exception('Unsupported version')
|
||||
|
||||
extra_fields = get_app_info_fields(app['id'], app['branch'], ['origin', 'arch', 'ref', 'commit'], check_runtime=True)
|
||||
app.update(extra_fields)
|
||||
if extra_fields:
|
||||
extra_fields = get_app_info_fields(app['id'], app['branch'], ['origin', 'arch', 'ref', 'commit'], check_runtime=True)
|
||||
app.update(extra_fields)
|
||||
|
||||
return app
|
||||
|
||||
@@ -81,13 +85,13 @@ def get_app_info(app_id: str, branch: str):
|
||||
return system.run_cmd('{} info {} {}'.format(BASE_CMD, app_id, branch))
|
||||
|
||||
|
||||
def list_installed() -> List[dict]:
|
||||
def list_installed(extra_fields: bool = True) -> List[dict]:
|
||||
apps_str = system.run_cmd('{} list'.format(BASE_CMD))
|
||||
|
||||
if apps_str:
|
||||
version = get_version()
|
||||
app_lines = apps_str.split('\n')
|
||||
return [app_str_to_json(line, version) for line in app_lines if line]
|
||||
return [app_str_to_json(line, version, extra_fields=extra_fields) for line in app_lines if line]
|
||||
|
||||
return []
|
||||
|
||||
@@ -215,4 +219,3 @@ def install_and_stream(app_id: str, origin: str):
|
||||
|
||||
def set_default_remotes():
|
||||
system.run_cmd('flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo')
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import time
|
||||
import traceback
|
||||
from threading import Thread
|
||||
|
||||
from colorama import Fore
|
||||
|
||||
from fpakman.core.controller import ApplicationManager
|
||||
from fpakman.core.flatpak import flatpak
|
||||
from fpakman.core.flatpak.constants import FLATHUB_API_URL, FLATHUB_URL
|
||||
from fpakman.core.flatpak.model import FlatpakApplication
|
||||
from fpakman.core.model import ApplicationStatus
|
||||
@@ -82,3 +84,41 @@ class FlatpakAsyncDataLoader(AsyncDataLoader):
|
||||
http_session=self.http_session,
|
||||
timeout=self.timeout,
|
||||
app=self.app)
|
||||
|
||||
|
||||
class FlatpakUpdateLoader(Thread):
|
||||
|
||||
def __init__(self, app: dict, http_session, attempts: int = 2, timeout: int = 20):
|
||||
super(FlatpakUpdateLoader, self).__init__(daemon=True)
|
||||
self.app = app
|
||||
self.http_session = http_session
|
||||
self.attempts = attempts
|
||||
self.timeout = timeout
|
||||
|
||||
def run(self):
|
||||
|
||||
if self.app.get('ref') is None:
|
||||
self.app.update(flatpak.get_app_info_fields(self.app['id'], self.app['branch'], fields=['ref'], check_runtime=True))
|
||||
else:
|
||||
self.app['runtime'] = self.app['ref'].startswith('runtime/')
|
||||
|
||||
if not self.app['runtime']:
|
||||
current_attempts = 0
|
||||
|
||||
while current_attempts < self.attempts:
|
||||
|
||||
current_attempts += 1
|
||||
|
||||
try:
|
||||
res = self.http_session.get('{}/apps/{}'.format(FLATHUB_API_URL, self.app['id']), timeout=self.timeout)
|
||||
|
||||
if res.status_code == 200 and res.text:
|
||||
data = res.json()
|
||||
|
||||
if data.get('currentReleaseVersion'):
|
||||
self.app['version'] = data['currentReleaseVersion']
|
||||
|
||||
break
|
||||
except:
|
||||
traceback.print_exc()
|
||||
time.sleep(0.5)
|
||||
|
||||
@@ -86,3 +86,14 @@ class Application(ABC):
|
||||
|
||||
def __str__(self):
|
||||
return '{} (id={}, name={})'.format(self.__class__.__name__, self.base_data.id, self.base_data.name)
|
||||
|
||||
|
||||
class ApplicationUpdate:
|
||||
|
||||
def __init__(self, app_id: str, version: str, app_type: str):
|
||||
self.id = app_id
|
||||
self.version = version
|
||||
self.type = app_type
|
||||
|
||||
def __str__(self):
|
||||
return '{} (id={}, type={}, new_version={})'.format(self.__class__.__name__, self.id, self.type, self.type)
|
||||
|
||||
@@ -7,7 +7,7 @@ from typing import Dict, List
|
||||
from fpakman.core import disk
|
||||
from fpakman.core.controller import ApplicationManager
|
||||
from fpakman.core.disk import DiskCacheLoader
|
||||
from fpakman.core.model import ApplicationData, Application
|
||||
from fpakman.core.model import ApplicationData, Application, ApplicationUpdate
|
||||
from fpakman.core.snap import snap
|
||||
from fpakman.core.snap.model import SnapApplication
|
||||
from fpakman.core.snap.worker import SnapAsyncDataLoader
|
||||
@@ -131,3 +131,6 @@ class SnapManager(ApplicationManager):
|
||||
|
||||
def prepare(self):
|
||||
pass
|
||||
|
||||
def list_updates(self) -> List[ApplicationUpdate]:
|
||||
return []
|
||||
|
||||
@@ -119,9 +119,6 @@ class AppsTable(QTableWidget):
|
||||
menu_row.exec_()
|
||||
|
||||
def fill_async_data(self):
|
||||
|
||||
self.lock_async_data.acquire()
|
||||
|
||||
if self.window.apps:
|
||||
|
||||
for idx, app_v in enumerate(self.window.apps):
|
||||
@@ -142,8 +139,6 @@ class AppsTable(QTableWidget):
|
||||
|
||||
self.window.resize_and_center()
|
||||
|
||||
self.lock_async_data.release()
|
||||
|
||||
def get_selected_app(self) -> ApplicationView:
|
||||
return self.window.apps[self.currentRow()]
|
||||
|
||||
@@ -202,9 +197,9 @@ class AppsTable(QTableWidget):
|
||||
if not icon_was_cached or not os.path.exists(app.model.get_disk_icon_path()):
|
||||
self.window.manager.cache_to_disk(app=app.model, icon_bytes=icon_data['bytes'], only_icon=True)
|
||||
|
||||
def update_apps(self, app_views: List[ApplicationView]):
|
||||
self.setEnabled(True)
|
||||
def update_apps(self, app_views: List[ApplicationView], update_check_enabled: bool = True):
|
||||
self.setRowCount(len(app_views) if app_views else 0)
|
||||
self.setEnabled(True)
|
||||
|
||||
if app_views:
|
||||
for idx, app_v in enumerate(app_views):
|
||||
@@ -214,7 +209,11 @@ class AppsTable(QTableWidget):
|
||||
self._set_col_type(idx, app_v)
|
||||
self._set_col_installed(idx, app_v)
|
||||
|
||||
col_update = UpdateToggleButton(app_v, self.window, self.window.locale_keys, app_v.model.update) if app_v.model.update else None
|
||||
col_update = None
|
||||
|
||||
if update_check_enabled and app_v.model.update:
|
||||
col_update = UpdateToggleButton(app_v, self.window, self.window.locale_keys, app_v.model.update)
|
||||
|
||||
self.setCellWidget(idx, 5, col_update)
|
||||
|
||||
def _set_col_installed(self, idx: int, app_v: ApplicationView):
|
||||
|
||||
@@ -6,9 +6,10 @@ from PyQt5.QtCore import QThread, pyqtSignal, QCoreApplication, Qt, QSize
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QSystemTrayIcon, QMenu
|
||||
|
||||
from fpakman import __app_name__
|
||||
from fpakman.core import resource, system
|
||||
from fpakman.core.controller import ApplicationManager
|
||||
from fpakman.core.model import Application
|
||||
from fpakman.core.model import ApplicationUpdate
|
||||
from fpakman.util.cache import Cache
|
||||
from fpakman.view.qt.about import AboutDialog
|
||||
from fpakman.view.qt.window import ManageWindow
|
||||
@@ -27,9 +28,7 @@ class UpdateCheck(QThread):
|
||||
|
||||
while True:
|
||||
|
||||
apps = self.manager.read_installed()
|
||||
|
||||
updates = [app for app in apps if app.update]
|
||||
updates = self.manager.list_updates()
|
||||
|
||||
if updates:
|
||||
self.signal.emit(updates)
|
||||
@@ -66,30 +65,32 @@ class TrayIcon(QSystemTrayIcon):
|
||||
self.setContextMenu(self.menu)
|
||||
|
||||
self.manage_window = None
|
||||
self.dialog_about = None
|
||||
self.check_thread = UpdateCheck(check_interval=check_interval, manager=self.manager)
|
||||
self.check_thread.signal.connect(self.notify_updates)
|
||||
self.check_thread.start()
|
||||
|
||||
self.dialog_about = None
|
||||
|
||||
self.last_updates = set()
|
||||
self.update_notification = update_notification
|
||||
self.lock_notify = Lock()
|
||||
|
||||
self.activated.connect(self.handle_click)
|
||||
self.set_default_tooltip()
|
||||
|
||||
def set_default_tooltip(self):
|
||||
self.setToolTip('{} ({})'.format(self.locale_keys['manage_window.title'], __app_name__))
|
||||
|
||||
def handle_click(self, reason):
|
||||
if reason == self.Trigger:
|
||||
self.show_manage_window()
|
||||
|
||||
def notify_updates(self, updates: List[Application]):
|
||||
def notify_updates(self, updates: List[ApplicationUpdate]):
|
||||
|
||||
self.lock_notify.acquire()
|
||||
|
||||
try:
|
||||
if len(updates) > 0:
|
||||
|
||||
update_keys = {'{}:{}'.format(app.base_data.id, app.base_data.version) for app in updates}
|
||||
update_keys = {'{}:{}:{}'.format(up.type, up.id, up.version) for up in updates}
|
||||
|
||||
new_icon = self.icon_update
|
||||
|
||||
@@ -103,7 +104,7 @@ class TrayIcon(QSystemTrayIcon):
|
||||
|
||||
else:
|
||||
new_icon = self.icon_default
|
||||
self.setToolTip(None)
|
||||
self.set_default_tooltip()
|
||||
|
||||
if self.icon().cacheKey() != new_icon.cacheKey(): # changes the icon if needed
|
||||
self.setIcon(new_icon)
|
||||
|
||||
@@ -302,6 +302,8 @@ class VerifyModels(QThread):
|
||||
if stop_at <= datetime.utcnow():
|
||||
break
|
||||
|
||||
time.sleep(0.1)
|
||||
|
||||
self.apps = None
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import operator
|
||||
from functools import reduce
|
||||
from threading import Lock
|
||||
from typing import List, Set
|
||||
|
||||
from PyQt5.QtCore import QEvent, Qt
|
||||
@@ -31,7 +30,6 @@ class ManageWindow(QWidget):
|
||||
self.locale_keys = locale_keys
|
||||
self.manager = manager
|
||||
self.tray_icon = tray_icon
|
||||
self.thread_lock = Lock()
|
||||
self.working = False # restrict the number of threaded actions
|
||||
self.apps = []
|
||||
self.label_flatpak = None
|
||||
@@ -42,7 +40,6 @@ class ManageWindow(QWidget):
|
||||
|
||||
self.icon_flathub = QIcon(resource.get_path('img/logo.svg'))
|
||||
self.resize(ManageWindow.__BASE_HEIGHT__, ManageWindow.__BASE_HEIGHT__)
|
||||
self.setWindowTitle(locale_keys['manage_window.title'])
|
||||
self.setWindowIcon(self.icon_flathub)
|
||||
|
||||
self.layout = QVBoxLayout()
|
||||
@@ -111,7 +108,7 @@ class ManageWindow(QWidget):
|
||||
self.bt_upgrade.setIcon(QIcon(resource.get_path('img/update_green.svg')))
|
||||
self.bt_upgrade.setEnabled(False)
|
||||
self.bt_upgrade.clicked.connect(self.update_selected)
|
||||
toolbar.addWidget(self.bt_upgrade)
|
||||
self.ref_bt_upgrade = toolbar.addWidget(self.bt_upgrade)
|
||||
|
||||
self.layout.addWidget(toolbar)
|
||||
|
||||
@@ -235,25 +232,6 @@ class ManageWindow(QWidget):
|
||||
self.hide()
|
||||
self._handle_console_option(False)
|
||||
|
||||
def _acquire_lock(self):
|
||||
|
||||
self.thread_lock.acquire()
|
||||
|
||||
if not self.working:
|
||||
self.working = True
|
||||
|
||||
self.thread_lock.release()
|
||||
return self.working
|
||||
|
||||
def _release_lock(self):
|
||||
|
||||
self.thread_lock.acquire()
|
||||
|
||||
if self.working:
|
||||
self.working = False
|
||||
|
||||
self.thread_lock.release()
|
||||
|
||||
def _handle_console(self, checked: bool):
|
||||
|
||||
if checked:
|
||||
@@ -271,69 +249,59 @@ class ManageWindow(QWidget):
|
||||
self.textarea_output.hide()
|
||||
|
||||
def refresh_apps(self, keep_console: bool = True):
|
||||
self.filter_types.clear()
|
||||
self.input_search.clear()
|
||||
|
||||
if self._acquire_lock():
|
||||
self.filter_types.clear()
|
||||
self.input_search.clear()
|
||||
if not keep_console:
|
||||
self._handle_console_option(False)
|
||||
|
||||
if not keep_console:
|
||||
self._handle_console_option(False)
|
||||
|
||||
self.ref_checkbox_updates.setVisible(False)
|
||||
self.ref_checkbox_only_apps.setVisible(False)
|
||||
self._begin_action(self.locale_keys['manage_window.status.refreshing'], clear_filters=True)
|
||||
|
||||
self.thread_refresh.start()
|
||||
self.ref_checkbox_updates.setVisible(False)
|
||||
self.ref_checkbox_only_apps.setVisible(False)
|
||||
self._begin_action(self.locale_keys['manage_window.status.refreshing'], clear_filters=True)
|
||||
self.thread_refresh.start()
|
||||
|
||||
def _finish_refresh_apps(self, apps: List[Application]):
|
||||
self.update_apps(apps)
|
||||
self.finish_action()
|
||||
self.ref_checkbox_only_apps.setVisible(True)
|
||||
self._release_lock()
|
||||
self.ref_bt_upgrade.setVisible(True)
|
||||
|
||||
def uninstall_app(self, app: ApplicationView):
|
||||
if self._acquire_lock():
|
||||
pwd = None
|
||||
requires_root = self.manager.requires_root('uninstall', self.table_apps.get_selected_app().model)
|
||||
|
||||
pwd = None
|
||||
requires_root = self.manager.requires_root('uninstall', self.table_apps.get_selected_app().model)
|
||||
if not is_root() and requires_root:
|
||||
pwd, ok = ask_root_password(self.locale_keys)
|
||||
|
||||
if not is_root() and requires_root:
|
||||
pwd, ok = ask_root_password(self.locale_keys)
|
||||
if not ok:
|
||||
return
|
||||
|
||||
if not ok:
|
||||
self._release_lock()
|
||||
return
|
||||
self._handle_console_option(True)
|
||||
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.uninstalling'], app.model.base_data.name))
|
||||
|
||||
self._handle_console_option(True)
|
||||
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.uninstalling'], app.model.base_data.name))
|
||||
|
||||
self.thread_uninstall.app = app
|
||||
self.thread_uninstall.root_password = pwd
|
||||
self.thread_uninstall.start()
|
||||
self.thread_uninstall.app = app
|
||||
self.thread_uninstall.root_password = pwd
|
||||
self.thread_uninstall.start()
|
||||
|
||||
def refresh(self, app: ApplicationView):
|
||||
if self._acquire_lock():
|
||||
pwd = None
|
||||
requires_root = self.manager.requires_root('refresh', self.table_apps.get_selected_app().model)
|
||||
|
||||
pwd = None
|
||||
requires_root = self.manager.requires_root('refresh', self.table_apps.get_selected_app().model)
|
||||
if not is_root() and requires_root:
|
||||
pwd, ok = ask_root_password(self.locale_keys)
|
||||
|
||||
if not is_root() and requires_root:
|
||||
pwd, ok = ask_root_password(self.locale_keys)
|
||||
if not ok:
|
||||
return
|
||||
|
||||
if not ok:
|
||||
self._release_lock()
|
||||
return
|
||||
self._handle_console_option(True)
|
||||
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.refreshing'], app.model.base_data.name))
|
||||
|
||||
self._handle_console_option(True)
|
||||
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.refreshing'], app.model.base_data.name))
|
||||
|
||||
self.thread_refresh_app.app = app
|
||||
self.thread_refresh_app.root_password = pwd
|
||||
self.thread_refresh_app.start()
|
||||
self.thread_refresh_app.app = app
|
||||
self.thread_refresh_app.root_password = pwd
|
||||
self.thread_refresh_app.start()
|
||||
|
||||
def _finish_uninstall(self, success: bool):
|
||||
self.finish_action()
|
||||
self._release_lock()
|
||||
|
||||
if success:
|
||||
if self._can_notify_user():
|
||||
@@ -353,7 +321,6 @@ class ManageWindow(QWidget):
|
||||
|
||||
def _finish_downgrade(self, success: bool):
|
||||
self.finish_action()
|
||||
self._release_lock()
|
||||
|
||||
if success:
|
||||
if self._can_notify_user():
|
||||
@@ -365,17 +332,16 @@ class ManageWindow(QWidget):
|
||||
if self._can_notify_user():
|
||||
system.notify_user(self.locale_keys['notification.downgrade.failed'])
|
||||
|
||||
self.change_update_state(notify_tray=False)
|
||||
self.change_update_state()
|
||||
self.checkbox_console.setChecked(True)
|
||||
|
||||
def _finish_refresh(self, success: bool):
|
||||
self.finish_action()
|
||||
self._release_lock()
|
||||
|
||||
if success:
|
||||
self.refresh_apps()
|
||||
else:
|
||||
self.change_update_state(notify_tray=False)
|
||||
self.change_update_state()
|
||||
self.checkbox_console.setChecked(True)
|
||||
|
||||
def apply_filters(self):
|
||||
@@ -399,11 +365,9 @@ class ManageWindow(QWidget):
|
||||
self.table_apps.change_headers_policy()
|
||||
self.resize_and_center(accept_lower_width=visible_apps > 0)
|
||||
|
||||
def change_update_state(self, notify_tray: bool = True, change_filters: bool = True):
|
||||
|
||||
def change_update_state(self, change_filters: bool = True):
|
||||
enable_bt_update = False
|
||||
|
||||
app_updates, library_updates = 0, 0
|
||||
app_updates, library_updates, not_installed = 0, 0, 0
|
||||
|
||||
for app_v in self.apps:
|
||||
if app_v.model.update:
|
||||
@@ -412,28 +376,33 @@ class ManageWindow(QWidget):
|
||||
else:
|
||||
app_updates += 1
|
||||
|
||||
if not app_v.model.installed:
|
||||
not_installed += 1
|
||||
|
||||
for app_v in self.apps:
|
||||
if app_v.visible and app_v.update_checked:
|
||||
if not_installed == 0 and app_v.visible and app_v.update_checked:
|
||||
enable_bt_update = True
|
||||
break
|
||||
|
||||
self.bt_upgrade.setEnabled(enable_bt_update)
|
||||
|
||||
total_updates = app_updates + library_updates
|
||||
|
||||
if total_updates > 0:
|
||||
self.label_updates.setPixmap(QPixmap(resource.get_path('img/exclamation.svg')).scaled(16, 16, Qt.KeepAspectRatio, Qt.SmoothTransformation))
|
||||
self.label_updates.setToolTip('{}: {} ( {} {} | {} {} )'.format(self.locale_keys['manage_window.label.updates'],
|
||||
total_updates,
|
||||
app_updates,
|
||||
self.locale_keys['manage_window.checkbox.only_apps'].lower(),
|
||||
library_updates,
|
||||
self.locale_keys['others'].lower()))
|
||||
total_updates,
|
||||
app_updates,
|
||||
self.locale_keys['manage_window.checkbox.only_apps'].lower(),
|
||||
library_updates,
|
||||
self.locale_keys['others'].lower()))
|
||||
|
||||
if not self.ref_checkbox_updates.isVisible():
|
||||
self.ref_checkbox_updates.setVisible(True)
|
||||
if not_installed == 0:
|
||||
if not self.ref_checkbox_updates.isVisible():
|
||||
self.ref_checkbox_updates.setVisible(True)
|
||||
|
||||
if change_filters and not self.checkbox_updates.isChecked():
|
||||
self.checkbox_updates.setChecked(True)
|
||||
if change_filters and not self.checkbox_updates.isChecked():
|
||||
self.checkbox_updates.setChecked(True)
|
||||
|
||||
if change_filters and library_updates > 0 and self.checkbox_only_apps.isChecked():
|
||||
self.checkbox_only_apps.setChecked(False)
|
||||
@@ -442,9 +411,6 @@ class ManageWindow(QWidget):
|
||||
self.ref_checkbox_updates.setVisible(False)
|
||||
self.label_updates.setPixmap(QPixmap())
|
||||
|
||||
if notify_tray:
|
||||
self.tray_icon.notify_updates([app.model for app in self.apps if app.model.update])
|
||||
|
||||
def centralize(self):
|
||||
geo = self.frameGeometry()
|
||||
screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
|
||||
@@ -452,7 +418,7 @@ class ManageWindow(QWidget):
|
||||
geo.moveCenter(center_point)
|
||||
self.move(geo.topLeft())
|
||||
|
||||
def update_apps(self, apps: List[Application]):
|
||||
def update_apps(self, apps: List[Application], update_check_enabled: bool = True):
|
||||
self.apps = []
|
||||
|
||||
napps = 0 # number of apps (not libraries)
|
||||
@@ -473,7 +439,7 @@ class ManageWindow(QWidget):
|
||||
self.checkbox_only_apps.setChecked(True)
|
||||
|
||||
self._update_type_filters(available_types)
|
||||
self.table_apps.update_apps(self.apps)
|
||||
self.table_apps.update_apps(self.apps, update_check_enabled=update_check_enabled)
|
||||
self.apply_filters()
|
||||
self.change_update_state()
|
||||
self.resize_and_center()
|
||||
@@ -510,22 +476,19 @@ class ManageWindow(QWidget):
|
||||
self.centralize()
|
||||
|
||||
def update_selected(self):
|
||||
if self.apps:
|
||||
|
||||
if self._acquire_lock():
|
||||
if self.apps:
|
||||
to_update = [app_v for app_v in self.apps if app_v.visible and app_v.update_checked]
|
||||
|
||||
to_update = [app_v for app_v in self.apps if app_v.visible and app_v.update_checked]
|
||||
if to_update:
|
||||
self._handle_console_option(True)
|
||||
|
||||
if to_update:
|
||||
self._handle_console_option(True)
|
||||
|
||||
self._begin_action(self.locale_keys['manage_window.status.upgrading'])
|
||||
self.thread_update.apps_to_update = to_update
|
||||
self.thread_update.start()
|
||||
self._begin_action(self.locale_keys['manage_window.status.upgrading'])
|
||||
self.thread_update.apps_to_update = to_update
|
||||
self.thread_update.start()
|
||||
|
||||
def _finish_update_selected(self, success: bool, updated: int):
|
||||
self.finish_action()
|
||||
self._release_lock()
|
||||
|
||||
if success:
|
||||
if self._can_notify_user():
|
||||
@@ -581,51 +544,43 @@ class ManageWindow(QWidget):
|
||||
self.checkbox_updates.setEnabled(True)
|
||||
|
||||
def downgrade_app(self, app: ApplicationView):
|
||||
if self._acquire_lock():
|
||||
pwd = None
|
||||
requires_root = self.manager.requires_root('downgrade', self.table_apps.get_selected_app().model)
|
||||
|
||||
pwd = None
|
||||
requires_root = self.manager.requires_root('downgrade', self.table_apps.get_selected_app().model)
|
||||
if not is_root() and requires_root:
|
||||
pwd, ok = ask_root_password(self.locale_keys)
|
||||
|
||||
if not is_root() and requires_root:
|
||||
pwd, ok = ask_root_password(self.locale_keys)
|
||||
if not ok:
|
||||
return
|
||||
|
||||
if not ok:
|
||||
self._release_lock()
|
||||
return
|
||||
self._handle_console_option(True)
|
||||
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.downgrading'], app.model.base_data.name))
|
||||
|
||||
self._handle_console_option(True)
|
||||
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.downgrading'], app.model.base_data.name))
|
||||
|
||||
self.thread_downgrade.app = app
|
||||
self.thread_downgrade.root_password = pwd
|
||||
self.thread_downgrade.start()
|
||||
self.thread_downgrade.app = app
|
||||
self.thread_downgrade.root_password = pwd
|
||||
self.thread_downgrade.start()
|
||||
|
||||
def get_app_info(self, app: dict):
|
||||
self._handle_console_option(False)
|
||||
self._begin_action(self.locale_keys['manage_window.status.info'])
|
||||
|
||||
if self._acquire_lock():
|
||||
self._handle_console_option(False)
|
||||
self._begin_action(self.locale_keys['manage_window.status.info'])
|
||||
|
||||
self.thread_get_info.app = app
|
||||
self.thread_get_info.start()
|
||||
self.thread_get_info.app = app
|
||||
self.thread_get_info.start()
|
||||
|
||||
def get_app_history(self, app: dict):
|
||||
if self._acquire_lock():
|
||||
self._handle_console_option(False)
|
||||
self._begin_action(self.locale_keys['manage_window.status.history'])
|
||||
self._handle_console_option(False)
|
||||
self._begin_action(self.locale_keys['manage_window.status.history'])
|
||||
|
||||
self.thread_get_history.app = app
|
||||
self.thread_get_history.start()
|
||||
self.thread_get_history.app = app
|
||||
self.thread_get_history.start()
|
||||
|
||||
def _finish_get_info(self, app_info: dict):
|
||||
self._release_lock()
|
||||
self.finish_action()
|
||||
self.change_update_state()
|
||||
dialog_info = InfoDialog(app_info, self.table_apps.get_selected_app_icon(), self.locale_keys, self.table_apps.get_selected_app().model.get_type(), self.screen_size)
|
||||
dialog_info.exec_()
|
||||
|
||||
def _finish_get_history(self, app: dict):
|
||||
self._release_lock()
|
||||
self.finish_action()
|
||||
self.change_update_state()
|
||||
|
||||
@@ -641,7 +596,7 @@ class ManageWindow(QWidget):
|
||||
|
||||
word = self.input_search.text().strip()
|
||||
|
||||
if word and self._acquire_lock():
|
||||
if word:
|
||||
self._handle_console_option(False)
|
||||
self.ref_checkbox_only_apps.setVisible(False)
|
||||
self.ref_checkbox_updates.setVisible(False)
|
||||
@@ -651,34 +606,30 @@ class ManageWindow(QWidget):
|
||||
self.thread_search.start()
|
||||
|
||||
def _finish_search(self, apps_found: List[Application]):
|
||||
self._release_lock()
|
||||
self.finish_action()
|
||||
self.update_apps(apps_found)
|
||||
self.ref_bt_upgrade.setVisible(False)
|
||||
self.update_apps(apps_found, update_check_enabled=False)
|
||||
|
||||
def install_app(self, app: ApplicationView):
|
||||
if self._acquire_lock():
|
||||
pwd = None
|
||||
requires_root = self.manager.requires_root('install', self.table_apps.get_selected_app().model)
|
||||
|
||||
pwd = None
|
||||
requires_root = self.manager.requires_root('install', self.table_apps.get_selected_app().model)
|
||||
if not is_root() and requires_root:
|
||||
pwd, ok = ask_root_password(self.locale_keys)
|
||||
|
||||
if not is_root() and requires_root:
|
||||
pwd, ok = ask_root_password(self.locale_keys)
|
||||
if not ok:
|
||||
return
|
||||
|
||||
if not ok:
|
||||
self._release_lock()
|
||||
return
|
||||
self._handle_console_option(True)
|
||||
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.installing'], app.model.base_data.name))
|
||||
|
||||
self._handle_console_option(True)
|
||||
self._begin_action('{} {}'.format(self.locale_keys['manage_window.status.installing'], app.model.base_data.name))
|
||||
|
||||
self.thread_install.app = app
|
||||
self.thread_install.root_password = pwd
|
||||
self.thread_install.start()
|
||||
self.thread_install.app = app
|
||||
self.thread_install.root_password = pwd
|
||||
self.thread_install.start()
|
||||
|
||||
def _finish_install(self, success: bool):
|
||||
self.input_search.setText('')
|
||||
self.finish_action()
|
||||
self._release_lock()
|
||||
|
||||
if success:
|
||||
if self._can_notify_user():
|
||||
|
||||
Reference in New Issue
Block a user