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

@@ -9,7 +9,7 @@ from colorama import Fore
from fpakman import __version__
from fpakman.core import resource
from fpakman.util import util
from fpakman.core.controller import FlatpakManager
from fpakman.core.controller import FlatpakManager, GenericApplicationManager
from fpakman.util.cache import Cache
from fpakman.util.memory import CacheCleaner
from fpakman.view.qt import common
@@ -66,7 +66,8 @@ caches.append(icon_cache)
app = QApplication(sys.argv)
app.setWindowIcon(QIcon(resource.get_path('img/logo.svg')))
manager = FlatpakManager(flatpak_api_cache)
manager = GenericApplicationManager([FlatpakManager(flatpak_api_cache)])
trayIcon = TrayIcon(locale_keys=locale_keys,
manager=manager,

View File

@@ -1,3 +1,4 @@
from abc import ABC, abstractmethod
from datetime import datetime
from threading import Lock
from typing import List
@@ -5,12 +6,59 @@ from typing import List
import requests
from fpakman.core import flatpak
from fpakman.core.model import FlatpakApplication, ApplicationData, ApplicationStatus
from fpakman.core.model import FlatpakApplication, ApplicationData, ApplicationStatus, Application
from fpakman.core.worker import FlatpakAsyncDataLoaderManager
from fpakman.util.cache import Cache
class FlatpakManager:
class ApplicationManager(ABC):
@abstractmethod
def search(self, word: str) -> List[Application]:
pass
@abstractmethod
def read_installed(self) -> List[Application]:
pass
@abstractmethod
def downgrade_app(self, app: Application, root_password: str):
pass
@abstractmethod
def clean_cache_for(self, app: Application):
pass
@abstractmethod
def can_downgrade(self):
pass
@abstractmethod
def update_and_stream(self, app: Application):
pass
@abstractmethod
def uninstall_and_stream(self, app: Application):
pass
@abstractmethod
def get_app_type(self) -> str:
pass
@abstractmethod
def get_info(self, app: Application) -> dict:
pass
@abstractmethod
def get_history(self, app: Application) -> List[dict]:
pass
@abstractmethod
def install_and_stream(self, app: Application):
pass
class FlatpakManager(ApplicationManager):
def __init__(self, api_cache: Cache):
self.api_cache = api_cache
@@ -19,6 +67,9 @@ class FlatpakManager:
self.async_data_loader = FlatpakAsyncDataLoaderManager(api_cache=self.api_cache)
flatpak.set_default_remotes()
def get_app_type(self):
return FlatpakApplication
def _map_to_model(self, app: dict) -> FlatpakApplication:
model = FlatpakApplication(arch=app.get('arch'),
@@ -103,6 +154,9 @@ class FlatpakManager:
finally:
self.lock_read.release()
def can_downgrade(self):
return True
def downgrade_app(self, app: FlatpakApplication, root_password: str):
commits = flatpak.get_app_commits(app.ref, app.origin)
@@ -114,5 +168,77 @@ class FlatpakManager:
return flatpak.downgrade_and_stream(app.ref, commits[commit_idx + 1], root_password)
def clean_cache_for(self, app_id: str):
self.api_cache.delete(app_id)
def clean_cache_for(self, app: FlatpakApplication):
self.api_cache.delete(app.base_data.id)
def update_and_stream(self, app: FlatpakApplication):
return flatpak.update_and_stream(app.ref)
def uninstall_and_stream(self, app: FlatpakApplication):
return flatpak.uninstall_and_stream(app.ref)
def get_info(self, app: FlatpakApplication) -> dict:
app_info = flatpak.get_app_info_fields(app.base_data.id, app.branch)
app_info['name'] = app.base_data.name
app_info['type'] = 'runtime' if app.runtime else 'app'
app_info['description'] = app.base_data.description
return app_info
def get_history(self, app: FlatpakApplication) -> List[dict]:
return flatpak.get_app_commits_data(app.ref, app.origin)
def install_and_stream(self, app: FlatpakApplication):
return flatpak.install_and_stream(app.base_data.id, app.origin)
class GenericApplicationManager(ApplicationManager):
def __init__(self, managers: List[ApplicationManager]):
self.managers = managers
self.map = {m.get_app_type(): m for m in self.managers}
def search(self, word: str) -> List[Application]:
apps = []
for man in self.managers:
apps.extend(man.search(word))
return apps
def read_installed(self) -> List[Application]:
installed = []
for man in self.managers:
installed.extend(man.read_installed())
return installed
def can_downgrade(self):
return True
def downgrade_app(self, app: Application, root_password: str):
manager = self.map.get(app.__class__)
if manager.can_downgrade():
return manager.downgrade_app(app, root_password)
else:
raise Exception("downgrade is not possible for {}".format(app.__class__.__name__))
def clean_cache_for(self, app: Application):
self.map[app.__class__].clean_cache_for(app)
def update_and_stream(self, app: Application):
return self.map[app.__class__].update_and_stream(app)
def uninstall_and_stream(self, app: Application):
return self.map[app.__class__].uninstall_and_stream(app)
def install_and_stream(self, app: Application):
return self.map[app.__class__].install_and_stream(app)
def get_info(self, app: Application):
return self.map[app.__class__].get_info(app)
def get_history(self, app: Application):
return self.map[app.__class__].get_history(app)
def get_app_type(self):
return None

View File

@@ -1,6 +1,8 @@
from abc import ABC
from abc import ABC, abstractmethod
from enum import Enum
from fpakman.core import resource
class ApplicationStatus(Enum):
READY = 1
@@ -26,6 +28,37 @@ class Application(ABC):
self.installed = installed
self.update = update
@abstractmethod
def has_history(self):
pass
@abstractmethod
def has_info(self):
pass
@abstractmethod
def can_be_downgraded(self):
pass
@abstractmethod
def can_be_uninstalled(self):
pass
@abstractmethod
def can_be_installed(self):
pass
@abstractmethod
def get_type(self):
pass
def get_default_logo_path(self):
return resource.get_path('img/logo.svg')
@abstractmethod
def is_library(self):
pass
class FlatpakApplication(Application):
@@ -40,3 +73,27 @@ class FlatpakApplication(Application):
def is_incomplete(self):
return self.base_data.description is None and self.base_data.icon_url
def has_history(self):
return True
def has_info(self):
return True
def can_be_downgraded(self):
return not self.runtime
def can_be_uninstalled(self):
return True
def can_be_installed(self):
return True
def get_type(self):
return 'flatpak'
def get_default_logo_path(self):
return resource.get_path('img/flathub.svg')
def is_library(self):
return self.runtime

View File

@@ -1,6 +1,5 @@
manage_window.title=Flatpak Application Manager
manage_window.title=Application Manager
manage_window.columns.latest_version=Latest Version
manage_window.columns.installed=Installed
manage_window.columns.update=Upgrade ?
manage_window.apps_table.row.actions.info=Information
manage_window.apps_table.row.actions.history=History
@@ -43,7 +42,7 @@ tray.action.manage=Manage applications
tray.action.exit=Exit
tray.action.about=About
tray.action.refreshing=Refreshing
notification.new_updates={} updates
notification.new_updates=Updates
flatpak.info.arch=arch
flatpak.info.branch=branch
flatpak.info.collection=collection
@@ -70,4 +69,11 @@ about.info.rate=If this tool is useful for you, give it a star on Github to keep
yes=yes
no=no
version.updated=updated
version.outdated=outdated
version.outdated=outdated
name=name
version=version
latest_version=latest version
description=description
type=type
installed=installed
others=others

View File

@@ -1,4 +1,4 @@
manage_window.title=Administrador de Aplicativos Flatpak
manage_window.title=Administrador de Aplicativos
manage_window.columns.latest_version=Ultima Versión
manage_window.columns.update=Actualizar ?
manage_window.columns.installed=Instalado
@@ -43,7 +43,7 @@ tray.action.manage=Administrar aplicativos
tray.action.exit=Salir
tray.action.about=Sobre
tray.action.refreshing=Recargando
notification.new_updates=Actualizaciones {}
notification.new_updates=Actualizaciones
flatpak.info.arch=arquitectura
flatpak.info.branch=rama
flatpak.info.collection=colección
@@ -70,4 +70,11 @@ about.info.rate=Si esta herramienta es útil para ti, dale una estrella en Githu
yes=sí
no=no
version.updated=actualizada
version.outdated=desactualizada
version.outdated=desactualizada
name=nombre
version=versión
latest_version=ultima versión
description=descripción
type=tipo
installed=instalado
others=otros

View File

@@ -1,4 +1,4 @@
manage_window.title=Gerenciador de Aplicativos Flatpak
manage_window.title=Gerenciador de Aplicativos
manage_window.columns.latest_version=Última Versão
manage_window.columns.update=Atualizar ?
manage_window.columns.installed=Instalado
@@ -43,7 +43,7 @@ tray.action.manage=Gerenciar aplicativos
tray.action.exit=Sair
tray.action.about=Sobre
tray.action.refreshing=Recarregando
notification.new_updates=Atualizações {}
notification.new_updates=Atualizações
flatpak.info.arch=arquitetura
flatpak.info.branch=ramo
flatpak.info.collection=coleção
@@ -70,4 +70,11 @@ about.info.rate=Se essa ferramenta é útil para você, dê uma estrela no Githu
yes=sim
no=não
version.updated=atualizada
version.outdated=desatualizada
version.outdated=desatualizada
name=nome
version=versão
latest_version=última versão
description=descrição
type=tipo
installed=instalado
others=outros

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):