mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 00:04:15 +02:00
[improvement] Not breaking the application when a i18n (translation) key was not found
This commit is contained in:
@@ -4,6 +4,10 @@ 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/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
## [0.7.3]
|
||||||
|
### Improvements
|
||||||
|
- Not breaking the application when a i18n (translation) key was not found
|
||||||
|
|
||||||
## [0.7.2] 2019-11-01
|
## [0.7.2] 2019-11-01
|
||||||
### Improvements
|
### Improvements
|
||||||
- Snap
|
- Snap
|
||||||
|
|||||||
@@ -20,3 +20,11 @@ The way to go here is to ask yourself if the improvement would be useful for mor
|
|||||||
* Explain why you think these changes could be useful
|
* Explain why you think these changes could be useful
|
||||||
* If it fixes a bug, be sure to link to the issue itself.
|
* If it fixes a bug, be sure to link to the issue itself.
|
||||||
* Follow the [PEP 8](https://www.python.org/dev/peps/pep-0008/) code style to keep the code consistent.
|
* Follow the [PEP 8](https://www.python.org/dev/peps/pep-0008/) code style to keep the code consistent.
|
||||||
|
|
||||||
|
# Adding a new translation
|
||||||
|
* To add a new translation, you will have to create a file in each directory listed below named as the first two letters in the ISO format (e.g: for 'english' would be 'en'):
|
||||||
|
- **bauh/view/resources/locale**
|
||||||
|
- **bauh/gems/appimage/resources/locale**
|
||||||
|
- **bauh/gems/arch/resources/locale**
|
||||||
|
- **bauh/gems/flatpak/resources/locale**
|
||||||
|
- **bauh/gems/snap/resources/locale**
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -5,6 +5,8 @@ It has a **tray mode** (see **Settings** below) that attaches the application ic
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
To contribute with this project, have a look at [CONTRIBUTING.md](https://github.com/vinifmor/bauh/blob/master/CONTRIBUTING.md)
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -65,13 +67,13 @@ If you do not want to clone / download this repository, go to your **Home** fold
|
|||||||
In order to autostart the application, use your Desktop Environment settings to register it as a startup application / script (**bauh --tray=1**).
|
In order to autostart the application, use your Desktop Environment settings to register it as a startup application / script (**bauh --tray=1**).
|
||||||
|
|
||||||
### Gems ( package technology support )
|
### Gems ( package technology support )
|
||||||
#### Flatpak ( flatpak gem )
|
#### Flatpak ( flatpak )
|
||||||
- The user is able to search, install, uninstall, downgrade, launch and retrieve the applications history
|
- The user is able to search, install, uninstall, downgrade, launch and retrieve the applications history
|
||||||
|
|
||||||
#### Snap ( snap gem )
|
#### Snap ( snap )
|
||||||
- The user is able to search, install, uninstall, refresh, launch and downgrade applications
|
- The user is able to search, install, uninstall, refresh, launch and downgrade applications
|
||||||
|
|
||||||
#### AUR ( arch gem )
|
#### AUR ( arch )
|
||||||
- It is **not enabled by default**
|
- It is **not enabled by default**
|
||||||
- The user is able to search, install, uninstall, downgrade, launch and retrieve the packages history
|
- 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 )
|
- It handles conflicts, and missing / optional packages installations ( including from your distro mirrors )
|
||||||
@@ -90,7 +92,7 @@ will be pre-downloaded faster ( it does **NOT** modify your **pacman** settings
|
|||||||
- Arch package memory-indexer running every 20 minutes. This memory index is used when AUR Api cannot handle the amount of results found for a given search. It can be disabled via the environment variable **BAUH_ARCH_AUR_INDEX_UPDATER=0**.
|
- Arch package memory-indexer running every 20 minutes. This memory index is used when AUR Api cannot handle the amount of results found for a given search. It can be disabled via the environment variable **BAUH_ARCH_AUR_INDEX_UPDATER=0**.
|
||||||
- If some of your installed packages are not categorized, send an e-mail to **bauh4linux@gmail.com** informing their names and categories in the following format: ```name=category1[,category2,category3,...]```
|
- If some of your installed packages are not categorized, send an e-mail to **bauh4linux@gmail.com** informing their names and categories in the following format: ```name=category1[,category2,category3,...]```
|
||||||
|
|
||||||
#### AppImage ( appimage gem )
|
#### AppImage ( appimage )
|
||||||
- The user is able to search, install, uninstall, downgrade, launch and retrieve the applications history
|
- The user is able to search, install, uninstall, downgrade, launch and retrieve the applications history
|
||||||
- Supported sources: [AppImageHub](https://appimage.github.io) ( **applications with no releases published to GitHub are currently not available** )
|
- Supported sources: [AppImageHub](https://appimage.github.io) ( **applications with no releases published to GitHub are currently not available** )
|
||||||
- Faster downloads if **aria2c** is installed. Same behavior described in the **AUR support** section.
|
- Faster downloads if **aria2c** is installed. Same behavior described in the **AUR support** section.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = '0.7.2'
|
__version__ = '0.7.3'
|
||||||
__app_name__ = 'bauh'
|
__app_name__ = 'bauh'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import logging
|
import logging
|
||||||
import platform
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from bauh.api.abstract.cache import MemoryCacheFactory
|
from bauh.api.abstract.cache import MemoryCacheFactory
|
||||||
from bauh.api.abstract.disk import DiskCacheLoaderFactory
|
from bauh.api.abstract.disk import DiskCacheLoaderFactory
|
||||||
from bauh.api.abstract.download import FileDownloader
|
from bauh.api.abstract.download import FileDownloader
|
||||||
from bauh.api.http import HttpClient
|
from bauh.api.http import HttpClient
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
class ApplicationContext:
|
class ApplicationContext:
|
||||||
|
|
||||||
def __init__(self, disk_cache: bool, download_icons: bool, http_client: HttpClient, app_root_dir: str, i18n: dict,
|
def __init__(self, disk_cache: bool, download_icons: bool, http_client: HttpClient, app_root_dir: str, i18n: I18n,
|
||||||
cache_factory: MemoryCacheFactory, disk_loader_factory: DiskCacheLoaderFactory,
|
cache_factory: MemoryCacheFactory, disk_loader_factory: DiskCacheLoaderFactory,
|
||||||
logger: logging.Logger, file_downloader: FileDownloader, distro: str):
|
logger: logging.Logger, file_downloader: FileDownloader, distro: str):
|
||||||
"""
|
"""
|
||||||
@@ -18,7 +18,7 @@ class ApplicationContext:
|
|||||||
:param download_icons: if packages icons should be downloaded
|
:param download_icons: if packages icons should be downloaded
|
||||||
:param http_client: a shared instance of http client
|
:param http_client: a shared instance of http client
|
||||||
:param app_root_dir: GUI root dir
|
:param app_root_dir: GUI root dir
|
||||||
:param i18n: the i18n dictionary keys
|
:param i18n: the translation keys
|
||||||
:param cache_factory:
|
:param cache_factory:
|
||||||
:param disk_loader_factory:
|
:param disk_loader_factory:
|
||||||
:param logger: a logger instance
|
:param logger: a logger instance
|
||||||
|
|||||||
11
bauh/app.py
11
bauh/app.py
@@ -12,9 +12,12 @@ from bauh.view.core.controller import GenericSoftwareManager
|
|||||||
from bauh.view.core.downloader import AdaptableFileDownloader
|
from bauh.view.core.downloader import AdaptableFileDownloader
|
||||||
from bauh.view.qt.systray import TrayIcon
|
from bauh.view.qt.systray import TrayIcon
|
||||||
from bauh.view.qt.window import ManageWindow
|
from bauh.view.qt.window import ManageWindow
|
||||||
from bauh.view.util import util, logs, resource
|
from bauh.view.util import util, logs, resource, translation
|
||||||
from bauh.view.util.cache import DefaultMemoryCacheFactory, CacheCleaner
|
from bauh.view.util.cache import DefaultMemoryCacheFactory, CacheCleaner
|
||||||
from bauh.view.util.disk import DefaultDiskCacheLoaderFactory
|
from bauh.view.util.disk import DefaultDiskCacheLoaderFactory
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
DEFAULT_I18N_KEY = 'en'
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -25,7 +28,9 @@ def main():
|
|||||||
logger = logs.new_logger(__app_name__, bool(args.logs))
|
logger = logs.new_logger(__app_name__, bool(args.logs))
|
||||||
app_args.validate(args, logger)
|
app_args.validate(args, logger)
|
||||||
|
|
||||||
i18n_key, i18n = util.get_locale_keys(args.locale)
|
i18n_key, current_i18n = translation.get_locale_keys(args.locale)
|
||||||
|
default_i18n = translation.get_locale_keys(DEFAULT_I18N_KEY)[1] if i18n_key != DEFAULT_I18N_KEY else {}
|
||||||
|
i18n = I18n(current_i18n, default_i18n)
|
||||||
|
|
||||||
cache_cleaner = CacheCleaner()
|
cache_cleaner = CacheCleaner()
|
||||||
cache_factory = DefaultMemoryCacheFactory(expiration_time=args.cache_exp, cleaner=cache_cleaner)
|
cache_factory = DefaultMemoryCacheFactory(expiration_time=args.cache_exp, cleaner=cache_cleaner)
|
||||||
@@ -57,7 +62,7 @@ def main():
|
|||||||
if app.style().objectName().lower() not in {'fusion', 'breeze'}:
|
if app.style().objectName().lower() not in {'fusion', 'breeze'}:
|
||||||
app.setStyle('Fusion')
|
app.setStyle('Fusion')
|
||||||
|
|
||||||
managers = gems.load_managers(context=context, locale=i18n_key, config=user_config)
|
managers = gems.load_managers(context=context, locale=i18n_key, config=user_config, default_locale=DEFAULT_I18N_KEY)
|
||||||
|
|
||||||
manager = GenericSoftwareManager(managers, context=context, app_args=args)
|
manager = GenericSoftwareManager(managers, context=context, app_args=args)
|
||||||
manager.prepare()
|
manager.prepare()
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ from typing import Set
|
|||||||
|
|
||||||
from bauh.api.abstract.handler import ProcessWatcher
|
from bauh.api.abstract.handler import ProcessWatcher
|
||||||
from bauh.api.abstract.view import MultipleSelectComponent, InputOption
|
from bauh.api.abstract.view import MultipleSelectComponent, InputOption
|
||||||
|
|
||||||
from bauh.commons.html import bold
|
from bauh.commons.html import bold
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
def request_optional_deps(pkgname: str, pkg_mirrors: dict, watcher: ProcessWatcher, i18n: dict) -> Set[str]:
|
def request_optional_deps(pkgname: str, pkg_mirrors: dict, watcher: ProcessWatcher, i18n: I18n) -> Set[str]:
|
||||||
opts = [InputOption('{}{} ( {} )'.format(p, ': ' + d['desc'] if d['desc'] else '', d['mirror'].upper()), p) for p, d in pkg_mirrors.items()]
|
opts = [InputOption('{}{} ( {} )'.format(p, ': ' + d['desc'] if d['desc'] else '', d['mirror'].upper()), p) for p, d in pkg_mirrors.items()]
|
||||||
view_opts = MultipleSelectComponent(label='',
|
view_opts = MultipleSelectComponent(label='',
|
||||||
options=opts,
|
options=opts,
|
||||||
@@ -21,7 +21,7 @@ def request_optional_deps(pkgname: str, pkg_mirrors: dict, watcher: ProcessWatch
|
|||||||
return {o.value for o in view_opts.values}
|
return {o.value for o in view_opts.values}
|
||||||
|
|
||||||
|
|
||||||
def request_install_missing_deps(pkgname: str, pkg_mirrors: dict, watcher: ProcessWatcher, i18n: dict) -> bool:
|
def request_install_missing_deps(pkgname: str, pkg_mirrors: dict, watcher: ProcessWatcher, i18n: I18n) -> bool:
|
||||||
deps_str = ''.join(['<br/><span style="font-weight:bold"> - {} ( {} )</span>'.format(d, m.upper()) for d, m in pkg_mirrors.items()])
|
deps_str = ''.join(['<br/><span style="font-weight:bold"> - {} ( {} )</span>'.format(d, m.upper()) for d, m in pkg_mirrors.items()])
|
||||||
msg = '<p>{}</p>'.format(i18n['arch.missing_deps.body'].format(bold(pkgname)) + ':<br/>' + deps_str)
|
msg = '<p>{}</p>'.format(i18n['arch.missing_deps.body'].format(bold(pkgname)) + ':<br/>' + deps_str)
|
||||||
msg += i18n['ask.continue']
|
msg += i18n['ask.continue']
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
from bauh.api.abstract.handler import ProcessWatcher
|
from bauh.api.abstract.handler import ProcessWatcher
|
||||||
from bauh.api.abstract.view import MessageType
|
from bauh.api.abstract.view import MessageType
|
||||||
from bauh.commons.html import bold
|
from bauh.commons.html import bold
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
def show_dep_not_installed(watcher: ProcessWatcher, pkgname: str, depname: str, i18n: dict):
|
def show_dep_not_installed(watcher: ProcessWatcher, pkgname: str, depname: str, i18n: I18n):
|
||||||
watcher.show_message(title=i18n['error'],
|
watcher.show_message(title=i18n['error'],
|
||||||
body=i18n['arch.install.dependency.install.error'].format(bold(depname), bold(pkgname)),
|
body=i18n['arch.install.dependency.install.error'].format(bold(depname), bold(pkgname)),
|
||||||
type_=MessageType.ERROR)
|
type_=MessageType.ERROR)
|
||||||
|
|
||||||
|
|
||||||
def show_dep_not_found(depname: str, i18n: dict, watcher: ProcessWatcher):
|
def show_dep_not_found(depname: str, i18n: I18n, watcher: ProcessWatcher):
|
||||||
watcher.show_message(title=i18n['arch.install.dep_not_found.title'],
|
watcher.show_message(title=i18n['arch.install.dep_not_found.title'],
|
||||||
body=i18n['arch.install.dep_not_found.body'].format(bold(depname)),
|
body=i18n['arch.install.dep_not_found.body'].format(bold(depname)),
|
||||||
type_=MessageType.ERROR)
|
type_=MessageType.ERROR)
|
||||||
|
|
||||||
|
|
||||||
def show_optdep_not_installed(depname: str, watcher: ProcessWatcher, i18n: dict):
|
def show_optdep_not_installed(depname: str, watcher: ProcessWatcher, i18n: I18n):
|
||||||
watcher.show_message(title=i18n['error'],
|
watcher.show_message(title=i18n['error'],
|
||||||
body=i18n['arch.install.optdep.error'].format(bold(depname)),
|
body=i18n['arch.install.optdep.error'].format(bold(depname)),
|
||||||
type_=MessageType.ERROR)
|
type_=MessageType.ERROR)
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ from bauh.api.abstract.handler import ProcessWatcher
|
|||||||
from bauh.api.http import HttpClient
|
from bauh.api.http import HttpClient
|
||||||
from bauh.commons.html import bold
|
from bauh.commons.html import bold
|
||||||
from bauh.commons.system import run_cmd, new_subprocess, ProcessHandler, SystemProcess, SimpleProcess
|
from bauh.commons.system import run_cmd, new_subprocess, ProcessHandler, SystemProcess, SimpleProcess
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
class AdaptableFileDownloader(FileDownloader):
|
class AdaptableFileDownloader(FileDownloader):
|
||||||
|
|
||||||
def __init__(self, logger: logging.Logger, multithread_enabled: bool, i18n: dict, http_client: HttpClient):
|
def __init__(self, logger: logging.Logger, multithread_enabled: bool, i18n: I18n, http_client: HttpClient):
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
self.multithread_enabled = multithread_enabled
|
self.multithread_enabled = multithread_enabled
|
||||||
self.i18n = i18n
|
self.i18n = i18n
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from typing import List
|
|||||||
from bauh import ROOT_DIR
|
from bauh import ROOT_DIR
|
||||||
from bauh.api.abstract.controller import SoftwareManager, ApplicationContext
|
from bauh.api.abstract.controller import SoftwareManager, ApplicationContext
|
||||||
from bauh.view.core.config import Configuration
|
from bauh.view.core.config import Configuration
|
||||||
from bauh.view.util import util
|
from bauh.view.util import util, translation
|
||||||
|
|
||||||
|
|
||||||
def find_manager(member):
|
def find_manager(member):
|
||||||
@@ -20,7 +20,7 @@ def find_manager(member):
|
|||||||
return manager_found
|
return manager_found
|
||||||
|
|
||||||
|
|
||||||
def load_managers(locale: str, context: ApplicationContext, config: Configuration) -> List[SoftwareManager]:
|
def load_managers(locale: str, context: ApplicationContext, config: Configuration, default_locale: str) -> List[SoftwareManager]:
|
||||||
managers = []
|
managers = []
|
||||||
|
|
||||||
for f in os.scandir(ROOT_DIR + '/gems'):
|
for f in os.scandir(ROOT_DIR + '/gems'):
|
||||||
@@ -37,7 +37,10 @@ def load_managers(locale: str, context: ApplicationContext, config: Configuratio
|
|||||||
locale_path = '{}/resources/locale'.format(f.path)
|
locale_path = '{}/resources/locale'.format(f.path)
|
||||||
|
|
||||||
if os.path.exists(locale_path):
|
if os.path.exists(locale_path):
|
||||||
context.i18n.update(util.get_locale_keys(locale, locale_path)[1])
|
context.i18n.current.update(translation.get_locale_keys(locale, locale_path)[1])
|
||||||
|
|
||||||
|
if default_locale and context.i18n.default:
|
||||||
|
context.i18n.default.update(translation.get_locale_keys(default_locale, locale_path)[1])
|
||||||
|
|
||||||
man = manager_class(context=context)
|
man = manager_class(context=context)
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtGui import QPixmap, QIcon
|
from PyQt5.QtGui import QPixmap
|
||||||
from PyQt5.QtWidgets import QVBoxLayout, QDialog, QLabel, QWidget, QHBoxLayout
|
from PyQt5.QtWidgets import QVBoxLayout, QDialog, QLabel, QWidget, QHBoxLayout
|
||||||
|
|
||||||
from bauh import __version__, __app_name__, ROOT_DIR
|
from bauh import __version__, __app_name__, ROOT_DIR
|
||||||
from bauh.view.util import resource
|
from bauh.view.util import resource
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
PROJECT_URL = 'https://github.com/vinifmor/' + __app_name__
|
PROJECT_URL = 'https://github.com/vinifmor/' + __app_name__
|
||||||
LICENSE_URL = 'https://raw.githubusercontent.com/vinifmor/{}/master/LICENSE'.format(__app_name__)
|
LICENSE_URL = 'https://raw.githubusercontent.com/vinifmor/{}/master/LICENSE'.format(__app_name__)
|
||||||
@@ -13,9 +14,9 @@ LICENSE_URL = 'https://raw.githubusercontent.com/vinifmor/{}/master/LICENSE'.for
|
|||||||
|
|
||||||
class AboutDialog(QDialog):
|
class AboutDialog(QDialog):
|
||||||
|
|
||||||
def __init__(self, locale_keys: dict):
|
def __init__(self, i18n: I18n):
|
||||||
super(AboutDialog, self).__init__()
|
super(AboutDialog, self).__init__()
|
||||||
self.setWindowTitle(locale_keys['tray.action.about'])
|
self.setWindowTitle(i18n['tray.action.about'])
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ class AboutDialog(QDialog):
|
|||||||
|
|
||||||
line_desc = QLabel(self)
|
line_desc = QLabel(self)
|
||||||
line_desc.setStyleSheet('font-size: 12px; font-weight: bold;')
|
line_desc.setStyleSheet('font-size: 12px; font-weight: bold;')
|
||||||
line_desc.setText(locale_keys['about.info.desc'])
|
line_desc.setText(i18n['about.info.desc'])
|
||||||
line_desc.setAlignment(Qt.AlignCenter)
|
line_desc.setAlignment(Qt.AlignCenter)
|
||||||
line_desc.setMinimumWidth(400)
|
line_desc.setMinimumWidth(400)
|
||||||
layout.addWidget(line_desc)
|
layout.addWidget(line_desc)
|
||||||
@@ -55,21 +56,21 @@ class AboutDialog(QDialog):
|
|||||||
layout.addWidget(gems_widget)
|
layout.addWidget(gems_widget)
|
||||||
layout.addWidget(QLabel(''))
|
layout.addWidget(QLabel(''))
|
||||||
|
|
||||||
label_version = QLabel(locale_keys['version'].lower() + ' ' + __version__)
|
label_version = QLabel(i18n['version'].lower() + ' ' + __version__)
|
||||||
label_version.setStyleSheet('QLabel { font-size: 11px; font-weight: bold }')
|
label_version.setStyleSheet('QLabel { font-size: 11px; font-weight: bold }')
|
||||||
label_version.setAlignment(Qt.AlignCenter)
|
label_version.setAlignment(Qt.AlignCenter)
|
||||||
layout.addWidget(label_version)
|
layout.addWidget(label_version)
|
||||||
|
|
||||||
label_more_info = QLabel()
|
label_more_info = QLabel()
|
||||||
label_more_info.setStyleSheet('font-size: 11px;')
|
label_more_info.setStyleSheet('font-size: 11px;')
|
||||||
label_more_info.setText(locale_keys['about.info.link'] + ": <a href='{url}'>{url}</a>".format(url=PROJECT_URL))
|
label_more_info.setText(i18n['about.info.link'] + ": <a href='{url}'>{url}</a>".format(url=PROJECT_URL))
|
||||||
label_more_info.setOpenExternalLinks(True)
|
label_more_info.setOpenExternalLinks(True)
|
||||||
label_more_info.setAlignment(Qt.AlignCenter)
|
label_more_info.setAlignment(Qt.AlignCenter)
|
||||||
layout.addWidget(label_more_info)
|
layout.addWidget(label_more_info)
|
||||||
|
|
||||||
label_license = QLabel()
|
label_license = QLabel()
|
||||||
label_license.setStyleSheet('font-size: 11px;')
|
label_license.setStyleSheet('font-size: 11px;')
|
||||||
label_license.setText("<a href='{}'>{}</a>".format(LICENSE_URL, locale_keys['about.info.license']))
|
label_license.setText("<a href='{}'>{}</a>".format(LICENSE_URL, i18n['about.info.license']))
|
||||||
label_license.setOpenExternalLinks(True)
|
label_license.setOpenExternalLinks(True)
|
||||||
label_license.setAlignment(Qt.AlignCenter)
|
label_license.setAlignment(Qt.AlignCenter)
|
||||||
layout.addWidget(label_license)
|
layout.addWidget(label_license)
|
||||||
@@ -78,7 +79,7 @@ class AboutDialog(QDialog):
|
|||||||
|
|
||||||
label_rate = QLabel()
|
label_rate = QLabel()
|
||||||
label_rate.setStyleSheet('font-size: 11px; font-weight: bold;')
|
label_rate.setStyleSheet('font-size: 11px; font-weight: bold;')
|
||||||
label_rate.setText(locale_keys['about.info.rate'] + ' :)')
|
label_rate.setText(i18n['about.info.rate'] + ' :)')
|
||||||
label_rate.setOpenExternalLinks(True)
|
label_rate.setOpenExternalLinks(True)
|
||||||
label_rate.setAlignment(Qt.AlignCenter)
|
label_rate.setAlignment(Qt.AlignCenter)
|
||||||
layout.addWidget(label_rate)
|
layout.addWidget(label_rate)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from bauh.view.qt import dialog
|
|||||||
from bauh.view.qt.components import IconButton
|
from bauh.view.qt.components import IconButton
|
||||||
from bauh.view.qt.view_model import PackageView, PackageViewStatus
|
from bauh.view.qt.view_model import PackageView, PackageViewStatus
|
||||||
from bauh.view.util import resource
|
from bauh.view.util import resource
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
INSTALL_BT_STYLE = 'background: {back}; color: white; font-size: 10px; font-weight: bold'
|
INSTALL_BT_STYLE = 'background: {back}; color: white; font-size: 10px; font-weight: bold'
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ PUBLISHER_MAX_SIZE = 25
|
|||||||
|
|
||||||
class UpdateToggleButton(QWidget):
|
class UpdateToggleButton(QWidget):
|
||||||
|
|
||||||
def __init__(self, app_view: PackageView, root: QWidget, i18n: dict, checked: bool = True, clickable: bool = True):
|
def __init__(self, app_view: PackageView, root: QWidget, i18n: I18n, checked: bool = True, clickable: bool = True):
|
||||||
super(UpdateToggleButton, self).__init__()
|
super(UpdateToggleButton, self).__init__()
|
||||||
|
|
||||||
self.app_view = app_view
|
self.app_view = app_view
|
||||||
@@ -113,7 +114,7 @@ class AppsTable(QTableWidget):
|
|||||||
if dialog.ask_confirmation(
|
if dialog.ask_confirmation(
|
||||||
title=self.i18n['manage_window.apps_table.row.actions.downgrade'],
|
title=self.i18n['manage_window.apps_table.row.actions.downgrade'],
|
||||||
body=self._parag(self.i18n['manage_window.apps_table.row.actions.downgrade.popup.body'].format(self._bold(str(pkg)))),
|
body=self._parag(self.i18n['manage_window.apps_table.row.actions.downgrade.popup.body'].format(self._bold(str(pkg)))),
|
||||||
locale_keys=self.i18n):
|
i18n=self.i18n):
|
||||||
self.window.downgrade(pkg)
|
self.window.downgrade(pkg)
|
||||||
|
|
||||||
action_downgrade.triggered.connect(downgrade)
|
action_downgrade.triggered.connect(downgrade)
|
||||||
@@ -131,7 +132,7 @@ class AppsTable(QTableWidget):
|
|||||||
if dialog.ask_confirmation(
|
if dialog.ask_confirmation(
|
||||||
title=self.i18n[action.i18_label_key],
|
title=self.i18n[action.i18_label_key],
|
||||||
body=self._parag('{} {} ?'.format(self.i18n[action.i18_label_key], self._bold(str(pkg)))),
|
body=self._parag('{} {} ?'.format(self.i18n[action.i18_label_key], self._bold(str(pkg)))),
|
||||||
locale_keys=self.i18n):
|
i18n=self.i18n):
|
||||||
self.window.execute_custom_action(pkg, action)
|
self.window.execute_custom_action(pkg, action)
|
||||||
|
|
||||||
item.triggered.connect(custom_action)
|
item.triggered.connect(custom_action)
|
||||||
@@ -162,7 +163,7 @@ class AppsTable(QTableWidget):
|
|||||||
def _uninstall_app(self, app_v: PackageView):
|
def _uninstall_app(self, app_v: PackageView):
|
||||||
if dialog.ask_confirmation(title=self.i18n['manage_window.apps_table.row.actions.uninstall.popup.title'],
|
if dialog.ask_confirmation(title=self.i18n['manage_window.apps_table.row.actions.uninstall.popup.title'],
|
||||||
body=self._parag(self.i18n['manage_window.apps_table.row.actions.uninstall.popup.body'].format(self._bold(str(app_v)))),
|
body=self._parag(self.i18n['manage_window.apps_table.row.actions.uninstall.popup.body'].format(self._bold(str(app_v)))),
|
||||||
locale_keys=self.i18n):
|
i18n=self.i18n):
|
||||||
self.window.uninstall_app(app_v)
|
self.window.uninstall_app(app_v)
|
||||||
|
|
||||||
def _bold(self, text: str) -> str:
|
def _bold(self, text: str) -> str:
|
||||||
@@ -176,7 +177,7 @@ class AppsTable(QTableWidget):
|
|||||||
if dialog.ask_confirmation(
|
if dialog.ask_confirmation(
|
||||||
title=self.i18n['manage_window.apps_table.row.actions.install.popup.title'],
|
title=self.i18n['manage_window.apps_table.row.actions.install.popup.title'],
|
||||||
body=self._parag(self.i18n['manage_window.apps_table.row.actions.install.popup.body'].format(self._bold(str(pkgv)))),
|
body=self._parag(self.i18n['manage_window.apps_table.row.actions.install.popup.body'].format(self._bold(str(pkgv)))),
|
||||||
locale_keys=self.i18n):
|
i18n=self.i18n):
|
||||||
|
|
||||||
self.window.install(pkgv)
|
self.window.install(pkgv)
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,23 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QMessageBox, QVBoxLayout, QLabel, QWidget
|
from PyQt5.QtWidgets import QMessageBox, QVBoxLayout, QLabel, QWidget
|
||||||
|
|
||||||
from bauh.api.abstract.view import ViewComponent, SingleSelectComponent, MultipleSelectComponent
|
from bauh.api.abstract.view import ViewComponent, SingleSelectComponent, MultipleSelectComponent
|
||||||
from bauh.view.qt import css
|
from bauh.view.qt import css
|
||||||
|
|
||||||
from bauh.view.qt.components import MultipleSelectQt, new_single_select
|
from bauh.view.qt.components import MultipleSelectQt, new_single_select
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
class ConfirmationDialog(QMessageBox):
|
class ConfirmationDialog(QMessageBox):
|
||||||
|
|
||||||
def __init__(self, title: str, body: str, locale_keys: dict, components: List[ViewComponent] = None, confirmation_label: str = None, deny_label: str = None):
|
def __init__(self, title: str, body: str, i18n: I18n, components: List[ViewComponent] = None, confirmation_label: str = None, deny_label: str = None):
|
||||||
super(ConfirmationDialog, self).__init__()
|
super(ConfirmationDialog, self).__init__()
|
||||||
self.setWindowTitle(title)
|
self.setWindowTitle(title)
|
||||||
self.setStyleSheet('QLabel { margin-right: 25px; }')
|
self.setStyleSheet('QLabel { margin-right: 25px; }')
|
||||||
self.bt_yes = self.addButton(locale_keys['popup.button.yes'] if not confirmation_label else confirmation_label.capitalize(), QMessageBox.YesRole)
|
self.bt_yes = self.addButton(i18n['popup.button.yes'] if not confirmation_label else confirmation_label.capitalize(), QMessageBox.YesRole)
|
||||||
self.bt_yes.setStyleSheet(css.OK_BUTTON)
|
self.bt_yes.setStyleSheet(css.OK_BUTTON)
|
||||||
|
|
||||||
self.addButton(locale_keys['popup.button.no'] if not deny_label else deny_label.capitalize(), QMessageBox.NoRole)
|
self.addButton(i18n['popup.button.no'] if not deny_label else deny_label.capitalize(), QMessageBox.NoRole)
|
||||||
|
|
||||||
if body:
|
if body:
|
||||||
if not components:
|
if not components:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from bauh.api.abstract.view import MessageType
|
|||||||
|
|
||||||
from bauh.view.util import resource
|
from bauh.view.util import resource
|
||||||
from bauh.view.qt import css
|
from bauh.view.qt import css
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
MSG_TYPE_MAP = {
|
MSG_TYPE_MAP = {
|
||||||
MessageType.ERROR: QMessageBox.Critical,
|
MessageType.ERROR: QMessageBox.Critical,
|
||||||
@@ -26,7 +27,7 @@ def show_message(title: str, body: str, type_: MessageType, icon: QIcon = QIcon(
|
|||||||
popup.exec_()
|
popup.exec_()
|
||||||
|
|
||||||
|
|
||||||
def ask_confirmation(title: str, body: str, locale_keys: dict, icon: QIcon = QIcon(resource.get_path('img/logo.svg')), widgets: List[QWidget] = None):
|
def ask_confirmation(title: str, body: str, i18n: I18n, icon: QIcon = QIcon(resource.get_path('img/logo.svg')), widgets: List[QWidget] = None):
|
||||||
diag = QMessageBox()
|
diag = QMessageBox()
|
||||||
diag.setIcon(QMessageBox.Question)
|
diag.setIcon(QMessageBox.Question)
|
||||||
diag.setWindowTitle(title)
|
diag.setWindowTitle(title)
|
||||||
@@ -42,10 +43,10 @@ def ask_confirmation(title: str, body: str, locale_keys: dict, icon: QIcon = QIc
|
|||||||
|
|
||||||
diag.layout().addWidget(wbody, 0, 1)
|
diag.layout().addWidget(wbody, 0, 1)
|
||||||
|
|
||||||
bt_yes = diag.addButton(locale_keys['popup.button.yes'], QMessageBox.YesRole)
|
bt_yes = diag.addButton(i18n['popup.button.yes'], QMessageBox.YesRole)
|
||||||
bt_yes.setStyleSheet(css.OK_BUTTON)
|
bt_yes.setStyleSheet(css.OK_BUTTON)
|
||||||
|
|
||||||
diag.addButton(locale_keys['popup.button.no'], QMessageBox.NoRole)
|
diag.addButton(i18n['popup.button.no'], QMessageBox.NoRole)
|
||||||
|
|
||||||
if icon:
|
if icon:
|
||||||
diag.setWindowIcon(icon)
|
diag.setWindowIcon(icon)
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ from bauh.view.core.controller import GenericSoftwareManager
|
|||||||
from bauh.view.util import resource
|
from bauh.view.util import resource
|
||||||
from bauh.view.qt import qt_utils, css
|
from bauh.view.qt import qt_utils, css
|
||||||
from bauh.view.qt.components import MultipleSelectQt, CheckboxQt, new_spacer
|
from bauh.view.qt.components import MultipleSelectQt, CheckboxQt, new_spacer
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
class GemSelectorPanel(QWidget):
|
class GemSelectorPanel(QWidget):
|
||||||
|
|
||||||
def __init__(self, window: QWidget, manager: GenericSoftwareManager, i18n: dict, config: Configuration, show_panel_after_restart: bool = False):
|
def __init__(self, window: QWidget, manager: GenericSoftwareManager, i18n: I18n, config: Configuration, show_panel_after_restart: bool = False):
|
||||||
super(GemSelectorPanel, self).__init__()
|
super(GemSelectorPanel, self).__init__()
|
||||||
self.window = window
|
self.window = window
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ from PyQt5.QtWidgets import QDialog, QVBoxLayout, QTableWidget, QTableWidgetItem
|
|||||||
|
|
||||||
from bauh.api.abstract.cache import MemoryCache
|
from bauh.api.abstract.cache import MemoryCache
|
||||||
from bauh.api.abstract.model import PackageHistory
|
from bauh.api.abstract.model import PackageHistory
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
class HistoryDialog(QDialog):
|
class HistoryDialog(QDialog):
|
||||||
|
|
||||||
def __init__(self, history: PackageHistory, icon_cache: MemoryCache, i18n: dict):
|
def __init__(self, history: PackageHistory, icon_cache: MemoryCache, i18n: I18n):
|
||||||
super(HistoryDialog, self).__init__()
|
super(HistoryDialog, self).__init__()
|
||||||
self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint)
|
self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint)
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ from PyQt5.QtWidgets import QDialog, QVBoxLayout, QGroupBox, \
|
|||||||
QLineEdit, QLabel, QGridLayout, QPushButton, QPlainTextEdit, QToolBar
|
QLineEdit, QLabel, QGridLayout, QPushButton, QPlainTextEdit, QToolBar
|
||||||
|
|
||||||
from bauh.api.abstract.cache import MemoryCache
|
from bauh.api.abstract.cache import MemoryCache
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
IGNORED_ATTRS = {'name', '__app__'}
|
IGNORED_ATTRS = {'name', '__app__'}
|
||||||
|
|
||||||
|
|
||||||
class InfoDialog(QDialog):
|
class InfoDialog(QDialog):
|
||||||
|
|
||||||
def __init__(self, app: dict, icon_cache: MemoryCache, i18n: dict, screen_size: QSize()):
|
def __init__(self, app: dict, icon_cache: MemoryCache, i18n: I18n, screen_size: QSize()):
|
||||||
super(InfoDialog, self).__init__()
|
super(InfoDialog, self).__init__()
|
||||||
self.setWindowTitle(str(app['__app__']))
|
self.setWindowTitle(str(app['__app__']))
|
||||||
self.screen_size = screen_size
|
self.screen_size = screen_size
|
||||||
|
|||||||
@@ -7,13 +7,14 @@ from bauh.api.abstract.view import MessageType
|
|||||||
from bauh.commons.system import new_subprocess
|
from bauh.commons.system import new_subprocess
|
||||||
from bauh.view.qt.dialog import show_message
|
from bauh.view.qt.dialog import show_message
|
||||||
from bauh.view.util import resource
|
from bauh.view.util import resource
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
def is_root():
|
def is_root():
|
||||||
return os.getuid() == 0
|
return os.getuid() == 0
|
||||||
|
|
||||||
|
|
||||||
def ask_root_password(i18n: dict):
|
def ask_root_password(i18n: I18n):
|
||||||
diag = QInputDialog()
|
diag = QInputDialog()
|
||||||
diag.setStyleSheet("""QLineEdit { border-radius: 5px; font-size: 16px }""")
|
diag.setStyleSheet("""QLineEdit { border-radius: 5px; font-size: 16px }""")
|
||||||
diag.setInputMode(QInputDialog.TextInput)
|
diag.setInputMode(QInputDialog.TextInput)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from bauh.view.qt import qt_utils
|
|||||||
from bauh.view.qt.components import new_spacer
|
from bauh.view.qt.components import new_spacer
|
||||||
from bauh.view.qt.thread import AnimateProgress
|
from bauh.view.qt.thread import AnimateProgress
|
||||||
from bauh.view.qt.view_model import PackageView
|
from bauh.view.qt.view_model import PackageView
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
class ScreenshotsDialog(QDialog):
|
class ScreenshotsDialog(QDialog):
|
||||||
@@ -19,7 +20,7 @@ class ScreenshotsDialog(QDialog):
|
|||||||
MAX_HEIGHT = 600
|
MAX_HEIGHT = 600
|
||||||
MAX_WIDTH = 800
|
MAX_WIDTH = 800
|
||||||
|
|
||||||
def __init__(self, pkg: PackageView, http_client: HttpClient, icon_cache: MemoryCache, i18n: dict, screenshots: List[QPixmap], logger: logging.Logger):
|
def __init__(self, pkg: PackageView, http_client: HttpClient, icon_cache: MemoryCache, i18n: I18n, screenshots: List[QPixmap], logger: logging.Logger):
|
||||||
super(ScreenshotsDialog, self).__init__()
|
super(ScreenshotsDialog, self).__init__()
|
||||||
self.setWindowTitle(str(pkg))
|
self.setWindowTitle(str(pkg))
|
||||||
self.screenshots = screenshots
|
self.screenshots = screenshots
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ from bauh.commons.html import bold
|
|||||||
from bauh.view.core import config
|
from bauh.view.core import config
|
||||||
from bauh.view.util import util
|
from bauh.view.util import util
|
||||||
from bauh.view.qt import dialog
|
from bauh.view.qt import dialog
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
class StylesComboBox(QComboBox):
|
class StylesComboBox(QComboBox):
|
||||||
|
|
||||||
def __init__(self, parent: QWidget, i18n: dict, show_panel_after_restart: bool):
|
def __init__(self, parent: QWidget, i18n: I18n, show_panel_after_restart: bool):
|
||||||
super(StylesComboBox, self).__init__(parent=parent)
|
super(StylesComboBox, self).__init__(parent=parent)
|
||||||
self.app = QApplication.instance()
|
self.app = QApplication.instance()
|
||||||
self.styles = []
|
self.styles = []
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ from bauh.api.abstract.model import PackageUpdate
|
|||||||
from bauh.view.util import util, resource
|
from bauh.view.util import util, resource
|
||||||
from bauh.view.qt.about import AboutDialog
|
from bauh.view.qt.about import AboutDialog
|
||||||
from bauh.view.qt.window import ManageWindow
|
from bauh.view.qt.window import ManageWindow
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
|
|
||||||
class UpdateCheck(QThread):
|
class UpdateCheck(QThread):
|
||||||
@@ -35,7 +36,7 @@ class UpdateCheck(QThread):
|
|||||||
|
|
||||||
class TrayIcon(QSystemTrayIcon):
|
class TrayIcon(QSystemTrayIcon):
|
||||||
|
|
||||||
def __init__(self, i18n: dict, manager: SoftwareManager, manage_window: ManageWindow, check_interval: int = 60, update_notification: bool = True):
|
def __init__(self, i18n: I18n, manager: SoftwareManager, manage_window: ManageWindow, check_interval: int = 60, update_notification: bool = True):
|
||||||
super(TrayIcon, self).__init__()
|
super(TrayIcon, self).__init__()
|
||||||
self.i18n = i18n
|
self.i18n = i18n
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ from bauh.api.abstract.handler import ProcessWatcher
|
|||||||
from bauh.api.abstract.model import PackageStatus, SoftwarePackage, PackageAction
|
from bauh.api.abstract.model import PackageStatus, SoftwarePackage, PackageAction
|
||||||
from bauh.api.abstract.view import InputViewComponent, MessageType
|
from bauh.api.abstract.view import InputViewComponent, MessageType
|
||||||
from bauh.api.exception import NoInternetException
|
from bauh.api.exception import NoInternetException
|
||||||
from bauh.api.http import HttpClient
|
|
||||||
from bauh.view.qt import commons
|
from bauh.view.qt import commons
|
||||||
from bauh.view.qt.view_model import PackageView
|
from bauh.view.qt.view_model import PackageView
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
RE_VERSION_IN_NAME = re.compile(r'\s+version\s+[\w\.]+\s*$')
|
RE_VERSION_IN_NAME = re.compile(r'\s+version\s+[\w\.]+\s*$')
|
||||||
|
|
||||||
@@ -76,12 +76,12 @@ class AsyncAction(QThread, ProcessWatcher):
|
|||||||
|
|
||||||
class UpdateSelectedApps(AsyncAction):
|
class UpdateSelectedApps(AsyncAction):
|
||||||
|
|
||||||
def __init__(self, manager: SoftwareManager, locale_keys: dict, apps_to_update: List[PackageView] = None):
|
def __init__(self, manager: SoftwareManager, i18n: I18n, apps_to_update: List[PackageView] = None):
|
||||||
super(UpdateSelectedApps, self).__init__()
|
super(UpdateSelectedApps, self).__init__()
|
||||||
self.apps_to_update = apps_to_update
|
self.apps_to_update = apps_to_update
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.root_password = None
|
self.root_password = None
|
||||||
self.locale_keys = locale_keys
|
self.i18n = i18n
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ class UpdateSelectedApps(AsyncAction):
|
|||||||
|
|
||||||
name = app.model.name if not RE_VERSION_IN_NAME.findall(app.model.name) else app.model.name.split('version')[0].strip()
|
name = app.model.name if not RE_VERSION_IN_NAME.findall(app.model.name) else app.model.name.split('version')[0].strip()
|
||||||
|
|
||||||
self.change_status('{} {} {}...'.format(self.locale_keys['manage_window.status.upgrading'], name, app.model.version))
|
self.change_status('{} {} {}...'.format(self.i18n['manage_window.status.upgrading'], name, app.model.version))
|
||||||
success = bool(self.manager.update(app.model, self.root_password, self))
|
success = bool(self.manager.update(app.model, self.root_password, self))
|
||||||
self.change_substatus('')
|
self.change_substatus('')
|
||||||
|
|
||||||
@@ -168,11 +168,11 @@ class UninstallApp(AsyncAction):
|
|||||||
|
|
||||||
class DowngradeApp(AsyncAction):
|
class DowngradeApp(AsyncAction):
|
||||||
|
|
||||||
def __init__(self, manager: SoftwareManager, locale_keys: dict, app: PackageView = None):
|
def __init__(self, manager: SoftwareManager, i18n: I18n, app: PackageView = None):
|
||||||
super(DowngradeApp, self).__init__()
|
super(DowngradeApp, self).__init__()
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.app = app
|
self.app = app
|
||||||
self.locale_keys = locale_keys
|
self.i18n = i18n
|
||||||
self.root_password = None
|
self.root_password = None
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -182,7 +182,7 @@ class DowngradeApp(AsyncAction):
|
|||||||
success = self.manager.downgrade(self.app.model, self.root_password, self)
|
success = self.manager.downgrade(self.app.model, self.root_password, self)
|
||||||
except (requests.exceptions.ConnectionError, NoInternetException) as e:
|
except (requests.exceptions.ConnectionError, NoInternetException) as e:
|
||||||
success = False
|
success = False
|
||||||
self.print(self.locale_keys['internet.required'])
|
self.print(self.i18n['internet.required'])
|
||||||
finally:
|
finally:
|
||||||
self.notify_finished({'app': self.app, 'success': success})
|
self.notify_finished({'app': self.app, 'success': success})
|
||||||
self.app = None
|
self.app = None
|
||||||
@@ -206,18 +206,18 @@ class GetAppInfo(AsyncAction):
|
|||||||
|
|
||||||
class GetAppHistory(AsyncAction):
|
class GetAppHistory(AsyncAction):
|
||||||
|
|
||||||
def __init__(self, manager: SoftwareManager, locale_keys: dict, app: PackageView = None):
|
def __init__(self, manager: SoftwareManager, i18n: I18n, app: PackageView = None):
|
||||||
super(GetAppHistory, self).__init__()
|
super(GetAppHistory, self).__init__()
|
||||||
self.app = app
|
self.app = app
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.locale_keys = locale_keys
|
self.i18n = i18n
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if self.app:
|
if self.app:
|
||||||
try:
|
try:
|
||||||
self.notify_finished({'history': self.manager.get_history(self.app.model)})
|
self.notify_finished({'history': self.manager.get_history(self.app.model)})
|
||||||
except (requests.exceptions.ConnectionError, NoInternetException) as e:
|
except (requests.exceptions.ConnectionError, NoInternetException) as e:
|
||||||
self.notify_finished({'error': self.locale_keys['internet.required']})
|
self.notify_finished({'error': self.i18n['internet.required']})
|
||||||
finally:
|
finally:
|
||||||
self.app = None
|
self.app = None
|
||||||
|
|
||||||
@@ -246,13 +246,13 @@ class SearchPackages(AsyncAction):
|
|||||||
|
|
||||||
class InstallPackage(AsyncAction):
|
class InstallPackage(AsyncAction):
|
||||||
|
|
||||||
def __init__(self, manager: SoftwareManager, disk_cache: bool, icon_cache: MemoryCache, locale_keys: dict, pkg: PackageView = None):
|
def __init__(self, manager: SoftwareManager, disk_cache: bool, icon_cache: MemoryCache, i18n: I18n, pkg: PackageView = None):
|
||||||
super(InstallPackage, self).__init__()
|
super(InstallPackage, self).__init__()
|
||||||
self.pkg = pkg
|
self.pkg = pkg
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.icon_cache = icon_cache
|
self.icon_cache = icon_cache
|
||||||
self.disk_cache = disk_cache
|
self.disk_cache = disk_cache
|
||||||
self.locale_keys = locale_keys
|
self.i18n = i18n
|
||||||
self.root_password = None
|
self.root_password = None
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -272,7 +272,7 @@ class InstallPackage(AsyncAction):
|
|||||||
only_icon=False)
|
only_icon=False)
|
||||||
except (requests.exceptions.ConnectionError, NoInternetException):
|
except (requests.exceptions.ConnectionError, NoInternetException):
|
||||||
success = False
|
success = False
|
||||||
self.print(self.locale_keys['internet.required'])
|
self.print(self.i18n['internet.required'])
|
||||||
finally:
|
finally:
|
||||||
self.signal_finished.emit({'success': success, 'pkg': self.pkg})
|
self.signal_finished.emit({'success': success, 'pkg': self.pkg})
|
||||||
self.pkg = None
|
self.pkg = None
|
||||||
@@ -403,9 +403,9 @@ class ListWarnings(QThread):
|
|||||||
|
|
||||||
signal_warnings = pyqtSignal(list)
|
signal_warnings = pyqtSignal(list)
|
||||||
|
|
||||||
def __init__(self, man: SoftwareManager, locale_keys: dict):
|
def __init__(self, man: SoftwareManager, i18n: I18n):
|
||||||
super(QThread, self).__init__()
|
super(QThread, self).__init__()
|
||||||
self.locale_keys = locale_keys
|
self.i18n = i18n
|
||||||
self.man = man
|
self.man = man
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -464,12 +464,13 @@ class ApplyFilters(AsyncAction):
|
|||||||
|
|
||||||
class CustomAction(AsyncAction):
|
class CustomAction(AsyncAction):
|
||||||
|
|
||||||
def __init__(self, manager: SoftwareManager, custom_action: PackageAction = None, pkg: PackageView = None, root_password: str = None):
|
def __init__(self, manager: SoftwareManager, i18n: I18n, custom_action: PackageAction = None, pkg: PackageView = None, root_password: str = None):
|
||||||
super(CustomAction, self).__init__()
|
super(CustomAction, self).__init__()
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.pkg = pkg
|
self.pkg = pkg
|
||||||
self.custom_action = custom_action
|
self.custom_action = custom_action
|
||||||
self.root_password = root_password
|
self.root_password = root_password
|
||||||
|
self.i18n = i18n
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
success = True
|
success = True
|
||||||
@@ -481,7 +482,7 @@ class CustomAction(AsyncAction):
|
|||||||
watcher=self)
|
watcher=self)
|
||||||
except (requests.exceptions.ConnectionError, NoInternetException):
|
except (requests.exceptions.ConnectionError, NoInternetException):
|
||||||
success = False
|
success = False
|
||||||
self.signal_output.emit(self.locale_keys['internet.required'])
|
self.signal_output.emit(self.i18n['internet.required'])
|
||||||
|
|
||||||
self.notify_finished({'success': success, 'pkg': self.pkg})
|
self.notify_finished({'success': success, 'pkg': self.pkg})
|
||||||
self.pkg = None
|
self.pkg = None
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ from bauh.view.qt.thread import UpdateSelectedApps, RefreshApps, UninstallApp, D
|
|||||||
from bauh.view.qt.view_model import PackageView
|
from bauh.view.qt.view_model import PackageView
|
||||||
from bauh.view.qt.view_utils import load_icon
|
from bauh.view.qt.view_utils import load_icon
|
||||||
from bauh.view.util import util, resource
|
from bauh.view.util import util, resource
|
||||||
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
DARK_ORANGE = '#FF4500'
|
DARK_ORANGE = '#FF4500'
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ class ManageWindow(QWidget):
|
|||||||
signal_user_res = pyqtSignal(bool)
|
signal_user_res = pyqtSignal(bool)
|
||||||
signal_table_update = pyqtSignal()
|
signal_table_update = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, i18n: dict, icon_cache: MemoryCache, manager: SoftwareManager, disk_cache: bool,
|
def __init__(self, i18n: I18n, icon_cache: MemoryCache, manager: SoftwareManager, disk_cache: bool,
|
||||||
download_icons: bool, screen_size, suggestions: bool, display_limit: int, config: Configuration,
|
download_icons: bool, screen_size, suggestions: bool, display_limit: int, config: Configuration,
|
||||||
context: ApplicationContext, notifications: bool, http_client: HttpClient, logger: logging.Logger,
|
context: ApplicationContext, notifications: bool, http_client: HttpClient, logger: logging.Logger,
|
||||||
tray_icon=None):
|
tray_icon=None):
|
||||||
@@ -231,7 +232,7 @@ class ManageWindow(QWidget):
|
|||||||
self.thread_downgrade = self._bind_async_action(DowngradeApp(self.manager, self.i18n), finished_call=self._finish_downgrade)
|
self.thread_downgrade = self._bind_async_action(DowngradeApp(self.manager, self.i18n), finished_call=self._finish_downgrade)
|
||||||
self.thread_suggestions = self._bind_async_action(FindSuggestions(man=self.manager), finished_call=self._finish_search, only_finished=True)
|
self.thread_suggestions = self._bind_async_action(FindSuggestions(man=self.manager), finished_call=self._finish_search, only_finished=True)
|
||||||
self.thread_run_app = self._bind_async_action(LaunchApp(self.manager), finished_call=self._finish_run_app, only_finished=False)
|
self.thread_run_app = self._bind_async_action(LaunchApp(self.manager), finished_call=self._finish_run_app, only_finished=False)
|
||||||
self.thread_custom_action = self._bind_async_action(CustomAction(manager=self.manager), finished_call=self._finish_custom_action)
|
self.thread_custom_action = self._bind_async_action(CustomAction(manager=self.manager, i18n=self.i18n), finished_call=self._finish_custom_action)
|
||||||
self.thread_screenshots = self._bind_async_action(GetScreenshots(self.manager), finished_call=self._finish_get_screenshots)
|
self.thread_screenshots = self._bind_async_action(GetScreenshots(self.manager), finished_call=self._finish_get_screenshots)
|
||||||
|
|
||||||
self.thread_apply_filters = ApplyFilters()
|
self.thread_apply_filters = ApplyFilters()
|
||||||
@@ -239,7 +240,7 @@ class ManageWindow(QWidget):
|
|||||||
self.thread_apply_filters.signal_table.connect(self._update_table_and_upgrades)
|
self.thread_apply_filters.signal_table.connect(self._update_table_and_upgrades)
|
||||||
self.signal_table_update.connect(self.thread_apply_filters.stop_waiting)
|
self.signal_table_update.connect(self.thread_apply_filters.stop_waiting)
|
||||||
|
|
||||||
self.thread_install = InstallPackage(manager=self.manager, disk_cache=self.disk_cache, icon_cache=self.icon_cache, locale_keys=self.i18n)
|
self.thread_install = InstallPackage(manager=self.manager, disk_cache=self.disk_cache, icon_cache=self.icon_cache, i18n=self.i18n)
|
||||||
self._bind_async_action(self.thread_install, finished_call=self._finish_install)
|
self._bind_async_action(self.thread_install, finished_call=self._finish_install)
|
||||||
|
|
||||||
self.thread_animate_progress = AnimateProgress()
|
self.thread_animate_progress = AnimateProgress()
|
||||||
@@ -289,7 +290,7 @@ class ManageWindow(QWidget):
|
|||||||
self.dialog_about = None
|
self.dialog_about = None
|
||||||
self.first_refresh = suggestions
|
self.first_refresh = suggestions
|
||||||
|
|
||||||
self.thread_warnings = ListWarnings(man=manager, locale_keys=i18n)
|
self.thread_warnings = ListWarnings(man=manager, i18n=i18n)
|
||||||
self.thread_warnings.signal_warnings.connect(self._show_warnings)
|
self.thread_warnings.signal_warnings.connect(self._show_warnings)
|
||||||
|
|
||||||
def set_tray_icon(self, tray_icon):
|
def set_tray_icon(self, tray_icon):
|
||||||
@@ -349,7 +350,7 @@ class ManageWindow(QWidget):
|
|||||||
self.thread_animate_progress.pause()
|
self.thread_animate_progress.pause()
|
||||||
diag = ConfirmationDialog(title=msg['title'],
|
diag = ConfirmationDialog(title=msg['title'],
|
||||||
body=msg['body'],
|
body=msg['body'],
|
||||||
locale_keys=self.i18n,
|
i18n=self.i18n,
|
||||||
components=msg['components'],
|
components=msg['components'],
|
||||||
confirmation_label=msg['confirmation_label'],
|
confirmation_label=msg['confirmation_label'],
|
||||||
deny_label=msg['deny_label'])
|
deny_label=msg['deny_label'])
|
||||||
@@ -792,7 +793,7 @@ class ManageWindow(QWidget):
|
|||||||
|
|
||||||
if to_update and dialog.ask_confirmation(title=self.i18n['manage_window.upgrade_all.popup.title'],
|
if to_update and dialog.ask_confirmation(title=self.i18n['manage_window.upgrade_all.popup.title'],
|
||||||
body=self.i18n['manage_window.upgrade_all.popup.body'],
|
body=self.i18n['manage_window.upgrade_all.popup.body'],
|
||||||
locale_keys=self.i18n,
|
i18n=self.i18n,
|
||||||
widgets=[UpdateToggleButton(None, self, self.i18n, clickable=False)]):
|
widgets=[UpdateToggleButton(None, self, self.i18n, clickable=False)]):
|
||||||
pwd = None
|
pwd = None
|
||||||
|
|
||||||
|
|||||||
67
bauh/view/util/translation.py
Normal file
67
bauh/view/util/translation.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import glob
|
||||||
|
import locale
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
from bauh.view.util import resource
|
||||||
|
|
||||||
|
|
||||||
|
class I18n(dict):
|
||||||
|
|
||||||
|
def __init__(self, current_locale: dict, default_locale: dict):
|
||||||
|
super(I18n, self).__init__()
|
||||||
|
self.current = current_locale
|
||||||
|
self.default = default_locale
|
||||||
|
|
||||||
|
def __getitem__(self, item):
|
||||||
|
try:
|
||||||
|
return self.current.__getitem__(item)
|
||||||
|
except KeyError:
|
||||||
|
if self.default:
|
||||||
|
return self.default.__getitem__(item)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
res = self.current.get(args[0])
|
||||||
|
|
||||||
|
if res is None:
|
||||||
|
if self.default:
|
||||||
|
return self.default.get(*args, **kwargs)
|
||||||
|
else:
|
||||||
|
return self.current.get(*args, **kwargs)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def get_locale_keys(key: str = None, locale_dir: str = resource.get_path('locale')) -> Tuple[str, dict]:
|
||||||
|
|
||||||
|
locale_path = None
|
||||||
|
|
||||||
|
if key is None:
|
||||||
|
current_locale = locale.getdefaultlocale()
|
||||||
|
else:
|
||||||
|
current_locale = [key.strip().lower()]
|
||||||
|
|
||||||
|
if current_locale:
|
||||||
|
current_locale = current_locale[0]
|
||||||
|
|
||||||
|
for locale_file in glob.glob(locale_dir + '/*'):
|
||||||
|
name = locale_file.split('/')[-1]
|
||||||
|
|
||||||
|
if current_locale == name or current_locale.startswith(name + '_'):
|
||||||
|
locale_path = locale_file
|
||||||
|
break
|
||||||
|
|
||||||
|
if not locale_path:
|
||||||
|
return key, {}
|
||||||
|
|
||||||
|
with open(locale_path, 'r') as f:
|
||||||
|
locale_keys = f.readlines()
|
||||||
|
|
||||||
|
locale_obj = {}
|
||||||
|
for line in locale_keys:
|
||||||
|
if line:
|
||||||
|
keyval = line.strip().split('=')
|
||||||
|
locale_obj[keyval[0].strip()] = keyval[1].strip()
|
||||||
|
|
||||||
|
return locale_path.split('/')[-1], locale_obj
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
import glob
|
|
||||||
import locale
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication
|
from PyQt5.QtCore import QCoreApplication
|
||||||
|
|
||||||
@@ -12,40 +9,6 @@ from bauh.commons.system import run_cmd
|
|||||||
from bauh.view.util import resource
|
from bauh.view.util import resource
|
||||||
|
|
||||||
|
|
||||||
def get_locale_keys(key: str = None, locale_dir: str = resource.get_path('locale')) -> Tuple[str, dict]:
|
|
||||||
|
|
||||||
locale_path = None
|
|
||||||
|
|
||||||
if key is None:
|
|
||||||
current_locale = locale.getdefaultlocale()
|
|
||||||
else:
|
|
||||||
current_locale = [key.strip().lower()]
|
|
||||||
|
|
||||||
if current_locale:
|
|
||||||
current_locale = current_locale[0]
|
|
||||||
|
|
||||||
for locale_file in glob.glob(locale_dir + '/*'):
|
|
||||||
name = locale_file.split('/')[-1]
|
|
||||||
|
|
||||||
if current_locale == name or current_locale.startswith(name + '_'):
|
|
||||||
locale_path = locale_file
|
|
||||||
break
|
|
||||||
|
|
||||||
if not locale_path:
|
|
||||||
locale_path = resource.get_path('locale/en')
|
|
||||||
|
|
||||||
with open(locale_path, 'r') as f:
|
|
||||||
locale_keys = f.readlines()
|
|
||||||
|
|
||||||
locale_obj = {}
|
|
||||||
for line in locale_keys:
|
|
||||||
if line:
|
|
||||||
keyval = line.strip().split('=')
|
|
||||||
locale_obj[keyval[0].strip()] = keyval[1].strip()
|
|
||||||
|
|
||||||
return locale_path.split('/')[-1], locale_obj
|
|
||||||
|
|
||||||
|
|
||||||
def notify_user(msg: str, icon_path: str = resource.get_path('img/logo.svg')):
|
def notify_user(msg: str, icon_path: str = resource.get_path('img/logo.svg')):
|
||||||
os.system("notify-send -a {} {} '{}'".format(__app_name__, "-i {}".format(icon_path) if icon_path else '', msg))
|
os.system("notify-send -a {} {} '{}'".format(__app_name__, "-i {}".format(icon_path) if icon_path else '', msg))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user