This commit is contained in:
Vinícius Moreira
2019-10-02 12:07:24 -03:00
committed by GitHub
25 changed files with 156 additions and 87 deletions

View File

@@ -4,13 +4,34 @@ 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.6.2] 2019-10-02
### Improvements
- Update notifications showing the number of updates by type as well ( if there are from more than one packaging type )
- Snap:
- **Installed** info field split into **version** and **size**
- AUR:
- Installed files available in the Info window
- Improving Arch distro checking
### Fixes
- Update-check daemon not showing notifications
- Not retrieving the system default locale to translate the application texts
- Not updating translations when the default locale is different from 'en'
- Installed button available after a recent installation if a new search is done
- Flatpak:
- error when retrieving information ( Flatpak 1.0.X )
- Snap:
- apps with commands different from their names do not launch
- AUR:
- ignoring downgrade warnings for different locales
## [0.6.1] 2019-09-26
### Improvements:
### Improvements
- Better warning presentation when there are several messages
- Better AUR update check handling
- "Show" button available for all information fields
### Fixes:
### Fixes
- Error when retrieving suggestions
- snapd health check when snapd.service is available
- AUR: not showing all optional dependencies ( Info )

View File

@@ -1,11 +1,9 @@
## bauh
**bauh** ( ba-oo ) is a graphical user interface to manage your Linux applications ( packages ) ( old **fpakman** ). It currently supports Flatpak, Snap and AUR packaging types. When you launch **bauh** you will see
a management panel where you can search, update, install, uninstall and launch applications. You can also downgrade some applications depending on the package technology.
It has a **tray mode** (see **Settings** below) that attaches the application icon to the system tray providing a quick way to launch it. Also the icon will get red when updates are available.
This project has an official Twitter account ( **@bauh4linux**) so people can stay on top of its news.
This project has an official Twitter account ( **@bauh4linux** ) so people can stay on top of its news.
### Developed with:
- Python3 and Qt5.
@@ -94,7 +92,7 @@ You can change some application settings via environment variables or arguments
- It is **not enabled by default**
- The user is able to search, install, uninstall, downgrade, launch and retrieve the packages history
- It handles conflicts, and missing / optional packages installations ( including from your distro mirrors )
- If (**aria2**) [https://github.com/aria2/aria2] is installed on your system and multi-threaded downloads are enabled ( see **BAUH_DOWNLOAD_MULTITHREAD** ), the source packages
- If [**aria2**](https://github.com/aria2/aria2) is installed on your system and multi-threaded downloads are enabled ( see **BAUH_DOWNLOAD_MULTITHREAD** ), the source packages
will be pre-downloaded faster ( it does **NOT** modify your **pacman** settings ).
- Automatically makes simple package compilation improvements

View File

@@ -1,24 +1,15 @@
# Generates a .desktop file based on the current python version. Used for AUR installation
import os
import sys
import locale
system_locale = locale.getdefaultlocale()
system_locale = system_locale[0].split('_')[0] if system_locale and isinstance(system_locale, list) else 'en'
if system_locale == 'pt':
comment = "Gerencie seus aplicativos Flatpak / Snap / AUR "
elif system_locale == 'es':
comment = "Administre sus aplicaciones Flatpak / Snap / AUR"
else:
comment = "Manage your Flatpak / Snap / AUR applications"
desktop_file = """
[Desktop Entry]
Type = Application
Name = bauh
Categories = System;
Comment = {comment}
Type=Application
Name=bauh
Categories=System;
Comment=Manage your Flatpak / Snap / AUR applications
Comment[pt]=Gerencie seus aplicativos Flatpak / Snap / AUR
Comment[es]=Administre sus aplicaciones Flatpak / Snap / AUR
Exec = {path}
Icon = {lib_path}/python{version}/site-packages/bauh/view/resources/img/logo.svg
"""
@@ -30,5 +21,4 @@ app_cmd = os.getenv('BAUH_PATH', '/usr/bin/bauh')
with open('bauh.desktop', 'w+') as f:
f.write(desktop_file.format(lib_path=os.getenv('BAUH_LIB_PATH', '/usr/lib'),
version=py_version,
path=app_cmd,
comment=comment))
path=app_cmd))

View File

@@ -1,27 +1,18 @@
# Generates a .desktop file based on the current python version. Used for AUR installation
import locale
import os
import sys
system_locale = locale.getdefaultlocale()
system_locale = system_locale[0].split('_')[0] if system_locale and isinstance(system_locale, list) else 'en'
if system_locale == 'pt':
comment = "Gerencie seus aplicativos Flatpak / Snap / AUR "
tray = 'bandeja'
elif system_locale == 'es':
comment = "Administre sus aplicativos Flatpak / Snap / AUR"
tray = 'bandeja'
else:
comment = "Manage your Flatpak / Snap / AUR applications"
tray = 'tray'
desktop_file = """
[Desktop Entry]
Type = Application
Name = bauh ( {tray} )
Name = bauh ( tray )
Name[pt] = bauh ( bandeja )
Name[es] = bauh ( bandeja )
Categories = System;
Comment = {comment}
Comment=Manage your Flatpak / Snap / AUR applications
Comment[pt]=Gerencie seus aplicativos Flatpak / Snap / AUR
Comment[es]=Administre sus aplicaciones Flatpak / Snap / AUR
Exec = {path}
Icon = {lib_path}/python{version}/site-packages/bauh/view/resources/img/logo.svg
"""
@@ -33,9 +24,7 @@ app_cmd = os.getenv('BAUH_PATH', '/usr/bin/bauh') + ' --tray=1'
with open('bauh_tray.desktop', 'w+') as f:
f.write(desktop_file.format(lib_path=os.getenv('BAUH_LIB_PATH', '/usr/lib'),
version=py_version,
path=app_cmd,
comment=comment,
tray=tray))
path=app_cmd))
with open('bauh-tray', 'w') as f:

View File

@@ -1,4 +1,4 @@
__version__ = '0.6.1'
__version__ = '0.6.2'
__app_name__ = 'bauh'
import os

View File

@@ -32,7 +32,6 @@ class ApplicationContext:
self.cache_factory = cache_factory
self.disk_loader_factory = disk_loader_factory
self.logger = logger
self.linux_distro = platform.linux_distribution()
self.file_downloader = file_downloader
self.arch_x86_64 = sys.maxsize > 2**32

View File

@@ -196,8 +196,9 @@ class SoftwareManager(ABC):
pass
@abstractmethod
def list_updates(self) -> List[PackageUpdate]:
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
"""
:param internet_available
:return: available package updates
"""
pass

View File

@@ -25,7 +25,7 @@ def main():
logger = logs.new_logger(__app_name__, bool(args.logs))
app_args.validate(args, logger)
i18n = util.get_locale_keys(args.locale)
i18n_key, i18n = util.get_locale_keys(args.locale)
cache_cleaner = CacheCleaner()
cache_factory = DefaultMemoryCacheFactory(expiration_time=args.cache_exp, cleaner=cache_cleaner)
@@ -53,7 +53,7 @@ def main():
if app.style().objectName().lower() not in {'fusion', 'breeze'}:
app.setStyle('Fusion')
managers = gems.load_managers(context=context, locale=args.locale, config=user_config)
managers = gems.load_managers(context=context, locale=i18n_key, config=user_config)
manager = GenericSoftwareManager(managers, context=context, app_args=args)
manager.prepare()

View File

@@ -14,8 +14,7 @@ def read() -> Namespace:
help='default memory caches expiration time in SECONDS. Default: %(default)s')
parser.add_argument('-ie', '--icon-exp', action="store", default=int(os.getenv('BAUH_ICON_EXPIRATION', 60 * 5)),
type=int, help='cached icons expiration time in SECONDS. Default: %(default)s')
parser.add_argument('-l', '--locale', action="store", default=os.getenv('BAUH_LOCALE', 'en'),
help='Translation key. Default: %(default)s')
parser.add_argument('-l', '--locale', action="store", default=os.getenv('BAUH_LOCALE'), help='Locale key. e.g: en, es, pt, ...')
parser.add_argument('-i', '--check-interval', action="store", default=int(os.getenv('BAUH_CHECK_INTERVAL', 60)),
type=int, help='Updates check interval in SECONDS. Default: %(default)s')
parser.add_argument('-n', '--system-notifications', action="store", choices=[0, 1],
@@ -48,7 +47,7 @@ def validate(args: Namespace, logger: logging.Logger):
if args.icon_exp < 0:
logger.info("'icon-exp' set to '{}': cache will not expire.".format(args.cache_exp))
if not args.locale.strip():
if args.locale and not args.locale.strip():
logger.info("'locale' set as '{}'. You must provide a valid one. Aborting...".format(args.locale))
exit(1)

View File

@@ -210,7 +210,8 @@ def new_root_subprocess(cmd: List[str], root_password: str, cwd: str = '.',
pwdin = new_subprocess(['echo', root_password], global_interpreter=global_interpreter, lang=lang).stdout
final_cmd.extend(cmd)
return subprocess.Popen(final_cmd, stdin=pwdin, stdout=PIPE, stderr=PIPE, cwd=cwd)
return subprocess.Popen(final_cmd, stdin=pwdin, stdout=PIPE, stderr=PIPE, cwd=cwd, env=gen_env(global_interpreter, lang))
def notify_user(msg: str, app_name: str, icon_path: str):

View File

@@ -50,7 +50,7 @@ class ArchManager(SoftwareManager):
self.comp_optimizer = ArchCompilationOptimizer(context.logger)
self.logger = context.logger
self.enabled = True
self.arch_distro = self.context.linux_distro[0].lower() == 'arch'
self.arch_distro = os.path.exists('/etc/arch-release')
def _upgrade_search_result(self, apidata: dict, installed_pkgs: dict, downgrade_enabled: bool, res: SearchResult, disk_loader: DiskCacheLoader):
app = self.mapper.map_api_data(apidata, installed_pkgs['not_signed'])
@@ -156,6 +156,7 @@ class ArchManager(SoftwareManager):
apps = []
if installed and installed['not_signed']:
self.dcache_updater.join()
self._fill_aur_pkgs(installed['not_signed'], apps, disk_loader, internet_available)
return SearchResult(apps, None, len(apps))
@@ -270,6 +271,8 @@ class ArchManager(SoftwareManager):
if pkg.pkgbuild:
info['13_pkg_build'] = pkg.pkgbuild
info['14_installed_files'] = pacman.list_installed_files(pkg.name)
return info
else:
info = {
@@ -295,7 +298,7 @@ class ArchManager(SoftwareManager):
info['12_optdepends'] = srcinfo['optdepends']
if pkg.pkgbuild:
info['13_pkg_build'] = pkg.pkgbuild
info['00_pkg_build'] = pkg.pkgbuild
else:
info['11_pkg_build_url'] = pkg.get_pkg_build_url()
@@ -422,7 +425,7 @@ class ArchManager(SoftwareManager):
# building main package
handler.watcher.change_substatus(self.i18n['arch.building.package'].format(bold(pkgname)))
pkgbuilt, output = handler.handle_simple(SimpleProcess(['makepkg', '-ALcsmf'], cwd=project_dir, lang=None))
pkgbuilt, output = handler.handle_simple(SimpleProcess(['makepkg', '-ALcsmf'], cwd=project_dir))
self._update_progress(handler.watcher, 65, change_progress)
if pkgbuilt:
@@ -689,8 +692,9 @@ class ArchManager(SoftwareManager):
self.comp_optimizer.start()
self.aur_index_updater.start()
def list_updates(self) -> List[PackageUpdate]:
return [PackageUpdate(app.id, app.latest_version, 'aur') for app in self.read_installed(disk_loader=None).installed if app.update]
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
installed = self.read_installed(disk_loader=None, internet_available=internet_available).installed
return [PackageUpdate(p.id, p.latest_version, 'aur') for p in installed if p.update]
def list_warnings(self) -> List[str]:
warnings = []

View File

@@ -150,6 +150,20 @@ def list_bin_paths(pkgnames: Set[str]) -> List[str]:
return bin_paths
def list_installed_files(pkgname: str) -> List[str]:
installed_files = new_subprocess(['pacman', '-Qlq', pkgname])
f_paths = []
for out in new_subprocess(['grep', '-E', '/.+\..+[^/]$'], stdin=installed_files.stdout).stdout:
if out:
line = out.decode().strip()
if line:
f_paths.append(line)
return f_paths
def verify_pgp_key(key: str) -> bool:
list_key = new_subprocess(['pacman-key', '-l']).stdout
@@ -168,3 +182,4 @@ def receive_key(key: str, root_password: str) -> SystemProcess:
def sign_key(key: str, root_password: str) -> SystemProcess:
return SystemProcess(new_root_subprocess(['pacman-key', '--lsign-key', key], root_password=root_password), check_error_output=False)

View File

@@ -22,6 +22,7 @@ arch.clone=Cloning the AUR repository {}
arch.downgrade.reading_commits=Reading the repository commits
arch.downgrade.version_found=Current package version found
arch.downgrade.install_older=Installing older version
aur.info.00_pkg_build=pkgbuild
aur.info.01_id=id
aur.info.02_name=name
aur.info.03_version=version
@@ -36,6 +37,7 @@ aur.info.11_pkg_build_url=url pkgbuild
aur.info.13_pkg_build=pkgbuild
aur.info.11_dependson=dependencies
aur.info.12_optdepends=optional dependencies
aur.info.14_installed_files=Installed files
arch.install.dep_not_found.title=Dependency not found
arch.install.dep_not_found.body=Required dependency {} was not found in AUR nor in default mirrors. Installation cancelled.
arch.install.dependency.install=Installing package dependency {}

View File

@@ -54,6 +54,7 @@ arch.clone=Clonando el repositorio {} de AUR
arch.downgrade.reading_commits=Leyendo los commits del repositorio
arch.downgrade.version_found=Version actual del paquete encontrada
arch.downgrade.install_older=Instalando versión anterior
aur.info.00_pkg_build=pkgbuild
aur.info.01_id=id
aur.info.02_name=nombre
aur.info.03_version=versión
@@ -68,6 +69,7 @@ aur.info.11_pkg_build_url=url pkgbuild
aur.info.13_pkg_build=pkgbuild
aur.info.11_dependson=dependencias
aur.info.12_optdepends=dependencias opcionales
aur.info.14_installed_files=Archivos instalados
arch.install.dep_not_found.title=Dependencia no encontrada
arch.install.dep_not_found.body=No se encontró la dependencia requerida {} en AUR ni en los espejos predeterminados. Instalación cancelada.
arch.install.dependency.install=Instalando el paquete dependiente {}

View File

@@ -54,6 +54,7 @@ arch.clone=Clonando o repositório {} do AUR
arch.downgrade.reading_commits=Lendo os commits do repositório
arch.downgrade.version_found=Versão atual do pacote encontrada
arch.downgrade.install_older=Instalando versão anterior
aur.info.00_pkg_build=pkgbuild
aur.info.01_id=id
aur.info.02_name=nome
aur.info.03_version=versão
@@ -68,6 +69,7 @@ aur.info.11_pkg_build_url=url pkgbuild
aur.info.13_pkg_build=pkgbuild
aur.info.11_dependson=dependências
aur.info.12_optdepends=dependências opcionais
aur.info.14_installed_files=Arquivos instalados
arch.install.dep_not_found.title=Dependência não encontrada
arch.install.dep_not_found.body=A dependência {} não foi encontrado no AUR nem nos espelhos padrões. Instalação cancelada.
arch.install.dependency.install=Instalando o pacote dependente {}

View File

@@ -139,7 +139,10 @@ class FlatpakManager(SoftwareManager):
app_info['name'] = app.name
app_info['type'] = 'runtime' if app.runtime else 'app'
app_info['description'] = strip_html(app.description) if app.description else ''
app_info['installed'] = app_info['installed'].replace('?', ' ')
if app_info.get('installed'):
app_info['installed'] = app_info['installed'].replace('?', ' ')
return app_info
def get_history(self, pkg: FlatpakApplication) -> PackageHistory:
@@ -184,26 +187,28 @@ class FlatpakManager(SoftwareManager):
def prepare(self):
pass
def list_updates(self) -> List[PackageUpdate]:
to_update = [app for app in self.read_installed(None).installed if app.update]
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
updates = []
installed = self.read_installed(None, internet_available=internet_available).installed
to_update = [p for p in installed if p.update]
if to_update:
loaders = []
loaders = []
for app in to_update:
if app.is_application():
loader = FlatpakUpdateLoader(app=app, http_client=self.context.http_client)
loader.start()
loaders.append(loader)
for app in to_update:
if app.is_application():
loader = FlatpakUpdateLoader(app=app, http_client=self.context.http_client)
loader.start()
loaders.append(loader)
for loader in loaders:
loader.join()
for loader in loaders:
loader.join()
for app in to_update:
updates.append(PackageUpdate(pkg_id='{}:{}'.format(app.id, app.branch),
pkg_type='flatpak',
version=app.version))
for app in to_update:
updates.append(PackageUpdate(pkg_id='{}:{}'.format(app.id, app.branch),
pkg_type='flatpak',
version=app.version))
return updates

View File

@@ -140,7 +140,7 @@ class SnapManager(SoftwareManager):
def prepare(self):
pass
def list_updates(self) -> List[PackageUpdate]:
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
pass
def list_warnings(self) -> List[str]:

View File

@@ -7,6 +7,8 @@ snap.info.revision=revisión
snap.info.tracking=tracking
snap.info.installed=instalado
snap.info.publisher=publicador
snap.info.version=versión
snap.info.size=tamaño
snap.notification.snapd_unavailable={} no parece estar instalado o habilitado. Los paquetes {} estarán indisponibles.
snap.notification.snap.disable=Si no desea usar aplicativos Snap, desmarque {} en {}
snap.action.refresh.status=Actualizando

View File

@@ -7,6 +7,8 @@ snap.info.revision=revisão
snap.info.tracking=tracking
snap.info.installed=instalado
snap.info.publisher=publicador
snap.info.version=versão
snap.info.size=tamanho
snap.notification.snapd_unavailable={} não parece estar instalado ou habilitado. Os pacotes {} estarão indisponíveis.
snap.notification.snap.disable=Se não deseja usar aplicativos Snap, desmarque {} em {}
snap.action.refresh.status=Atualizando

View File

@@ -63,7 +63,16 @@ def get_info(app_name: str, attrs: tuple = None):
info_map = re.findall(r'({}):\s+(.+)'.format(re_attrs), full_info_lines)
for info in info_map:
data[info[0]] = info[1].strip()
val = info[1].strip()
if info[0] == 'installed':
val_split = [s for s in val.split(' ') if s]
data['version'] = val_split[0]
if len(val_split) > 2:
data['size'] = val_split[2]
else:
data[info[0]] = val
if not attrs or 'description' in attrs:
desc = re.findall(r'\|\n+((\s+.+\n+)+)', full_info_lines)
@@ -180,7 +189,7 @@ def run(app: SnapApplication, logger: logging.Logger):
break
if not command:
for c in command:
for c in commands:
if not c.endswith('.apm'):
command = c

View File

@@ -143,12 +143,12 @@ class GenericSoftwareManager(SoftwareManager):
t.start()
return t
def read_installed(self, disk_loader: DiskCacheLoader = None, limit: int = -1, only_apps: bool = False, pkg_types: Set[Type[SoftwarePackage]] = None, internet_available: bool = None) -> SearchResult:
def read_installed(self, disk_loader: DiskCacheLoader = None, limit: int = -1, only_apps: bool = False, pkg_types: Set[Type[SoftwarePackage]] = None, net_check: bool = None) -> SearchResult:
ti = time.time()
self._wait_to_be_ready()
internet_available = {}
thread_internet_check = self._get_internet_check(internet_available)
net_check = {}
thread_internet_check = self._get_internet_check(net_check)
res = SearchResult([], None, 0)
@@ -165,7 +165,7 @@ class GenericSoftwareManager(SoftwareManager):
thread_internet_check.join()
mti = time.time()
man_res = man.read_installed(disk_loader=disk_loader, pkg_types=None, internet_available=internet_available['available'])
man_res = man.read_installed(disk_loader=disk_loader, pkg_types=None, internet_available=net_check['available'])
mtf = time.time()
self.logger.info(man.__class__.__name__ + " took {0:.2f} seconds".format(mtf - mti))
@@ -184,7 +184,7 @@ class GenericSoftwareManager(SoftwareManager):
thread_internet_check.join()
mti = time.time()
man_res = man.read_installed(disk_loader=disk_loader, pkg_types=None, internet_available=internet_available['available'])
man_res = man.read_installed(disk_loader=disk_loader, pkg_types=None, internet_available=net_check['available'])
mtf = time.time()
self.logger.info(man.__class__.__name__ + " took {0:.2f} seconds".format(mtf - mti))
@@ -286,15 +286,22 @@ class GenericSoftwareManager(SoftwareManager):
self.thread_prepare = Thread(target=self._prepare)
self.thread_prepare.start()
def list_updates(self) -> List[PackageUpdate]:
def list_updates(self, net_check: bool = None) -> List[PackageUpdate]:
self._wait_to_be_ready()
updates = []
if self.managers:
net_check = {}
thread_internet_check = self._get_internet_check(net_check)
for man in self.managers:
if self._can_work(man):
man_updates = man.list_updates()
if thread_internet_check.is_alive():
thread_internet_check.join()
man_updates = man.list_updates(internet_available=net_check['available'])
if man_updates:
updates.extend(man_updates)

View File

@@ -34,7 +34,7 @@ def load_managers(locale: str, context: ApplicationContext, config: Configuratio
locale_path = '{}/resources/locale'.format(f.path)
if os.path.exists(locale_path):
context.i18n.update(util.get_locale_keys(locale, locale_path))
context.i18n.update(util.get_locale_keys(locale, locale_path)[1])
man = manager_class(context=context)

View File

@@ -1,4 +1,5 @@
import time
from io import StringIO
from threading import Lock, Thread
from typing import List
@@ -96,7 +97,23 @@ class TrayIcon(QSystemTrayIcon):
if update_keys.difference(self.last_updates):
self.last_updates = update_keys
n_updates = len(updates)
msg = self.i18n['notification.update{}'.format('' if n_updates == 1 else 's')].format(n_updates)
ups_by_type = {}
for key in update_keys:
ptype = key.split(':')[0]
count = ups_by_type.get(ptype)
count = 1 if count is None else count + 1
ups_by_type[ptype] = count
msg = StringIO()
msg.write(self.i18n['notification.update{}'.format('' if n_updates == 1 else 's')].format(n_updates))
if len(ups_by_type) > 1:
for ptype, count in ups_by_type.items():
msg.write('\n * {} ( {} )'.format(ptype.capitalize(), count))
msg.seek(0)
msg = msg.read()
self.setToolTip(msg)
if self.update_notification and notify_user:

View File

@@ -261,6 +261,7 @@ class ManageWindow(QWidget):
self.filter_updates = False
self._maximized = False
self.progress_controll_enabled = True
self.recent_installation = False
self.dialog_about = None
self.first_refresh = suggestions
@@ -403,6 +404,7 @@ class ManageWindow(QWidget):
self.textarea_output.hide()
def refresh_apps(self, keep_console: bool = True, top_app: PackageView = None, pkg_types: Set[Type[SoftwarePackage]] = None):
self.recent_installation = False
self.type_filter = None
self.input_search.clear()
@@ -417,11 +419,11 @@ class ManageWindow(QWidget):
self.thread_refresh.pkg_types = pkg_types
self.thread_refresh.start()
def _finish_refresh_apps(self, res: dict):
def _finish_refresh_apps(self, res: dict, as_installed: bool = True):
self.finish_action()
self.ref_checkbox_only_apps.setVisible(bool(res['installed']))
self.ref_bt_upgrade.setVisible(True)
self.update_pkgs(res['installed'], as_installed=True, types=res['types'])
self.update_pkgs(res['installed'], as_installed=as_installed, types=res['types'])
self.first_refresh = False
def uninstall_app(self, app: PackageView):
@@ -618,7 +620,7 @@ class ManageWindow(QWidget):
self.thread_verify_models.start()
if self.pkgs_installed:
self.ref_bt_installed.setVisible(not as_installed)
self.ref_bt_installed.setVisible(not as_installed and not self.recent_installation)
self.resize_and_center(accept_lower_width=self.pkgs_installed)
@@ -892,6 +894,7 @@ class ManageWindow(QWidget):
self.textarea_output.appendPlainText("[warning] Could not write install log file to '{}'".format(log_path))
if res['success']:
self.recent_installation = True
if self._can_notify_user():
util.notify_user(msg='{} ({}) {}'.format(res['pkg'].model.name, res['pkg'].model.get_type(), self.i18n['installed']))

View File

@@ -3,6 +3,7 @@ import locale
import os
import subprocess
import sys
from typing import Tuple
from PyQt5.QtCore import QCoreApplication
@@ -10,7 +11,7 @@ from bauh import __app_name__
from bauh.view.util import resource
def get_locale_keys(key: str = None, locale_dir: str = resource.get_path('locale')):
def get_locale_keys(key: str = None, locale_dir: str = resource.get_path('locale')) -> Tuple[str, dict]:
locale_path = None
@@ -41,7 +42,7 @@ def get_locale_keys(key: str = None, locale_dir: str = resource.get_path('locale
keyval = line.strip().split('=')
locale_obj[keyval[0].strip()] = keyval[1].strip()
return locale_obj
return locale_path.split('/')[-1], locale_obj
def notify_user(msg: str, icon_path: str = resource.get_path('img/logo.svg')):