[view] improvement: sorting packages by closest match instead of considering installed first (search)

This commit is contained in:
Vinicius Moreira
2022-03-11 11:55:07 -03:00
parent b1a131950c
commit 508e9169c2
5 changed files with 46 additions and 71 deletions

View File

@@ -115,27 +115,6 @@ class GenericSoftwareManager(SoftwareManager):
type_=MessageType.ERROR)
return False
def _sort(self, apps: List[SoftwarePackage], word: str) -> List[SoftwarePackage]:
exact_name_matches, contains_name_matches, others = [], [], []
for app in apps:
lower_name = app.name.lower()
if word == lower_name:
exact_name_matches.append(app)
elif word in lower_name:
contains_name_matches.append(app)
else:
others.append(app)
res = []
for app_list in (exact_name_matches, contains_name_matches, others):
app_list.sort(key=lambda a: a.name.lower())
res.extend(app_list)
return res
def _can_work(self, man: SoftwareManager):
if self._available_cache is not None:
available = False
@@ -197,8 +176,8 @@ class GenericSoftwareManager(SoftwareManager):
disk_loader.stop_working()
disk_loader.join()
res.installed = self._sort(res.installed, norm_word)
res.new = self._sort(res.new, norm_word)
# res.installed = self._sort(res.installed, norm_word)
# res.new = self._sort(res.new, norm_word)
else:
raise NoInternetException()

View File

@@ -1,3 +1,6 @@
from typing import Iterable, List
from bauh.api.abstract.model import SoftwarePackage
from bauh.view.qt.view_model import PackageView
@@ -73,3 +76,33 @@ def is_package_hidden(pkg: PackageView, filters: dict) -> bool:
hidden = not filters['name'] in pkg.model.name.lower()
return hidden
def sort_packages(pkgs: Iterable[SoftwarePackage], word: str, limit: int = 0) -> List[SoftwarePackage]:
exact, starts_with, contains, others = [], [], [], []
for p in pkgs:
lower_name = p.name.lower()
if word == lower_name:
exact.append(p)
elif lower_name.startswith(word):
starts_with.append(p)
elif word in lower_name:
contains.append(p)
else:
others.append(p)
res = []
for app_list in (exact, starts_with, contains, others):
if app_list:
last = limit - len(res) if limit > 0 else None
if last is not None and last <= 0:
break
to_add = app_list[0:last]
to_add.sort(key=lambda a: a.name.lower())
res.extend(to_add)
return res

View File

@@ -5,7 +5,7 @@ import traceback
from datetime import datetime, timedelta
from io import StringIO
from pathlib import Path
from typing import List, Type, Set, Tuple, Optional
from typing import List, Type, Set, Tuple, Optional, Iterable
import requests
from PyQt5.QtCore import QThread, pyqtSignal, QObject
@@ -27,6 +27,7 @@ from bauh.commons.system import get_human_size_str, ProcessHandler, SimpleProces
from bauh.view.core import timeshift
from bauh.view.core.config import CoreConfigManager
from bauh.view.qt import commons
from bauh.view.qt.commons import sort_packages
from bauh.view.qt.view_model import PackageView, PackageViewStatus
from bauh.view.util.translation import I18n
@@ -704,8 +705,7 @@ class SearchPackages(AsyncAction):
if self.word:
try:
res = self.manager.search(words=self.word, disk_loader=None, limit=-1, is_url=False)
search_res['pkgs_found'].extend(res.installed)
search_res['pkgs_found'].extend(res.new)
search_res['pkgs_found'] = sort_packages((*(res.installed or ()), *(res.new or ())), self.word)
except NoInternetException:
search_res['error'] = 'internet.required'
finally:
@@ -951,48 +951,6 @@ class ApplyFilters(AsyncAction):
def stop_waiting(self):
self.wait_table_update = False
def _sort_by_word(self, word: str, pkgs: List[PackageView], limit: int) -> List[PackageView]:
norm_word = word.strip().lower()
exact_installed, exact_not_installed = [], []
starts_installed, starts_not_installed = [], []
contains_installed, contains_not_installed = [], []
for p in pkgs:
lower_name = p.model.name.lower()
if norm_word == lower_name:
if p.model.installed:
exact_installed.append(p)
else:
exact_not_installed.append(p)
elif lower_name.startswith(norm_word):
if p.model.installed:
starts_installed.append(p)
else:
starts_not_installed.append(p)
else:
if p.model.installed:
contains_installed.append(p)
else:
contains_not_installed.append(p)
res = []
for matches in (exact_installed, exact_not_installed,
starts_installed, starts_not_installed,
contains_installed, contains_not_installed):
if matches:
matches.sort(key=lambda p: p.model.name.lower())
if limit:
res.extend(matches[0:limit - len(res)])
if len(res) == limit:
break
else:
res.extend(matches)
return res
def run(self):
if self.pkgs:
pkgs_info = commons.new_pkgs_info()
@@ -1004,9 +962,9 @@ class ApplyFilters(AsyncAction):
commons.apply_filters(pkgv, self.filters, pkgs_info, limit=not name_filtering)
if name_filtering and pkgs_info['pkgs_displayed']:
pkgs_info['pkgs_displayed'] = self._sort_by_word(word=self.filters['name'],
pkgs=pkgs_info['pkgs_displayed'],
limit=self.filters['display_limit'])
pkgs_info['pkgs_displayed'] = sort_packages(word=self.filters['name'],
pkgs=pkgs_info['pkgs_displayed'],
limit=self.filters['display_limit'])
self.wait_table_update = True
self.signal_table.emit(pkgs_info)

View File

@@ -32,6 +32,10 @@ class PackageView:
self.update_checked = model.update
self.status = PackageViewStatus.LOADING if model.status == PackageStatus.LOADING_DATA else PackageViewStatus.READY
@property
def name(self) -> str:
return self.model.name
def __repr__(self):
return '{} ({})'.format(self.model.name, self.get_type_label())