[view] feature: adding a new 'verified' filter for the packages table

This commit is contained in:
Vinicius Moreira
2023-11-30 17:17:32 -03:00
parent 4c91973028
commit a4c24c8aa6
32 changed files with 254 additions and 38 deletions

View File

@@ -5,6 +5,9 @@ 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/).
## NEXT
### Features
- new **verified** filter for the management table
### Improvements
- Arch
- adding the AUR's URL on the package information dialog [#339](https://github.com/vinifmor/bauh/issues/339)
@@ -18,6 +21,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- the "Skip" button on the initialization panel is now enabled after 10 seconds [#310](https://github.com/vinifmor/bauh/issues/310)
- faster package icons download
- faster packages filtering (`type`, `category`, `name`, etc... up to **95% less time**)
- displaying a text warning before installing an unverified package (unverified = not verified by the system maintainers or a trustable source)
- at the moment the following packaging formats are considered completely **unverified**: AppImage, AUR, native Web application
- Snap supports both verified and unverified software
### Fixes
- AppImage

View File

@@ -288,3 +288,6 @@ class ArchPackage(SoftwarePackage):
@property
def orphan(self) -> bool:
return self.maintainer is None
def is_trustable(self) -> bool:
return self.repository and self.repository != "aur"

View File

@@ -314,4 +314,3 @@ gem.arch.info=Software packages available for distributions based on Arch Linux
gem.arch.label=Arch
gem.arch.type.arch_repo.label=Arch - Dipòsit
gem.arch.type.aur.label=Arch - AUR
gem.aur.install.warning=Els paquets AUR són mantinguts per una comunitat dusuaris independent. No hi ha cap garantia que funcionin o que no danyin el vostre sistema.

View File

@@ -314,4 +314,3 @@ gem.arch.info=Verfügbare Softwarepakete für Distributionen, die auf Arch Linux
gem.arch.label=Arch
gem.arch.type.arch_repo.label=Arch - Repository
gem.arch.type.aur.label=Arch - AUR
gem.aur.install.warning=AUR-Pakete werden von einer unabhängigen Benutzergemeinschaft gepflegt. Es gibt keine Garantie, dass sie funktionieren oder Ihr System nicht beschädigen.

View File

@@ -314,4 +314,3 @@ gem.arch.info=Software packages available for distributions based on Arch Linux
gem.arch.label=Arch
gem.arch.type.arch_repo.label=Arch - Repository
gem.arch.type.aur.label=Arch - AUR
gem.aur.install.warning=AUR packages are maintained by an independent user community. There is no warranty they will work or not harm your system.

View File

@@ -314,4 +314,3 @@ gem.arch.info=Paquetes de software disponibles para distribuciones basadas en Ar
gem.arch.label=Arch
gem.arch.type.arch_repo.label=Arch - Repositorio
gem.arch.type.aur.label=Arch - AUR
gem.aur.install.warning=Los paquetes AUR son mantenidos por una comunidad de usuarios independiente. No hay garantía de que funcionen o que no dañen su sistema.

View File

@@ -314,4 +314,3 @@ gem.arch.info=Paquets logiciels disponibles pour les distributions basées sur A
gem.arch.label=Arch
gem.arch.type.arch_repo.label=Arch - Dépôt
gem.arch.type.aur.label=Arch - AUR
gem.aur.install.warning=Les paquets AUR sont maintenus par une communauté indépendante. Il n'y a aucune garantie qu'ils fonctionneront et qu'ils n'endommageront pas votre système.

View File

@@ -314,4 +314,3 @@ gem.arch.info=Software packages available for distributions based on Arch Linux
gem.arch.label=Arch
gem.arch.type.arch_repo.label=Arch - Deposito
gem.arch.type.aur.label=Arch - AUR
gem.aur.install.warning=I pacchetti AUR sono gestiti da una comunità di utenti indipendenti. Non esiste alcuna garanzia che funzionino o non danneggino il sistema.

View File

@@ -313,4 +313,3 @@ gem.arch.info=Pacotes de software disponíveis para distribuições baseadas em
gem.arch.label=Arch
gem.arch.type.arch_repo.label=Arch - Repositório
gem.arch.type.aur.label=Arch - AUR
gem.aur.install.warning=Pacotes do AUR são mantidos por uma comunidade de usuários independente. Não há garantia que funcionarão ou que não prejudicarão o seus sistema.

View File

@@ -314,4 +314,3 @@ gem.arch.info=Пакеты программного обеспечения, до
gem.arch.label=Arch
gem.arch.type.arch_repo.label=Arch - Репозиторий
gem.arch.type.aur.label=Arch - AUR
gem.aur.install.warning=AUR-пакеты поддерживаются независимым сообществом пользователей. Нет никакой гарантии, что они будут работать или не навредят вашей системе.

View File

@@ -314,4 +314,3 @@ gem.arch.info=Arch Linux tabanlı dağıtımlar için mevcut yazılım paketleri
gem.arch.label=Arch
gem.arch.type.arch_repo.label=Arch - Depoları
gem.arch.type.aur.label=Arch - AUR
gem.aur.install.warning=AUR paketleri bağımsız bir Arch Kullanıcı Topluluğu tarafından sağlanır. Çalışacaklarının veya sisteminize zarar vermeyeceklerinin garantisi yoktur.

View File

@@ -132,6 +132,9 @@ class DebianPackage(SoftwarePackage):
def supports_ignored_updates(self) -> bool:
return True
def is_trustable(self) -> bool:
return True
def __eq__(self, other):
if isinstance(other, DebianPackage):
return self.name == other.name

View File

@@ -159,6 +159,9 @@ class FlatpakApplication(SoftwarePackage):
if self.id and self.arch and self.branch:
self.ref = f'{self.id}/{self.arch}/{self.branch}'
def is_trustable(self) -> bool:
return True
def __repr__(self) -> str:
return f'Flatpak (id={self.id}, branch={self.branch}, origin={self.origin}, installation={self.installation},' \
f' partial={self.partial}, update_component={self.update_component})'

View File

@@ -11,6 +11,7 @@ from PyQt5.QtWidgets import QTableWidget, QTableView, QMenu, QToolButton, QWidge
from bauh.api.abstract.cache import MemoryCache
from bauh.api.abstract.model import PackageStatus, CustomSoftwareAction
from bauh.api.abstract.view import MessageType
from bauh.commons.html import strip_html, bold
from bauh.view.qt.components import IconButton, QCustomMenuAction, QCustomToolbar
from bauh.view.qt.dialog import ConfirmationDialog
@@ -206,15 +207,17 @@ class PackagesTable(QTableWidget):
body = self.i18n['manage_window.apps_table.row.actions.install.popup.body'].format(self._bold(str(pkgv)))
warning = self.i18n.get('gem.{}.install.warning'.format(pkgv.model.get_type().lower()))
if warning:
confirm_icon = MessageType.INFO
if not pkgv.model.is_trustable():
warning = self.i18n["action.install.unverified.warning"]
confirm_icon = MessageType.WARNING
body += '<br/><br/> {}'.format(
'<br/>'.join(('{}.'.format(phrase) for phrase in warning.split('.') if phrase)))
if ConfirmationDialog(title=self.i18n['manage_window.apps_table.row.actions.install.popup.title'],
body=self._parag(body),
i18n=self.i18n).ask():
i18n=self.i18n,
confirmation_icon_type=confirm_icon).ask():
self.window.install(pkgv)
def _update_pkg_icon(self, url_: str, content: Optional[bytes], table_idx: int):

View File

@@ -15,13 +15,14 @@ class PackageFilters(NamedTuple):
only_apps: bool
only_installed: bool
only_updates: bool
only_verified: bool
search: Optional[str] # initial search term
type: str
@property
def anything(self) -> bool:
return not self.only_installed and not self.only_updates and not self.only_apps \
and not self.name and self.type == "any" and self.category == "any"
and not self.only_verified and not self.name and self.type == "any" and self.category == "any"
def new_pkgs_info() -> Dict[str, Any]:
@@ -35,6 +36,7 @@ def new_pkgs_info() -> Dict[str, Any]:
'not_installed': 0,
'installed': 0,
'categories': set(),
'verified': 0,
'pkgs': []} # total packages
@@ -46,6 +48,9 @@ def update_info(pkgv: PackageView, pkgs_info: Dict[str, Any]):
else:
pkgs_info['napps_count'] += 1
if pkgv.model.is_trustable():
pkgs_info['verified'] += 1
if pkgv.model.update and not pkgv.model.is_update_ignored():
if pkgv.model.is_application():
pkgs_info['app_updates'] += 1
@@ -94,6 +99,9 @@ def is_package_hidden(pkg: PackageView, filters: PackageFilters) -> bool:
if not hidden and filters.only_updates:
hidden = not pkg.model.update or pkg.model.is_update_ignored()
if not hidden and filters.only_verified:
hidden = not pkg.model.is_trustable()
if not hidden and filters.type is not None and filters.type != "any":
hidden = pkg.model.get_type() != filters.type

View File

@@ -35,7 +35,8 @@ class ConfirmationDialog(QDialog):
widgets: Optional[List[QWidget]] = None, confirmation_button: bool = True, deny_button: bool = True,
window_cancel: bool = False, confirmation_label: Optional[str] = None, deny_label: Optional[str] = None,
confirmation_icon: bool = True, min_width: Optional[int] = None,
min_height: Optional[int] = None, max_width: Optional[int] = None):
min_height: Optional[int] = None, max_width: Optional[int] = None,
confirmation_icon_type: MessageType = MessageType.INFO):
super(ConfirmationDialog, self).__init__()
if not window_cancel:
@@ -79,6 +80,7 @@ class ConfirmationDialog(QDialog):
if confirmation_icon:
lb_icon = QLabel()
lb_icon.setObjectName("confirm_dialog_icon")
lb_icon.setProperty("type", confirmation_icon_type.name.lower())
container_body.layout().addWidget(lb_icon)
if body:

View File

@@ -17,15 +17,19 @@ def new_type_index() -> Dict[str, Dict[str, Dict[str, List[PackageView]]]]:
return defaultdict(new_category_idx)
def new_update_index() -> Dict[int, Dict[str, Dict[str, Dict[str, List[PackageView]]]]]:
def new_verified_index() -> Dict[int, Dict[str, Dict[str, Dict[str, List[PackageView]]]]]:
return defaultdict(new_type_index)
def new_app_index() -> Dict[int, Dict[int, Dict[str, Dict[str, Dict[str, List[PackageView]]]]]]:
def new_update_index() -> Dict[int, Dict[int, Dict[str, Dict[str, Dict[str, List[PackageView]]]]]]:
return defaultdict(new_verified_index)
def new_app_index() -> Dict[int, Dict[int, Dict[int, Dict[str, Dict[str, Dict[str, List[PackageView]]]]]]]:
return defaultdict(new_update_index)
def new_package_index() -> Dict[int, Dict[int, Dict[int, Dict[str, Dict[str, Dict[str, List[PackageView]]]]]]]:
def new_package_index() -> Dict[int, Dict[int, Dict[int, Dict[int, Dict[str, Dict[str, Dict[str, List[PackageView]]]]]]]]:
return defaultdict(new_app_index)
@@ -42,6 +46,9 @@ def add_to_index(pkgv: PackageView, index: dict) -> None:
else:
update_lvl = app_lvl[0]
# verified keys: (1) verified | (0) unverified
verified_lvl = update_lvl[1 if pkgv.model.is_trustable() else 0]
norm_name = pkgv.name.strip().lower()
starts_with_chars = tuple(norm_name[0:i] for i in range(1, len(norm_name) + 1))
@@ -49,13 +56,13 @@ def add_to_index(pkgv: PackageView, index: dict) -> None:
category = cat.lower().strip()
# any type > specific category > any character (None)
update_lvl["any"][category][None].append(pkgv)
verified_lvl["any"][category][None].append(pkgv)
# any type > specific category > characters (start
for chars in starts_with_chars:
update_lvl["any"][category][chars].append(pkgv)
verified_lvl["any"][category][chars].append(pkgv)
type_lvl = update_lvl[pkgv.model.get_type()]
type_lvl = verified_lvl[pkgv.model.get_type()]
# specific type > specific category > any character (None)
type_lvl[category][None].append(pkgv)
@@ -65,7 +72,7 @@ def add_to_index(pkgv: PackageView, index: dict) -> None:
type_lvl[category][chars].append(pkgv)
def generate_queries(filters: PackageFilters) -> Generator[Tuple[Optional[Union[int, str]]], None, None]:
def generate_queries(filters: PackageFilters) -> Generator[Tuple[Optional[Union[int, str]], ...], None, None]:
chars_query = None
if filters.name:
@@ -74,11 +81,13 @@ def generate_queries(filters: PackageFilters) -> Generator[Tuple[Optional[Union[
installed_queries = (1,) if filters.only_installed else (1, 0)
apps_queries = (1,) if filters.only_apps else (1, 0)
updates_queries = (1,) if filters.only_updates else (1, 0)
verified_queries = (1,) if filters.only_verified else (1, 0)
for installed in installed_queries:
for app in apps_queries:
for update in updates_queries:
yield installed, app, update, filters.type, filters.category, chars_query
for verified in verified_queries:
yield installed, app, update, verified, filters.type, filters.category, chars_query
def query_packages(index: dict, filters: PackageFilters) -> Generator[PackageView, None, None]:
@@ -90,7 +99,7 @@ def query_packages(index: dict, filters: PackageFilters) -> Generator[PackageVie
yielded_pkgs = defaultdict(set)
for query in queries:
packages = index[query[0]][query[1]][query[2]][query[3]][query[4]][query[5]]
packages = index[query[0]][query[1]][query[2]][query[3]][query[4]][query[5]][query[6]]
for pkgv in packages:
yield pkgv
@@ -111,7 +120,7 @@ def query_packages(index: dict, filters: PackageFilters) -> Generator[PackageVie
if 0 < yield_limit <= yield_count:
break
packages = index[query[0]][query[1]][query[2]][query[3]][query[4]][None]
packages = index[query[0]][query[1]][query[2]][query[3]][query[4]][query[5]][None]
for pkgv in packages:
# checking if the package has already been yielded

View File

@@ -75,13 +75,14 @@ CHECK_INSTALLED = 6
CHECK_UPDATES = 7
CHECK_APPS = 8
COMBO_TYPES = 9
COMBO_CATEGORIES = 10
INP_NAME = 11
CHECK_DETAILS = 12
BT_SETTINGS = 13
BT_CUSTOM_ACTIONS = 14
BT_ABOUT = 15
BT_THEMES = 16
CHECK_VERIFIED = 10
COMBO_CATEGORIES = 11
INP_NAME = 12
CHECK_DETAILS = 13
BT_SETTINGS = 14
BT_CUSTOM_ACTIONS = 15
BT_ABOUT = 16
BT_THEMES = 17
# component groups ids
GROUP_FILTERS = 1
@@ -177,6 +178,16 @@ class ManageWindow(QWidget):
self.toolbar_filters.layout().addWidget(self.check_apps)
self.comp_manager.register_component(CHECK_APPS, self.check_apps)
self.check_verified = QCheckBox()
self.check_verified.setObjectName('check_verified')
self.check_verified.setCursor(QCursor(Qt.PointingHandCursor))
self.check_verified.setText(self.i18n['manage_window.checkbox.only_verified'])
self.check_verified.setChecked(False)
self.check_verified.stateChanged.connect(self._handle_filter_only_verified)
self.check_verified.sizePolicy().setRetainSizeWhenHidden(True)
self.toolbar_filters.layout().addWidget(self.check_verified)
self.comp_manager.register_component(CHECK_VERIFIED, self.check_verified)
self.any_type_filter = 'any'
self.cache_type_filter_icons = {}
self.combo_filter_type = QComboBox()
@@ -434,6 +445,7 @@ class ManageWindow(QWidget):
self.layout.addWidget(self.container_progress)
self.filter_only_apps = True
self.filter_only_verified = False
self.type_filter = self.any_type_filter
self.category_filter = self.any_category_filter
self.filter_updates = False
@@ -462,22 +474,23 @@ class ManageWindow(QWidget):
qt_utils.centralize(self)
def _register_groups(self):
common_filters = (CHECK_APPS, CHECK_UPDATES, COMBO_CATEGORIES, COMBO_TYPES, INP_NAME)
common_filters = (CHECK_APPS, CHECK_VERIFIED, CHECK_UPDATES, COMBO_CATEGORIES, COMBO_TYPES, INP_NAME)
self.comp_manager.register_group(GROUP_FILTERS, False, CHECK_INSTALLED, *common_filters)
self.comp_manager.register_group(GROUP_VIEW_SEARCH, False,
COMBO_CATEGORIES, COMBO_TYPES, INP_NAME, # filters
BT_INSTALLED, BT_SUGGESTIONS, CHECK_INSTALLED) # buttons
CHECK_INSTALLED, CHECK_VERIFIED, COMBO_CATEGORIES, COMBO_TYPES, INP_NAME,
BT_INSTALLED, BT_SUGGESTIONS)
self.comp_manager.register_group(GROUP_VIEW_INSTALLED, False,
BT_REFRESH, BT_UPGRADE, # buttons
*common_filters)
self.comp_manager.register_group(GROUP_UPPER_BAR, False,
CHECK_APPS, CHECK_UPDATES, CHECK_INSTALLED, COMBO_CATEGORIES, COMBO_TYPES, INP_NAME,
BT_INSTALLED, BT_SUGGESTIONS, BT_REFRESH, BT_UPGRADE)
CHECK_APPS, CHECK_VERIFIED, CHECK_UPDATES, CHECK_INSTALLED, COMBO_CATEGORIES,
COMBO_TYPES, INP_NAME, BT_INSTALLED, BT_SUGGESTIONS, BT_REFRESH, BT_UPGRADE)
self.comp_manager.register_group(GROUP_LOWER_BTS, False, BT_SUGGESTIONS, BT_THEMES, BT_CUSTOM_ACTIONS, BT_SETTINGS, BT_ABOUT)
self.comp_manager.register_group(GROUP_LOWER_BTS, False, BT_SUGGESTIONS, BT_THEMES, BT_CUSTOM_ACTIONS,
BT_SETTINGS, BT_ABOUT)
def update_custom_actions(self):
self.custom_actions = [a for a in self.manager.gen_custom_actions()]
@@ -653,6 +666,10 @@ class ManageWindow(QWidget):
self.filter_only_apps = status == 2
self.begin_apply_filters()
def _handle_filter_only_verified(self, status: int):
self.filter_only_verified = status == 2
self.begin_apply_filters()
def _handle_filter_only_installed(self, status: int):
self.filter_installed = status == 2
self.begin_apply_filters()
@@ -974,6 +991,7 @@ class ManageWindow(QWidget):
display_limit=0 if self.filter_updates else self.display_limit,
name=self.input_name.text().strip(),
only_apps=False if self.search_performed else self.filter_only_apps,
only_verified=self.filter_only_verified,
only_updates=False if ignore_updates else self.filter_updates,
only_installed=self.filter_installed,
search=self.searched_term,
@@ -1029,6 +1047,7 @@ class ManageWindow(QWidget):
self.check_apps.setCheckable(True)
self._change_checkbox(self.check_apps, True, 'filter_only_apps', trigger=False)
self._update_verified_filter(verified_available=pkgs_info['verified'] > 0, keep_state=keep_filters)
self.change_update_state(pkgs_info=pkgs_info, trigger_filters=False, keep_selected=keep_filters and bool(pkgs_info['pkgs_displayed']))
self._update_categories(pkgs_info['categories'], keep_selected=keep_filters and bool(pkgs_info['pkgs_displayed']))
self._update_type_filters(pkgs_info['available_types'], keep_selected=keep_filters and bool(pkgs_info['pkgs_displayed']))
@@ -1081,6 +1100,19 @@ class ManageWindow(QWidget):
else:
self.comp_manager.set_component_visible(CHECK_INSTALLED, has_installed)
def _update_verified_filter(self, keep_state: bool = True, verified_available: Optional[bool] = None):
if verified_available is not None:
has_verified = verified_available
else:
has_verified = False
if self.pkgs_available:
has_verified = next((True for p in self.pkgs_available if p.model.is_trustable()), False)
if not keep_state or not has_verified:
self._change_checkbox(self.check_verified, False, 'filter_only_verified', trigger=False)
self.comp_manager.set_component_visible(CHECK_VERIFIED, has_verified)
def _apply_filters(self, pkgs_info: dict, ignore_updates: bool):
pkgs_info['pkgs_displayed'] = []
filters = self._gen_filters(ignore_updates=ignore_updates)

View File

@@ -66,6 +66,7 @@ action.ignore_updates.success=Updates from {} will be ignored from now on
action.ignore_updates_reverse.fail=It was not possible to revert ignored updates from {}
action.ignore_updates_reverse.success=Updates from {} will be displayed again from now on
action.info.tooltip=Feu clic aquí per a veure informació sobre aquesta aplicació
action.install.unverified.warning=This app has not been verified by this system maintainers or a trusted source. Check its information before proceeding.
action.not_allowed=Action not allowed
action.request_reboot.title=System restart
action.reset=Restore
@@ -344,6 +345,7 @@ manage_window.bt_themes.tip=Click here to choose a theme
manage_window.bt_themes.option.invalid=Invalid
manage_window.checkbox.only_apps=Aplicacions
manage_window.checkbox.only_installed=Instal·lats
manage_window.checkbox.only_verified=Verificats
manage_window.checkbox.show_details=Mostra detalls
manage_window.columns.installed=Installed
manage_window.columns.latest_version=Versió més recent

View File

@@ -66,6 +66,7 @@ action.ignore_updates.success=Updates von {} werden an jetzt ignoriert
action.ignore_updates_reverse.fail=Es war nicht möglich, ignorierte Aktualisierungen von {} rückgängig zu machen
action.ignore_updates_reverse.success=Aktualisierungen von {} werden ab jetzt wieder angezeigt
action.info.tooltip=Klicken Sie hier, um Informationen über diese Anwendung anzuzeigen
action.install.unverified.warning=This app has not been verified by this system maintainers or a trusted source. Check its information before proceeding.
action.not_allowed=Aktion nicht erlaubt
action.request_reboot.title=System neustarten
action.reset=Wiederherstellen
@@ -346,6 +347,7 @@ manage_window.bt_themes.tip=Klicken Sie hier, um ein Thema auszuwählen
manage_window.bt_themes.option.invalid=Ungültig
manage_window.checkbox.only_apps=Anwendungen
manage_window.checkbox.only_installed=Installierte
manage_window.checkbox.only_verified=Verifiziert
manage_window.checkbox.show_details=Details anzeigen
manage_window.columns.installed=Installiert
manage_window.columns.latest_version=Neueste Version

View File

@@ -66,6 +66,7 @@ action.ignore_updates.success=Updates from {} will be ignored from now on
action.ignore_updates_reverse.fail=It was not possible to revert ignored updates from {}
action.ignore_updates_reverse.success=Updates from {} will be displayed again from now on
action.info.tooltip=Click here to see information about this application
action.install.unverified.warning=This app has not been verified by this system maintainers or a trusted source. Check its information before proceeding.
action.not_allowed=Action not allowed
action.request_reboot.title=System restart
action.reset=Restore
@@ -346,6 +347,7 @@ manage_window.bt_themes.tip=Click here to choose a theme
manage_window.bt_themes.option.invalid=Invalid
manage_window.checkbox.only_apps=Apps
manage_window.checkbox.only_installed=Installed
manage_window.checkbox.only_verified=Verified
manage_window.checkbox.show_details=Show details
manage_window.columns.installed=Installed
manage_window.columns.latest_version=Latest Version

View File

@@ -66,6 +66,7 @@ action.ignore_updates.success=Las actualizaciones de {} serán ignoradas de ahor
action.ignore_updates_reverse.fail=No fue posible revertir las actualizaciones ignoradas de {}
action.ignore_updates_reverse.success=Las actualizaciones de {} se mostrarán nuevamente a partir de ahora
action.info.tooltip=Pulse aquí para ver información sobre esta aplicación
action.install.unverified.warning=Este ap no ha sido verificado por los mantenedores de este sistema ni por una fuente confiable. Verifique su información antes de continuar.
action.not_allowed=Acción no permitida
action.request_reboot.title=Reinicio de sistema
action.reset=Restaurar
@@ -345,6 +346,7 @@ manage_window.bt_themes.tip=Pulse aquí para elegir un tema
manage_window.bt_themes.option.invalid=Inválido
manage_window.checkbox.only_apps=Aplicaciones
manage_window.checkbox.only_installed=Instalados
manage_window.checkbox.only_verified=Verificados
manage_window.checkbox.show_details=Mostrar detalles
manage_window.columns.installed=Instaladas
manage_window.columns.latest_version=Versión más reciente

View File

@@ -66,6 +66,7 @@ action.ignore_updates.success=Les mises à jour de {} seront désormais ignorée
action.ignore_updates_reverse.fail=Il était impossible d'annuler les mises à jour de {}
action.ignore_updates_reverse.success=Les mises à jour de {} sont désormais de retour
action.info.tooltip=Cliquez ici pour plus d'informations sur cette application
action.install.unverified.warning=This app has not been verified by this system maintainers or a trusted source. Check its information before proceeding.
action.not_allowed=Action non permise
action.request_reboot.title=Redémarrage du système
action.reset=Restaurer
@@ -342,6 +343,7 @@ manage_window.bt_themes.tip=Click here to choose a theme
manage_window.bt_themes.option.invalid=Invalid
manage_window.checkbox.only_apps=Apps
manage_window.checkbox.only_installed=Installées
manage_window.checkbox.only_verified=Vérifiés
manage_window.checkbox.show_details=Détails
manage_window.columns.installed=Installé
manage_window.columns.latest_version=Dernière Version

View File

@@ -66,6 +66,7 @@ action.ignore_updates.success=Updates from {} will be ignored from now on
action.ignore_updates_reverse.fail=It was not possible to revert ignored updates from {}
action.ignore_updates_reverse.success=Updates from {} will be displayed again from now on
action.info.tooltip=Clicca qui per vedere informazioni su questa applicazione
action.install.unverified.warning=This app has not been verified by this system maintainers or a trusted source. Check its information before proceeding.
action.not_allowed=Action not allowed
action.request_reboot.title=System restart
action.reset=Restore
@@ -345,6 +346,7 @@ manage_window.bt_themes.tip=Click here to choose a theme
manage_window.bt_themes.option.invalid=Invalid
manage_window.checkbox.only_apps=Apps
manage_window.checkbox.only_installed=Installate
manage_window.checkbox.only_verified=Verificati
manage_window.checkbox.show_details=Mostra dettagli
manage_window.columns.installed=Installed
manage_window.columns.latest_version=Ultima Versione

View File

@@ -66,6 +66,7 @@ action.ignore_updates.success=As atualizações de {} serão ignoradas a partir
action.ignore_updates_reverse.fail=Não foi possível reverter as atualizações ignoradas de {}
action.ignore_updates_reverse.success=As atualizações de {} serão exibidas novamente a partir de agora
action.info.tooltip=Clique aqui para ver informações sobre este aplicativo
action.install.unverified.warning=Este app não foi verificado pelos mantenedores desse sistema ou uma fonte confiável. Confira suas informações antes de prosseguir.
action.not_allowed=Ação não permitida
action.request_reboot.title=Reinicialização de sistema
action.reset=Restaurar
@@ -344,6 +345,7 @@ manage_window.bt_themes.tip=Clique aqui para escolher um tema
manage_window.bt_themes.option.invalid=Inválido
manage_window.checkbox.only_apps=Aplicativos
manage_window.checkbox.only_installed=Instalados
manage_window.checkbox.only_verified=Verificados
manage_window.checkbox.show_details=Mostrar detalhes
manage_window.columns.installed=Instalado
manage_window.columns.latest_version=Última Versão

View File

@@ -66,6 +66,7 @@ action.ignore_updates.success=Обновления от {} теперь буду
action.ignore_updates_reverse.fail=Не удалось вернуть игнорируемые обновления из {}
action.ignore_updates_reverse.success=Теперь обновления из {} будут отображаться снова
action.info.tooltip=Нажмите здесь, чтобы посмотреть информацию об этом приложении
action.install.unverified.warning=This app has not been verified by this system maintainers or a trusted source. Check its information before proceeding.
action.not_allowed=Действие не допускается
action.request_reboot.title=Перезапуск системы
action.reset=Восстановить
@@ -346,6 +347,7 @@ manage_window.bt_themes.tip=Нажмите здесь, чтобы выбрать
manage_window.bt_themes.option.invalid=Недопустимый
manage_window.checkbox.only_apps=Приложения
manage_window.checkbox.only_installed=Установленные
manage_window.checkbox.only_verified=Проверено
manage_window.checkbox.show_details=Показать детали
manage_window.columns.installed=Установленно
manage_window.columns.latest_version=Последняя версия

View File

@@ -66,6 +66,7 @@ action.ignore_updates.success=Updates from {} will be ignored from now on
action.ignore_updates_reverse.fail=It was not possible to revert ignored updates from {}
action.ignore_updates_reverse.success=Updates from {} will be displayed again from now on
action.info.tooltip=Uygulama bilgilerini görmek için buraya tıkla
action.install.unverified.warning=This app has not been verified by this system maintainers or a trusted source. Check its information before proceeding.
action.not_allowed=Eyleme izin verilmiyor
action.request_reboot.title=Sistemi yeniden başlat
action.reset=Restore
@@ -343,6 +344,7 @@ manage_window.bt_themes.tip=Tema seçmek için burayı tıkla
manage_window.bt_themes.option.invalid=Invalid
manage_window.checkbox.only_apps=Uygulamalar
manage_window.checkbox.only_installed=Yüklü
manage_window.checkbox.only_verified=Doğrulandı
manage_window.checkbox.show_details=Detayları göster
manage_window.columns.installed=Yüklü
manage_window.columns.latest_version=Son sürüm

View File

@@ -424,6 +424,10 @@ QLabel#confirm_dialog_icon {
qproperty-pixmap: url("@style_dir/img/question.svg");
}
QLabel#confirm_dialog_icon[type = "warning"] {
qproperty-pixmap: url("@style_dir/img/warning.svg");
}
FormQt IconButton#clean_field {
qproperty-icon: url("@style_dir/img/clean.svg");
}

View File

@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
id="Capa_1"
x="0px"
y="0px"
width="512"
height="512"
viewBox="0 0 512 512"
xml:space="preserve"
sodipodi:docname="warning.svg"
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata
id="metadata933"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs931">
</defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="739"
id="namedview929"
showgrid="false"
showborder="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="0.70710679"
inkscape:cx="354.26049"
inkscape:cy="276.47875"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Capa_1"
inkscape:document-rotation="0"
inkscape:pagecheckerboard="0" />
<g
id="g898"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g900"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g902"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g904"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g906"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g908"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g910"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g912"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g914"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g916"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g918"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g920"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g922"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g924"
transform="translate(239.5083,-10.347359)">
</g>
<g
id="g926"
transform="translate(239.5083,-10.347359)">
</g>
<ellipse
style="fill:none;stroke:#6e6e6e;stroke-width:36.1559"
id="path9773"
cx="270.94653"
cy="252.39122"
rx="213.86691"
ry="206.0806" /><path
id="path939"
style="fill:#be9117;fill-opacity:1;stroke:#be9117;stroke-width:1.88256;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 255.87109,2.9414062 A 252.84608,253.05907 0 0 0 3.1542969,256 252.84608,253.05907 0 0 0 256,509.05859 252.84608,253.05907 0 0 0 508.8457,256 252.84608,253.05907 0 0 0 256,2.9414062 a 252.84608,253.05907 0 0 0 -0.12891,0 z M 252.38672,122.42188 c 46.17094,0 91.62695,21.28145 91.62695,72.18554 0,46.94252 -53.74634,64.99664 -65.28906,81.95899 -8.66556,12.61739 -5.773,30.3457 -29.58203,30.3457 -15.50947,0 -23.08399,-12.62527 -23.08399,-24.17773 0,-42.98946 63.10938,-52.71862 63.10938,-88.11719 0,-19.48412 -12.95594,-31.03711 -34.61133,-31.03711 -46.17094,0 -28.14066,47.64062 -63.10937,47.64062 -12.6238,0 -23.46094,-7.58162 -23.46094,-22.01367 -0.009,-35.40709 40.38307,-66.78515 84.40039,-66.78515 z m -1.79688,207.92773 c 16.20751,0 29.58008,13.34102 29.58008,29.61328 0,16.27226 -13.34704,29.61523 -29.58008,29.61523 -16.23303,0 -29.58789,-13.32592 -29.58789,-29.61523 0,-16.26375 13.35486,-29.61328 29.58789,-29.61328 z" /></svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -417,6 +417,10 @@ QLabel#confirm_dialog_icon {
qproperty-pixmap: url("@style_dir/img/help.svg");
}
QLabel#confirm_dialog_icon[type = "warning"] {
qproperty-pixmap: url("@style_dir/img/warning.svg");
}
FormQt IconButton#clean_field {
qproperty-icon: url("@style_dir/img/clean.svg");
}

View File

@@ -83,6 +83,10 @@ QLabel#confirm_dialog_icon {
qproperty-pixmap: url("@style_dir/img/question.svg");
}
QLabel#confirm_dialog_icon[type = "warning"] {
qproperty-pixmap: url("@style_dir/img/warning.svg");
}
QPlainTextEdit[console = 'true'] {
background: @console.background.color;
color: @console.font.color;

View File

@@ -131,6 +131,10 @@ QLabel#confirm_dialog_icon {
qproperty-pixmap: url("@style_dir/img/question.svg");
}
QLabel#confirm_dialog_icon[type = "warning"] {
qproperty-pixmap: url("@style_dir/img/warning.svg");
}
QPlainTextEdit {
background: @texteditor.background.color;
color: @texteditor.font.color;