architecture expanded to support other types of packaging

This commit is contained in:
Vinícius Moreira
2019-07-10 11:31:57 -03:00
committed by GitHub
parent 925aa7cec6
commit ff8510153d
11 changed files with 326 additions and 133 deletions

View File

@@ -43,13 +43,12 @@ class AppsTable(QTableWidget):
super(AppsTable, self).__init__()
self.setParent(parent)
self.window = parent
self.column_names = [parent.locale_keys[key].capitalize() for key in ['flatpak.info.name',
'flatpak.info.version',
'manage_window.columns.latest_version',
'flatpak.info.branch',
self.column_names = [parent.locale_keys[key].capitalize() for key in ['name',
'version',
'latest_version',
'flatpak.info.description',
'flatpak.info.origin',
'manage_window.columns.installed',
'type',
'installed',
'manage_window.columns.update']]
self.setColumnCount(len(self.column_names))
self.setFocusPolicy(Qt.NoFocus)
@@ -59,6 +58,7 @@ class AppsTable(QTableWidget):
self.setHorizontalHeaderLabels(self.column_names)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.icon_flathub = QIcon(resource.get_path('img/flathub.svg'))
self.icon_logo = QIcon(resource.get_path('img/logo.svg'))
self.network_man = QNetworkAccessManager()
self.network_man.finished.connect(self._load_icon)
@@ -73,31 +73,36 @@ class AppsTable(QTableWidget):
menu_row = QMenu()
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)
menu_row.addAction(action_info)
action_history = QAction(self.window.locale_keys["manage_window.apps_table.row.actions.history"])
action_history.setIcon(QIcon(resource.get_path('img/history.svg')))
action_history.triggered.connect(self._get_app_history)
menu_row.addAction(action_history)
if app.model.has_info():
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)
menu_row.addAction(action_info)
action_uninstall = QAction(self.window.locale_keys["manage_window.apps_table.row.actions.uninstall"])
action_uninstall.setIcon(QIcon(resource.get_path('img/uninstall.svg')))
action_uninstall.triggered.connect(self._uninstall_app)
menu_row.addAction(action_uninstall)
if app.model.has_history():
action_history = QAction(self.window.locale_keys["manage_window.apps_table.row.actions.history"])
action_history.setIcon(QIcon(resource.get_path('img/history.svg')))
action_history.triggered.connect(self._get_app_history)
menu_row.addAction(action_history)
if isinstance(app.model, FlatpakApplication) and not app.model.runtime: # not available for runtimes
if app.model.can_be_uninstalled():
action_uninstall = QAction(self.window.locale_keys["manage_window.apps_table.row.actions.uninstall"])
action_uninstall.setIcon(QIcon(resource.get_path('img/uninstall.svg')))
action_uninstall.triggered.connect(self._uninstall_app)
menu_row.addAction(action_uninstall)
if app.model.can_be_downgraded():
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')))
menu_row.addAction(action_downgrade)
else:
action_install = QAction(self.window.locale_keys["manage_window.apps_table.row.actions.install"])
action_install.setIcon(QIcon(resource.get_path('img/install.svg')))
action_install.triggered.connect(self._install_app)
menu_row.addAction(action_install)
if app.model.can_be_installed():
action_install = QAction(self.window.locale_keys["manage_window.apps_table.row.actions.install"])
action_install.setIcon(QIcon(resource.get_path('img/install.svg')))
action_install.triggered.connect(self._install_app)
menu_row.addAction(action_install)
menu_row.adjustSize()
menu_row.popup(QCursor.pos())
@@ -108,20 +113,21 @@ class AppsTable(QTableWidget):
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)
self._set_col_description(self.item(idx, 4), app_v)
visible, ready = 0, 0
for idx, app_v in enumerate(self.window.apps):
for app_v in self.window.apps:
if app_v.visible:
visible += 1
if app_v.status == ApplicationViewStatus.READY:
ready += 1
if 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)
self._set_col_description(self.item(idx, 3), app_v)
app_v.status = ApplicationViewStatus.READY
if app_v.status == ApplicationViewStatus.READY:
ready += 1
if ready == visible:
self.window.resize_and_center()
@@ -185,14 +191,14 @@ class AppsTable(QTableWidget):
col_name.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
if not app_v.model.base_data.icon_url:
col_name.setIcon(self.icon_flathub)
col_name.setIcon(QIcon(app_v.model.get_default_logo_path()))
else:
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)
col_name.setIcon(QIcon(app_v.model.get_default_logo_path()))
self.setItem(idx, 0, col_name)
@@ -209,30 +215,25 @@ class AppsTable(QTableWidget):
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_v.model.branch if isinstance(app_v.model, FlatpakApplication) else '')
col_branch.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
self.setItem(idx, 3, col_branch)
col_description = QTableWidgetItem()
col_description.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
self._set_col_description(col_description, app_v)
self.setItem(idx, 4, col_description)
self.setItem(idx, 3, col_description)
col_origin = QTableWidgetItem()
col_origin.setText(app_v.model.origin if isinstance(app_v.model, FlatpakApplication) else '')
col_origin.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
self.setItem(idx, 5, col_origin)
col_type = QTableWidgetItem()
col_type.setText(app_v.model.get_type())
col_type.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
self.setItem(idx, 4, col_type)
col_installed = QLabel()
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, 6, col_installed)
self.setCellWidget(idx, 5, col_installed)
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, 7, col_update)
self.setCellWidget(idx, 6, col_update)
def _set_col_description(self, col: QTableWidgetItem, app_v: ApplicationView):
desc = app_v.get_async_attr('description', strip_html=True)

View File

@@ -8,7 +8,7 @@ from PyQt5.QtWidgets import QDialog, QVBoxLayout, QTableWidget, QTableWidgetItem
class HistoryDialog(QDialog):
def __init__(self, app: dict, app_icon: QIcon, locale_keys: dict):
def __init__(self, app: dict, app_icon: QIcon, locale_keys: dict):
super(HistoryDialog, self).__init__()
self.setWindowTitle('{} - {} '.format(locale_keys['popup.history.title'], app['model'].base_data.name))
@@ -23,11 +23,11 @@ class HistoryDialog(QDialog):
table_history.verticalHeader().setVisible(False)
table_history.setAlternatingRowColors(True)
table_history.setColumnCount(len(app['commits'][0]))
table_history.setRowCount(len(app['commits']))
table_history.setHorizontalHeaderLabels([locale_keys['flatpak.info.' + key].capitalize() for key in sorted(app['commits'][0].keys())])
table_history.setColumnCount(len(app['history'][0]))
table_history.setRowCount(len(app['history']))
table_history.setHorizontalHeaderLabels([locale_keys['flatpak.info.' + key].capitalize() for key in sorted(app['history'][0].keys())])
for row, commit in enumerate(app['commits']):
for row, commit in enumerate(app['history']):
current_app_commit = app['model'].commit == commit['commit']

View File

@@ -7,7 +7,7 @@ from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QSystemTrayIcon, QMenu
from fpakman.core import resource, system
from fpakman.core.controller import FlatpakManager
from fpakman.core.controller import FlatpakManager, ApplicationManager
from fpakman.core.model import Application
from fpakman.util.cache import Cache
from fpakman.view.qt.about import AboutDialog
@@ -18,7 +18,7 @@ class UpdateCheck(QThread):
signal = pyqtSignal(list)
def __init__(self, manager: FlatpakManager, check_interval: int, parent=None):
def __init__(self, manager: ApplicationManager, check_interval: int, parent=None):
super(UpdateCheck, self).__init__(parent)
self.check_interval = check_interval
self.manager = manager
@@ -39,7 +39,7 @@ class UpdateCheck(QThread):
class TrayIcon(QSystemTrayIcon):
def __init__(self, locale_keys: dict, manager: FlatpakManager, icon_cache: Cache, check_interval: int = 60, update_notification: bool = True):
def __init__(self, locale_keys: dict, manager: ApplicationManager, icon_cache: Cache, check_interval: int = 60, update_notification: bool = True):
super(TrayIcon, self).__init__()
self.locale_keys = locale_keys
self.manager = manager
@@ -86,7 +86,7 @@ class TrayIcon(QSystemTrayIcon):
if update_keys.difference(self.last_updates):
self.last_updates = update_keys
msg = '{}: {}'.format(self.locale_keys['notification.new_updates'].format('Flatpak'), len(updates))
msg = '{}: {}'.format(self.locale_keys['notification.new_updates'], len(updates))
self.setToolTip(msg)
if self.update_notification:

View File

@@ -4,12 +4,11 @@ from typing import List
from PyQt5.QtCore import QThread, pyqtSignal
from fpakman.core import flatpak
from fpakman.core.controller import FlatpakManager
from fpakman.core.model import ApplicationStatus, FlatpakApplication
from fpakman.core.controller import ApplicationManager
from fpakman.core.model import ApplicationStatus
from fpakman.util.cache import Cache
from fpakman.view.qt import dialog
from fpakman.view.qt.view_model import ApplicationView, ApplicationViewStatus
from fpakman.view.qt.view_model import ApplicationView
class UpdateSelectedApps(QThread):
@@ -17,14 +16,15 @@ class UpdateSelectedApps(QThread):
signal_finished = pyqtSignal()
signal_output = pyqtSignal(str)
def __init__(self):
def __init__(self, manager: ApplicationManager, apps_to_update: List[ApplicationView] = None):
super(UpdateSelectedApps, self).__init__()
self.refs_to_update = []
self.apps_to_update = apps_to_update
self.manager = manager
def run(self):
for app_ref in self.refs_to_update:
for output in flatpak.update_and_stream(app_ref):
for app in self.apps_to_update:
for output in self.manager.update_and_stream(app.model):
line = output.decode().strip()
if line:
self.signal_output.emit(line)
@@ -36,7 +36,7 @@ class RefreshApps(QThread):
signal = pyqtSignal(list)
def __init__(self, manager: FlatpakManager):
def __init__(self, manager: ApplicationManager):
super(RefreshApps, self).__init__()
self.manager = manager
@@ -48,21 +48,21 @@ class UninstallApp(QThread):
signal_finished = pyqtSignal()
signal_output = pyqtSignal(str)
def __init__(self, manager: FlatpakManager, icon_cache: Cache, app: ApplicationView = None):
def __init__(self, manager: ApplicationManager, icon_cache: Cache, app: ApplicationView = None):
super(UninstallApp, self).__init__()
self.app = app
self.manager = manager
self.icon_cache = icon_cache
def run(self):
if self.app and isinstance(self.app.model, FlatpakApplication):
for output in flatpak.uninstall_and_stream(self.app.model.ref):
if self.app:
for output in self.manager.uninstall_and_stream(self.app.model):
line = output.decode().strip()
if line:
self.signal_output.emit(line)
self.icon_cache.delete(self.app.model.base_data.icon_url)
self.manager.clean_cache_for(self.app.model.base_data.id)
self.manager.clean_cache_for(self.app.model)
self.signal_finished.emit()
@@ -70,7 +70,7 @@ class DowngradeApp(QThread):
signal_finished = pyqtSignal()
signal_output = pyqtSignal(str)
def __init__(self, manager: FlatpakManager, locale_keys: dict, app: ApplicationView = None):
def __init__(self, manager: ApplicationManager, locale_keys: dict, app: ApplicationView = None):
super(DowngradeApp, self).__init__()
self.manager = manager
self.app = app
@@ -78,7 +78,7 @@ class DowngradeApp(QThread):
self.root_password = None
def run(self):
if self.app and isinstance(self.app.model, FlatpakApplication):
if self.app:
stream = self.manager.downgrade_app(self.app.model, self.root_password)
@@ -99,38 +99,35 @@ class DowngradeApp(QThread):
class GetAppInfo(QThread):
signal_finished = pyqtSignal(dict)
def __init__(self, app: ApplicationView = None):
def __init__(self, manager: ApplicationManager, app: ApplicationView = None):
super(GetAppInfo, self).__init__()
self.app = app
self.manager = manager
def run(self):
if self.app and isinstance(self.app.model, FlatpakApplication):
app_info = flatpak.get_app_info_fields(self.app.model.base_data.id, self.app.model.branch)
app_info['name'] = self.app.model.base_data.name
app_info['type'] = 'runtime' if self.app.model.runtime else 'app'
app_info['description'] = self.app.model.base_data.description
self.signal_finished.emit(app_info)
if self.app:
self.signal_finished.emit(self.manager.get_info(self.app.model))
self.app = None
class GetAppHistory(QThread):
signal_finished = pyqtSignal(dict)
def __init__(self, app: ApplicationView = None):
def __init__(self, manager: ApplicationManager, app: ApplicationView = None):
super(GetAppHistory, self).__init__()
self.app = app
self.manager = manager
def run(self):
if self.app and isinstance(self.app.model, FlatpakApplication):
commits = flatpak.get_app_commits_data(self.app.model.ref, self.app.model.origin)
self.signal_finished.emit({'model': self.app.model, 'commits': commits})
if self.app:
self.signal_finished.emit({'model': self.app.model, 'history': self.manager.get_history(self.app.model)})
self.app = None
class SearchApps(QThread):
signal_finished = pyqtSignal(list)
def __init__(self, manager: FlatpakManager):
def __init__(self, manager: ApplicationManager):
super(SearchApps, self).__init__()
self.word = None
self.manager = manager
@@ -150,14 +147,15 @@ class InstallApp(QThread):
signal_finished = pyqtSignal()
signal_output = pyqtSignal(str)
def __init__(self, app: ApplicationView = None):
def __init__(self, manager: ApplicationManager, app: ApplicationView = None):
super(InstallApp, self).__init__()
self.app = app
self.manager = manager
def run(self):
if self.app and isinstance(self.app.model, FlatpakApplication):
for output in flatpak.install_and_stream(self.app.model.base_data.id, self.app.model.origin):
if self.app:
for output in self.manager.install_and_stream(self.app.model):
line = output.decode().strip()
if line:
self.signal_output.emit(line)

View File

@@ -8,11 +8,11 @@ from PyQt5.QtGui import QIcon, QWindowStateChangeEvent, QPixmap
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, QCheckBox, QHeaderView, QToolButton, QToolBar, \
QSizePolicy, QLabel, QPlainTextEdit, QLineEdit, QProgressBar
from fpakman.core import resource, flatpak
from fpakman.core.controller import FlatpakManager
from fpakman.core.model import Application, FlatpakApplication
from fpakman.core import resource
from fpakman.core.controller import ApplicationManager
from fpakman.core.model import Application
from fpakman.util.cache import Cache
from fpakman.view.qt import dialog, common
from fpakman.view.qt import common
from fpakman.view.qt.apps_table import AppsTable
from fpakman.view.qt.history import HistoryDialog
from fpakman.view.qt.info import InfoDialog
@@ -27,7 +27,7 @@ DARK_ORANGE = '#FF4500'
class ManageWindow(QWidget):
__BASE_HEIGHT__ = 400
def __init__(self, locale_keys: dict, icon_cache: Cache, manager: FlatpakManager, tray_icon=None):
def __init__(self, locale_keys: dict, icon_cache: Cache, manager: ApplicationManager, tray_icon=None):
super(ManageWindow, self).__init__()
self.locale_keys = locale_keys
self.manager = manager
@@ -128,7 +128,7 @@ class ManageWindow(QWidget):
self.textarea_output.setVisible(False)
self.textarea_output.setReadOnly(True)
self.thread_update = UpdateSelectedApps()
self.thread_update = UpdateSelectedApps(self.manager)
self.thread_update.signal_output.connect(self._update_action_output)
self.thread_update.signal_finished.connect(self._finish_update_selected)
@@ -143,16 +143,16 @@ class ManageWindow(QWidget):
self.thread_downgrade.signal_output.connect(self._update_action_output)
self.thread_downgrade.signal_finished.connect(self._finish_downgrade)
self.thread_get_info = GetAppInfo()
self.thread_get_info = GetAppInfo(self.manager)
self.thread_get_info.signal_finished.connect(self._finish_get_info)
self.thread_get_history = GetAppHistory()
self.thread_get_history = GetAppHistory(self.manager)
self.thread_get_history.signal_finished.connect(self._finish_get_history)
self.thread_search = SearchApps(self.manager)
self.thread_search.signal_finished.connect(self._finish_search)
self.thread_install = InstallApp()
self.thread_install = InstallApp(self.manager)
self.thread_install.signal_output.connect(self._update_action_output)
self.thread_install.signal_finished.connect(self._finish_install)
@@ -175,9 +175,6 @@ class ManageWindow(QWidget):
self.toolbar_bottom.addWidget(self._new_spacer())
self.label_flatpak = QLabel(self._get_flatpak_label())
self.toolbar_bottom.addWidget(self.label_flatpak)
self.layout.addWidget(self.toolbar_bottom)
self.centralize()
@@ -204,15 +201,8 @@ class ManageWindow(QWidget):
self._handle_console_option(False)
def _check_flatpak_installed(self):
common.check_flatpak_installed(self.locale_keys)
if self.label_flatpak:
self.label_flatpak.setText(self._get_flatpak_label())
def _get_flatpak_label(self):
return 'flatpak: ' + flatpak.get_version()
def _acquire_lock(self):
self.thread_lock.acquire()
@@ -288,7 +278,7 @@ class ManageWindow(QWidget):
show_only_apps = True if only_apps == 2 else False
for idx, app_v in enumerate(self.apps):
hidden = show_only_apps and isinstance(app_v.model, FlatpakApplication) and app_v.model.runtime
hidden = show_only_apps and app_v.model.is_library()
self.table_apps.setRowHidden(idx, hidden)
app_v.visible = not hidden
@@ -301,22 +291,22 @@ class ManageWindow(QWidget):
enable_bt_update = False
app_updates, runtime_updates = 0, 0
app_updates, library_updates = 0, 0
for app_v in self.apps:
if app_v.model.update:
if app_v.model.runtime:
runtime_updates += 1
library_updates += 1
else:
app_updates += 1
total_updates = app_updates + runtime_updates
total_updates = app_updates + library_updates
if total_updates > 0:
self.label_updates.setText('{}: {}'.format(self.locale_keys['manage_window.label.updates'], total_updates))
self.label_updates.setToolTip('{} {} | {} runtimes'.format(app_updates,
self.locale_keys[
'manage_window.checkbox.only_apps'].lower(),
runtime_updates))
self.label_updates.setToolTip('{} {} | {} {}'.format(app_updates,
self.locale_keys['manage_window.checkbox.only_apps'].lower(),
library_updates,
self.locale_keys['others'].lower()))
else:
self.label_updates.setText('')
@@ -340,14 +330,14 @@ class ManageWindow(QWidget):
self.apps = []
napps = 0 # number of apps (not runtimes)
napps = 0 # number of apps (not libraries)
if apps:
for app in apps:
app_model = ApplicationView(model=app,
visible=(isinstance(app, FlatpakApplication) and not app.runtime) or not self.checkbox_only_apps.isChecked())
visible=(not app.is_library()) or not self.checkbox_only_apps.isChecked())
napps += 1 if isinstance(app, FlatpakApplication) and not app.runtime else 0
napps += 1 if not app.is_library() else 0
self.apps.append(app_model)
if napps == 0:
@@ -375,13 +365,13 @@ class ManageWindow(QWidget):
if self._acquire_lock():
if self.apps:
to_update = [app_v.model.ref for app_v in self.apps if app_v.visible and app_v.update_checked and isinstance(app_v.model, FlatpakApplication)]
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)
self._begin_action(self.locale_keys['manage_window.status.upgrading'])
self.thread_update.refs_to_update = to_update
self.thread_update.apps_to_update = to_update
self.thread_update.start()
def _finish_update_selected(self):