mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-08 17:54:15 +02:00
[view] feature: adding a new 'verified' filter for the packages table
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user