mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-08 09:44:15 +02:00
improving initialization time and reducing async overload
This commit is contained in:
@@ -1,20 +1,24 @@
|
||||
from threading import Lock
|
||||
from typing import List
|
||||
|
||||
from PyQt5.QtCore import Qt, QUrl
|
||||
from PyQt5.QtGui import QPixmap, QIcon, QColor, QCursor
|
||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkAccessManager
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest
|
||||
from PyQt5.QtWidgets import QTableWidget, QTableView, QMenu, QAction, QTableWidgetItem, QToolButton, QWidget, \
|
||||
QHeaderView, QLabel
|
||||
|
||||
from fpakman.core import resource, util
|
||||
from fpakman.core import resource
|
||||
from fpakman.core.model import FlatpakApplication, ApplicationStatus
|
||||
from fpakman.util.cache import Cache
|
||||
from fpakman.view.qt import dialog
|
||||
from fpakman.view.qt.view_model import ApplicationView, ApplicationViewStatus
|
||||
|
||||
|
||||
class UpdateToggleButton(QToolButton):
|
||||
|
||||
def __init__(self, model: dict, root: QWidget, locale_keys: dict, checked: bool = True):
|
||||
def __init__(self, app_view: ApplicationView, root: QWidget, locale_keys: dict, checked: bool = True):
|
||||
super(UpdateToggleButton, self).__init__()
|
||||
self.app = model
|
||||
self.app_view = app_view
|
||||
self.root = root
|
||||
self.setCheckable(True)
|
||||
self.clicked.connect(self.change_state)
|
||||
@@ -28,14 +32,14 @@ class UpdateToggleButton(QToolButton):
|
||||
self.click()
|
||||
|
||||
def change_state(self, not_checked: bool):
|
||||
self.app['update_checked'] = not not_checked
|
||||
self.app_view.updated_checked = not not_checked
|
||||
self.setIcon(self.icon_on if not not_checked else self.icon_off)
|
||||
self.root.change_update_state()
|
||||
|
||||
|
||||
class AppsTable(QTableWidget):
|
||||
|
||||
def __init__(self, parent: QWidget):
|
||||
def __init__(self, parent: QWidget, icon_cache: Cache):
|
||||
super(AppsTable, self).__init__()
|
||||
self.setParent(parent)
|
||||
self.window = parent
|
||||
@@ -44,7 +48,7 @@ class AppsTable(QTableWidget):
|
||||
'manage_window.columns.latest_version',
|
||||
'flatpak.info.branch',
|
||||
'flatpak.info.arch',
|
||||
'flatpak.info.id',
|
||||
'flatpak.info.description',
|
||||
'flatpak.info.origin',
|
||||
'manage_window.columns.installed',
|
||||
'manage_window.columns.update']]
|
||||
@@ -60,7 +64,8 @@ class AppsTable(QTableWidget):
|
||||
self.network_man = QNetworkAccessManager()
|
||||
self.network_man.finished.connect(self._load_icon)
|
||||
|
||||
self.icon_cache = {}
|
||||
self.icon_cache = icon_cache
|
||||
self.lock_async_data = Lock()
|
||||
|
||||
def contextMenuEvent(self, QContextMenuEvent): # selected row right click event
|
||||
|
||||
@@ -68,7 +73,7 @@ class AppsTable(QTableWidget):
|
||||
|
||||
menu_row = QMenu()
|
||||
|
||||
if app['model']['installed']:
|
||||
if app.model.installed:
|
||||
action_info = QAction(self.window.locale_keys["manage_window.apps_table.row.actions.info"])
|
||||
action_info.setIcon(QIcon(resource.get_path('img/info.svg')))
|
||||
action_info.triggered.connect(self._get_app_info)
|
||||
@@ -84,7 +89,7 @@ class AppsTable(QTableWidget):
|
||||
action_uninstall.triggered.connect(self._uninstall_app)
|
||||
menu_row.addAction(action_uninstall)
|
||||
|
||||
if not app['model']['runtime']: # not available for runtimes
|
||||
if isinstance(app.model, FlatpakApplication) and not app.model.runtime: # not available for runtimes
|
||||
action_downgrade = QAction(self.window.locale_keys["manage_window.apps_table.row.actions.downgrade"])
|
||||
action_downgrade.triggered.connect(self._downgrade_app)
|
||||
action_downgrade.setIcon(QIcon(resource.get_path('img/downgrade.svg')))
|
||||
@@ -99,25 +104,54 @@ class AppsTable(QTableWidget):
|
||||
menu_row.popup(QCursor.pos())
|
||||
menu_row.exec_()
|
||||
|
||||
def get_selected_app(self):
|
||||
def fill_async_data(self):
|
||||
|
||||
self.lock_async_data.acquire()
|
||||
|
||||
if self.window.apps:
|
||||
for idx, app_v in enumerate(self.window.apps):
|
||||
if app_v.visible and app_v.status == ApplicationViewStatus.LOADING and app_v.model.status == ApplicationStatus.READY:
|
||||
self.network_man.get(QNetworkRequest(QUrl(app_v.model.base_data.icon_url)))
|
||||
self.item(idx, 2).setText(app_v.model.base_data.latest_version)
|
||||
|
||||
desc = app_v.get_async_attr('description', strip_html=True)
|
||||
self.item(idx, 5).setText(desc)
|
||||
self.item(idx, 5).setToolTip(desc)
|
||||
app_v.status = ApplicationViewStatus.READY
|
||||
|
||||
visible, ready = 0, 0
|
||||
|
||||
for app_v in self.window.apps:
|
||||
if app_v.visible:
|
||||
visible += 1
|
||||
|
||||
if app_v.status == ApplicationViewStatus.READY:
|
||||
ready += 1
|
||||
|
||||
if ready == visible:
|
||||
self.window.resize_and_center()
|
||||
|
||||
self.lock_async_data.release()
|
||||
|
||||
def get_selected_app(self) -> ApplicationView:
|
||||
return self.window.apps[self.currentRow()]
|
||||
|
||||
def get_selected_app_icon(self):
|
||||
def get_selected_app_icon(self) -> QIcon:
|
||||
return self.item(self.currentRow(), 0).icon()
|
||||
|
||||
def _uninstall_app(self):
|
||||
selected_app = self.get_selected_app()
|
||||
|
||||
if dialog.ask_confirmation(title=self.window.locale_keys['manage_window.apps_table.row.actions.uninstall.popup.title'],
|
||||
body=self.window.locale_keys['manage_window.apps_table.row.actions.uninstall.popup.body'].format(selected_app['model']['name']),
|
||||
body=self.window.locale_keys['manage_window.apps_table.row.actions.uninstall.popup.body'].format(selected_app.model.base_data.name),
|
||||
locale_keys=self.window.locale_keys):
|
||||
self.window.uninstall_app(selected_app['model']['ref'])
|
||||
self.window.uninstall_app(selected_app)
|
||||
|
||||
def _downgrade_app(self):
|
||||
selected_app = self.get_selected_app()
|
||||
|
||||
if dialog.ask_confirmation(title=self.window.locale_keys['manage_window.apps_table.row.actions.downgrade'],
|
||||
body=self.window.locale_keys['manage_window.apps_table.row.actions.downgrade.popup.body'].format(selected_app['model']['name']),
|
||||
body=self.window.locale_keys['manage_window.apps_table.row.actions.downgrade.popup.body'].format(selected_app.model.base_data.name),
|
||||
locale_keys=self.window.locale_keys):
|
||||
self.window.downgrade_app(selected_app)
|
||||
|
||||
@@ -132,94 +166,92 @@ class AppsTable(QTableWidget):
|
||||
|
||||
def _load_icon(self, http_response):
|
||||
icon_url = http_response.url().toString()
|
||||
pixmap = QPixmap()
|
||||
pixmap.loadFromData(http_response.readAll())
|
||||
icon = QIcon(pixmap)
|
||||
self.icon_cache[icon_url] = icon
|
||||
|
||||
for idx, app in enumerate(self.window.apps):
|
||||
if app['model']['icon'] == icon_url:
|
||||
self.item(idx, 0).setIcon(icon)
|
||||
self.window.resize_and_center()
|
||||
break
|
||||
if not self.icon_cache.get(icon_url):
|
||||
pixmap = QPixmap()
|
||||
pixmap.loadFromData(http_response.readAll())
|
||||
icon = QIcon(pixmap)
|
||||
self.icon_cache.add(icon_url, icon)
|
||||
|
||||
def update_apps(self, apps: List[dict]):
|
||||
for idx, app in enumerate(self.window.apps):
|
||||
if app.model.base_data.icon_url == icon_url:
|
||||
self.item(idx, 0).setIcon(icon)
|
||||
break
|
||||
|
||||
def update_apps(self, app_views: List[ApplicationView]):
|
||||
self.setEnabled(True)
|
||||
self.setRowCount(len(apps) if apps else 0)
|
||||
self.setRowCount(len(app_views) if app_views else 0)
|
||||
|
||||
if apps:
|
||||
for idx, app in enumerate(apps):
|
||||
|
||||
tooltip = util.strip_html(app['model']['description']) if app['model']['description'] else None
|
||||
if app_views:
|
||||
for idx, app_v in enumerate(app_views):
|
||||
|
||||
col_name = QTableWidgetItem()
|
||||
col_name.setText(app['model']['name'])
|
||||
col_name.setText(app_v.model.base_data.name)
|
||||
col_name.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
col_name.setToolTip(tooltip)
|
||||
|
||||
if not app['model']['icon']:
|
||||
if not app_v.model.base_data.icon_url:
|
||||
col_name.setIcon(self.icon_flathub)
|
||||
else:
|
||||
cached_icon = self.icon_cache.get(app['model']['icon'])
|
||||
cached_icon = self.icon_cache.get(app_v.model.base_data.icon_url)
|
||||
|
||||
if cached_icon:
|
||||
col_name.setIcon(cached_icon)
|
||||
else:
|
||||
col_name.setIcon(self.icon_flathub)
|
||||
self.network_man.get(QNetworkRequest(QUrl(app['model']['icon'])))
|
||||
|
||||
self.setItem(idx, 0, col_name)
|
||||
|
||||
col_version = QTableWidgetItem()
|
||||
col_version.setText(app['model']['version'])
|
||||
col_version.setText(app_v.model.base_data.version)
|
||||
col_version.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
col_version.setToolTip(tooltip)
|
||||
self.setItem(idx, 1, col_version)
|
||||
|
||||
col_release = QTableWidgetItem()
|
||||
col_release.setText(app['model']['latest_version'])
|
||||
col_release.setText(app_v.get_async_attr('latest_version'))
|
||||
col_release.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
col_release.setToolTip(tooltip)
|
||||
self.setItem(idx, 2, col_release)
|
||||
|
||||
if app['model']['version'] and app['model']['latest_version'] and app['model']['version'] < app['model']['latest_version']:
|
||||
if app_v.model.base_data.version and app_v.model.base_data.latest_version and app_v.model.base_data.version < app_v.model.base_data.latest_version:
|
||||
col_release.setForeground(QColor('orange'))
|
||||
|
||||
col_branch = QTableWidgetItem()
|
||||
col_branch.setText(app['model']['branch'])
|
||||
col_branch.setText(app_v.model.branch if isinstance(app_v.model, FlatpakApplication) else '')
|
||||
col_branch.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
col_branch.setToolTip(tooltip)
|
||||
self.setItem(idx, 3, col_branch)
|
||||
|
||||
col_arch = QTableWidgetItem()
|
||||
col_arch.setText(app['model']['arch'])
|
||||
col_arch.setText(app_v.model.arch if isinstance(app_v.model, FlatpakApplication) else '')
|
||||
col_arch.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
col_arch.setToolTip(tooltip)
|
||||
self.setItem(idx, 4, col_arch)
|
||||
|
||||
col_id = QTableWidgetItem()
|
||||
col_id.setText(app['model']['id'])
|
||||
col_id.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
col_id.setToolTip(tooltip)
|
||||
self.setItem(idx, 5, col_id)
|
||||
desc = app_v.get_async_attr('description', strip_html=True)
|
||||
col_description = QTableWidgetItem()
|
||||
col_description.setText(desc)
|
||||
col_description.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
|
||||
if app_v.model.status == ApplicationStatus.READY:
|
||||
col_description.setToolTip(desc)
|
||||
|
||||
self.setItem(idx, 5, col_description)
|
||||
|
||||
col_origin = QTableWidgetItem()
|
||||
col_origin.setText(app['model']['origin'])
|
||||
col_origin.setText(app_v.model.origin if isinstance(app_v.model, FlatpakApplication) else '')
|
||||
col_origin.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
|
||||
col_origin.setToolTip(tooltip)
|
||||
self.setItem(idx, 6, col_origin)
|
||||
|
||||
col_installed = QLabel()
|
||||
col_installed.setPixmap((QPixmap(resource.get_path('img/{}.svg'.format('checked' if app['model']['installed'] else 'red_cross')))))
|
||||
col_installed.setToolTip(tooltip)
|
||||
col_installed.setPixmap((QPixmap(resource.get_path('img/{}.svg'.format('checked' if app_v.model.installed else 'red_cross')))))
|
||||
col_installed.setAlignment(Qt.AlignCenter)
|
||||
|
||||
self.setCellWidget(idx, 7, col_installed)
|
||||
|
||||
col_update = UpdateToggleButton(app, self.window, self.window.locale_keys, app['model']['update']) if app['model']['update'] else None
|
||||
col_update = UpdateToggleButton(app_v, self.window, self.window.locale_keys, app_v.model.update) if app_v.model.update else None
|
||||
self.setCellWidget(idx, 8, col_update)
|
||||
|
||||
def change_headers_policy(self, policy: QHeaderView = QHeaderView.ResizeToContents):
|
||||
header_horizontal = self.horizontalHeader()
|
||||
for i in range(self.columnCount()):
|
||||
header_horizontal.setSectionResizeMode(i, policy)
|
||||
if i == 5:
|
||||
header_horizontal.setSectionResizeMode(i, QHeaderView.Stretch)
|
||||
else:
|
||||
header_horizontal.setSectionResizeMode(i, policy)
|
||||
|
||||
Reference in New Issue
Block a user