This commit is contained in:
Vinícius Moreira
2019-08-09 19:00:21 -03:00
committed by GitHub
13 changed files with 120 additions and 39 deletions

View File

@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [0.5.1] - 2019-08-09
### Improvements:
- suggestions are now retrieved asynchronously taking 45% less time.
- search response takes an average of 20% less time ( reaching 35% for several results )
- app boot takes 98% less time when snapd is installed, but disabled
- FPAKMAN_TRAY (--tray) is not enabled by default (0).
### Fixes
- not showing correctly the latest flatpak app versions when bringing the search results
- [flatpak dependency](https://github.com/vinifmor/fpakman/issues/36)
## [0.5.0] - 2019-08-06
### Improvements
- search results sorting takes an average of 35% less time, reaching 60% in some scenarios

View File

@@ -52,7 +52,7 @@ You can change some application settings via environment variables or arguments
- **FPAKMAN_FLATPAK**: enables / disables flatpak usage. Use **0** (disable) or **1** (enabled, default)
- **FPAKMAN_SNAP**: enables / disables snap usage. Use **0** (disable) or **1** (enabled, default)
- **FPAKMAN_CHECK_PACKAGING_ONCE**: If the available supported packaging types should be checked ONLY once. It improves the application speed if enabled, but can generate errors if you uninstall any packaging technology while using it, and every time a supported packaging type is installed it will only be available after a restart. Use **0** (disable, default) or **1** (enable).
- **FPAKMAN_TRAY**: If the tray icon and update-check daemon should be created. Use **0** (disable) or **1** (enable, default).
- **FPAKMAN_TRAY**: If the tray icon and update-check daemon should be created. Use **0** (disable, default) or **1** (enable).
- **FPAKMAN_SUGGESTIONS**: If application suggestions should be displayed if no app is installed (runtimes do not count as apps). Use **0** (disable) or **1** (enable, default).
### How to improve the application performance

View File

@@ -1,4 +1,5 @@
# Generates a .desktop file based on the current python version. Used for AUR installation
import os
import sys
desktop_file = """
@@ -7,11 +8,15 @@ Type = Application
Name = fpakman
Categories = System;
Comment = Manage your Flatpak / Snap applications
Exec = /usr/bin/fpakman --tray=0
Icon = /usr/lib/python{version}/site-packages/fpakman/resources/img/logo.svg
Exec = {path}
Icon = {lib_path}/python{version}/site-packages/fpakman/resources/img/logo.svg
"""
py_version = "{}.{}".format(sys.version_info.major, sys.version_info.minor)
fpakman_cmd = os.getenv('FPAKMAN_PATH', '/usr/bin/fpakman')
with open('fpakman.desktop', 'w+') as f:
f.write(desktop_file.format(version=py_version))
f.write(desktop_file.format(lib_path=os.getenv('FPAKMAN_LIB_PATH', '/usr/lib'),
version=py_version,
path=fpakman_cmd))

View File

@@ -1,17 +1,26 @@
# Generates a .desktop file based on the current python version. Used for AUR installation
import os
import sys
desktop_file = """
[Desktop Entry]
Type = Application
Name = fpakman ( tray )
Name = fpakman (tray)
Categories = System;
Comment = Manage your Flatpak / Snap applications
Exec = /usr/bin/fpakman
Icon = /usr/lib/python{version}/site-packages/fpakman/resources/img/logo.svg
Exec = {path}
Icon = {lib_path}/python{version}/site-packages/fpakman/resources/img/logo.svg
"""
py_version = "{}.{}".format(sys.version_info.major, sys.version_info.minor)
fpakman_cmd = os.getenv('FPAKMAN_PATH', '/usr/bin/fpakman') + ' --tray=1'
with open('fpakman_tray.desktop', 'w+') as f:
f.write(desktop_file.format(version=py_version))
f.write(desktop_file.format(lib_path=os.getenv('FPAKMAN_LIB_PATH', '/usr/lib'),
version=py_version,
path=fpakman_cmd))
with open('fpakman-tray', 'w') as f:
f.write(fpakman_cmd)

View File

@@ -1,4 +1,4 @@
__version__ = '0.5.0'
__version__ = '0.5.1'
__app_name__ = 'fpakman'
import os

View File

@@ -21,7 +21,6 @@ from fpakman.core.snap.model import SnapApplication
from fpakman.util import util
from fpakman.util.cache import Cache
from fpakman.util.memory import CacheCleaner
from fpakman.view.qt import dialog
from fpakman.view.qt.systray import TrayIcon
from fpakman.view.qt.window import ManageWindow
@@ -46,7 +45,7 @@ parser.add_argument('-di', '--download-icons', action="store", choices=[0, 1], d
parser.add_argument('--flatpak', action="store", default=os.getenv('FPAKMAN_FLATPAK', 1), choices=[0, 1], type=int, help='Enables / disables flatpak usage. Default: %(default)s')
parser.add_argument('--snap', action="store", default=os.getenv('FPAKMAN_SNAP', 1), choices=[0, 1], type=int, help='Enables / disables snap usage. Default: %(default)s')
parser.add_argument('-co', '--check-packaging-once', action="store", default=os.getenv('FPAKMAN_CHECK_PACKAGING_ONCE', 0), choices=[0, 1], type=int, help='If the available supported packaging types should be checked ONLY once. It improves the application speed if enabled, but can generate errors if you uninstall any packaging technology while using it, and every time a supported packaging type is installed it will only be available after a restart. Default: %(default)s')
parser.add_argument('--tray', action="store", default=os.getenv('FPAKMAN_TRAY', 1), choices=[0, 1], type=int, help='If the tray icon and update-check daemon should be created. Default: %(default)s')
parser.add_argument('--tray', action="store", default=os.getenv('FPAKMAN_TRAY', 0), choices=[0, 1], type=int, help='If the tray icon and update-check daemon should be created. Default: %(default)s')
parser.add_argument('--sugs', action="store", default=os.getenv('FPAKMAN_SUGGESTIONS', 1), choices=[0, 1], type=int, help='If app suggestions should be displayed if no app is installed (runtimes do not count as apps). Default: %(default)s')
args = parser.parse_args()
@@ -135,18 +134,11 @@ if args.tray:
manage_window=manage_window,
check_interval=args.check_interval,
update_notification=bool(args.update_notification))
manage_window.tray_icon = trayIcon
trayIcon.show()
else:
manage_window.refresh_apps()
manage_window.show()
warnings = manager.list_warnings()
if warnings:
for warning in warnings:
dialog.show_warning(title=locale_keys['warning'].capitalize(), body=warning)
CacheCleaner(caches).start()
sys.exit(app.exec_())

View File

@@ -1,6 +1,6 @@
import time
from abc import ABC, abstractmethod
from argparse import Namespace
from threading import Thread
from typing import List, Dict
from fpakman.core.disk import DiskCacheLoader, DiskCacheLoaderFactory
@@ -103,6 +103,12 @@ class GenericApplicationManager(ApplicationManager):
self.map = {m.get_app_type(): m for m in self.managers}
self.disk_loader_factory = disk_loader_factory
self._enabled_map = {} if app_args.check_packaging_once else None
self.thread_prepare = None
def _wait_to_be_ready(self):
if self.thread_prepare:
self.thread_prepare.join()
self.thread_prepare = None
def _sort(self, apps: List[Application], word: str) -> List[Application]:
exact_name_matches, contains_name_matches, others = [], [], []
@@ -125,7 +131,6 @@ class GenericApplicationManager(ApplicationManager):
return res
def _is_enabled(self, man: ApplicationManager):
if self._enabled_map is not None:
enabled = self._enabled_map.get(man.get_app_type())
@@ -137,21 +142,30 @@ class GenericApplicationManager(ApplicationManager):
else:
return man.is_enabled()
def _search(self, word: str, man: ApplicationManager, disk_loader, res: dict):
if self._is_enabled(man):
apps_found = man.search(word=word, disk_loader=disk_loader)
res['installed'].extend(apps_found['installed'])
res['new'].extend(apps_found['new'])
def search(self, word: str, disk_loader: DiskCacheLoader = None) -> Dict[str, List[Application]]:
self._wait_to_be_ready()
res = {'installed': [], 'new': []}
norm_word = word.strip().lower()
disk_loader = None
disk_loader = self.disk_loader_factory.new()
disk_loader.start()
threads = []
for man in self.managers:
if self._is_enabled(man):
if not disk_loader:
disk_loader = self.disk_loader_factory.new()
disk_loader.start()
t = Thread(target=self._search, args=(norm_word, man, disk_loader, res))
t.start()
threads.append(t)
apps_found = man.search(word=norm_word, disk_loader=disk_loader)
res['installed'].extend(apps_found['installed'])
res['new'].extend(apps_found['new'])
for t in threads:
t.join()
if disk_loader:
disk_loader.stop = True
@@ -163,6 +177,8 @@ class GenericApplicationManager(ApplicationManager):
return res
def read_installed(self, disk_loader: DiskCacheLoader = None) -> List[Application]:
self._wait_to_be_ready()
installed = []
disk_loader = None
@@ -254,18 +270,26 @@ class GenericApplicationManager(ApplicationManager):
return man.requires_root(action, app)
def refresh(self, app: Application, root_password: str) -> FpakmanProcess:
self._wait_to_be_ready()
man = self._get_manager_for(app)
if man:
return man.refresh(app, root_password)
def prepare(self):
def _prepare(self):
if self.managers:
for man in self.managers:
if self._is_enabled(man):
man.prepare()
def prepare(self):
self.thread_prepare = Thread(target=self._prepare)
self.thread_prepare.start()
def list_updates(self) -> List[ApplicationUpdate]:
self._wait_to_be_ready()
updates = []
if self.managers:
@@ -290,10 +314,22 @@ class GenericApplicationManager(ApplicationManager):
return warnings
def _fill_suggestions(self, suggestions: list, man: ApplicationManager, limit: int):
if self._is_enabled(man):
man_sugs = man.list_suggestions(limit)
if man_sugs:
suggestions.extend(man_sugs)
def list_suggestions(self, limit: int) -> List[Application]:
if self.managers:
suggestions = []
suggestions, threads = [], []
for man in self.managers:
if self._is_enabled(man):
suggestions.extend(man.list_suggestions(6))
t = Thread(target=self._fill_suggestions, args=(suggestions, man, 6))
t.start()
threads.append(t)
for t in threads:
t.join()
return suggestions

View File

@@ -181,8 +181,9 @@ class FlatpakManager(ApplicationManager):
return updates
def list_warnings(self) -> List[str]:
if not flatpak.has_remotes_set():
return [self.locale_keys['flatpak.notification.no_remotes']]
if flatpak.is_installed():
if not flatpak.has_remotes_set():
return [self.locale_keys['flatpak.notification.no_remotes']]
def list_suggestions(self, limit: int) -> List[FlatpakApplication]:

View File

@@ -48,6 +48,9 @@ class FlatpakAsyncDataLoader(AsyncDataLoader):
if not self.app.base_data.version and self.app.base_data.latest_version:
self.app.base_data.version = self.app.base_data.latest_version
if not self.app.installed and self.app.base_data.latest_version:
self.app.base_data.version = self.app.base_data.latest_version
if self.app.base_data.icon_url and self.app.base_data.icon_url.startswith('/'):
self.app.base_data.icon_url = FLATHUB_URL + self.app.base_data.icon_url

View File

@@ -3,7 +3,6 @@ from threading import Thread
from typing import List
from fpakman.util.cache import Cache
import gc
class CacheCleaner(Thread):
@@ -20,6 +19,5 @@ class CacheCleaner(Thread):
for cache in self.caches:
cache.clean_expired()
gc.collect()
time.sleep(self.check_interval)

View File

@@ -315,7 +315,7 @@ class AppsTable(QTableWidget):
label_version.setStyleSheet("color: #4EC306; font-weight: bold")
tooltip = self.window.locale_keys['version.installed_outdated']
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:
if app_v.model.installed and 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:
tooltip = '{}. {}: {}'.format(tooltip, self.window.locale_keys['version.latest'], app_v.model.base_data.latest_version)
label_version.setText(label_version.text() + ' > {}'.format(app_v.model.base_data.latest_version))

View File

@@ -347,4 +347,18 @@ class FindSuggestions(AsyncAction):
def run(self):
self.signal_finished.emit(self.man.list_suggestions(limit=-1))
class ListWarnings(QThread):
signal_warnings = pyqtSignal(list)
def __init__(self, man: ApplicationManager, locale_keys: dict):
super(QThread, self).__init__()
self.locale_keys = locale_keys
self.man = man
def run(self):
warnings = self.man.list_warnings()
if warnings:
self.signal_warnings.emit(warnings)

View File

@@ -18,7 +18,7 @@ from fpakman.view.qt.history import HistoryDialog
from fpakman.view.qt.info import InfoDialog
from fpakman.view.qt.root import is_root, ask_root_password
from fpakman.view.qt.thread import UpdateSelectedApps, RefreshApps, UninstallApp, DowngradeApp, GetAppInfo, \
GetAppHistory, SearchApps, InstallApp, AnimateProgress, VerifyModels, RefreshApp, FindSuggestions
GetAppHistory, SearchApps, InstallApp, AnimateProgress, VerifyModels, RefreshApp, FindSuggestions, ListWarnings
from fpakman.view.qt.view_model import ApplicationView
DARK_ORANGE = '#FF4500'
@@ -213,6 +213,19 @@ class ManageWindow(QWidget):
self.dialog_about = None
self.first_refresh = suggestions
self.thread_warnings = ListWarnings(man=manager, locale_keys=locale_keys)
self.thread_warnings.signal_warnings.connect(self._show_warnings)
def _show_warnings(self, warnings: List[str]):
if warnings:
for warning in warnings:
dialog.show_warning(title=self.locale_keys['warning'].capitalize(), body=warning)
def show(self):
super(ManageWindow, self).show()
if not self.thread_warnings.isFinished():
self.thread_warnings.start()
def _show_about(self):
if self.dialog_about is None:
self.dialog_about = AboutDialog(self.locale_keys)