From 1bff6bca135625cbcd8d988748d188373a222272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sat, 21 Jan 2023 13:34:55 +0100 Subject: [PATCH 1/3] do not load all the packages to the main treewidgetitem --- wingetui/customWidgets.py | 3 +- wingetui/uiSections.py | 61 ++++++++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/wingetui/customWidgets.py b/wingetui/customWidgets.py index 32a332f9b..8777a54b5 100644 --- a/wingetui/customWidgets.py +++ b/wingetui/customWidgets.py @@ -198,8 +198,9 @@ def addItem(self, item: QWidget): class TreeWidgetItemWithQAction(QTreeWidgetItem): itemAction: QAction = QAction - def __init__(self): + def __init__(self, parent = None): super().__init__() + def setAction(self, action: QAction): self.itemAction = action diff --git a/wingetui/uiSections.py b/wingetui/uiSections.py index 0472c8f66..aaf677349 100644 --- a/wingetui/uiSections.py +++ b/wingetui/uiSections.py @@ -30,6 +30,8 @@ class DiscoverSoftwareSection(QWidget): isToolbarSmall: bool = False toolbarDefaultWidth: int = 0 packages: dict[str:dict] = {} + packageItems: list[TreeWidgetItemWithQAction] = [] + showableItems: list[TreeWidgetItemWithQAction] = [] wingetLoaded = False scoopLoaded = False @@ -119,6 +121,7 @@ def __init__(self, parent = None): self.packageListScrollBar = CustomScrollBar() self.packageListScrollBar.setOrientation(Qt.Vertical) + self.packageListScrollBar.valueChanged.connect(lambda v: self.addItemsToTreeWidget() if v==self.packageListScrollBar.maximum() else None) self.packageList = TreeWidget("a") self.packageList.setHeaderLabels([_("Package Name"), _("Package ID"), _("Version"), _("Source")]) @@ -181,6 +184,7 @@ def showMenu(pos: QPoint): self.packageList.setColumnWidth(2, 150) self.packageList.setColumnWidth(3, 150) + self.loadingProgressBar = QProgressBar() self.loadingProgressBar.setRange(0, 1000) self.loadingProgressBar.setValue(0) @@ -389,6 +393,7 @@ def finishLoadingIfNeeded(self, store: str) -> None: self.filter() self.searchButton.setEnabled(True) self.query.setEnabled(True) + self.addItemsToTreeWidget() elif(store == "scoop"): self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount()))) if self.packageList.topLevelItemCount() == 0: @@ -399,6 +404,7 @@ def finishLoadingIfNeeded(self, store: str) -> None: self.reloadButton.setEnabled(True) self.filter() self.searchButton.setEnabled(True) + self.addItemsToTreeWidget() self.query.setEnabled(True) elif("chocolatey" in store): msg = store.split("-")[-1] @@ -417,6 +423,7 @@ def finishLoadingIfNeeded(self, store: str) -> None: self.reloadButton.setEnabled(True) self.filter() self.searchButton.setEnabled(True) + self.addItemsToTreeWidget() self.query.setEnabled(True) if(self.wingetLoaded and self.scoopLoaded and self.chocoLoaded): self.reloadButton.setEnabled(True) @@ -429,10 +436,10 @@ def finishLoadingIfNeeded(self, store: str) -> None: def resizeEvent(self, event: QResizeEvent): self.adjustWidgetsSize() return super().resizeEvent(event) - + def addItem(self, name: str, id: str, version: str, store) -> None: if not "---" in name: - item = TreeWidgetItemWithQAction() + item = TreeWidgetItemWithQAction(self) item.setText(0, name) item.setText(1, id) item.setIcon(0, self.installIcon) @@ -452,24 +459,54 @@ def addItem(self, name: str, id: str, version: str, store) -> None: "store": store, "item": item } - self.packageList.addTopLevelItem(item) + self.packageItems.append(item) + if self.containsQuery(item, self.query.text()): + self.showableItems.append(item) + + def addItemsToTreeWidget(self, reset: bool = False): + if reset: + for item in self.packageItems: + if self.packageList.indexOfTopLevelItem(item) >= 0: + if not item in self.showableItems: + self.packageList.takeTopLevelItem(self.packageList.indexOfTopLevelItem(item)) + nextItem = 0 + else: + nextItem = self.packageList.topLevelItemCount() + addedItems = 0 + while addedItems < 500: + cprint(len(self.showableItems)) + if nextItem >= len(self.showableItems): + break + itemToAdd = self.showableItems[nextItem] + itemToAdd.setHidden(False) + self.packageList.addTopLevelItem(itemToAdd) + addedItems += 1 + nextItem += 1 + currentItem = self.packageList.currentItem() + if currentItem != None: + if self.containsQuery(currentItem, self.query.text()): + self.packageList.addTopLevelItem(currentItem) + self.countLabel.setText(str(self.packageList.topLevelItemCount())) def filter(self) -> None: print(f"🟢 Searching for string \"{self.query.text()}\"") Thread(target=lambda: (time.sleep(0.25), self.callInMain.emit(partial(self.finishFiltering, self.query.text())))).start() + + def containsQuery(self, item: QTreeWidgetItem, text: str) -> bool: + return text.lower() in item.text(0).lower() or text.lower() in item.text(1).lower() def finishFiltering(self, text: str): if self.query.text() != text: return - resultsFound = self.packageList.findItems(self.query.text(), Qt.MatchContains, 0) - resultsFound += self.packageList.findItems(self.query.text(), Qt.MatchContains, 1) + self.showableItems = [] found = 0 - for item in self.packageList.findItems('', Qt.MatchContains, 0): - if not(item in resultsFound): - item.setHidden(True) - else: - item.setHidden(False) - found += 1 + for item in self.packageItems: + try: + if self.containsQuery(item, text): + self.showableItems.append(item) + found += 1 + except RuntimeError: + print("nullitem") if found == 0: if self.packageList.label.text() == "": self.packageList.label.show() @@ -478,6 +515,7 @@ def finishFiltering(self, text: str): if self.packageList.label.text() == _("No packages found matching the input criteria"): self.packageList.label.hide() self.packageList.label.setText("") + self.addItemsToTreeWidget(reset = True) self.packageList.scrollToItem(self.packageList.currentItem()) def showQuery(self) -> None: @@ -497,6 +535,7 @@ def fastinstall(self, title: str, id: str, store: str, admin: bool = False, inte self.addInstallation(PackageInstallerWidget(title, store, useId=not("…" in id), packageId=id, admin=admin, args=["--skip" if skiphash else ""], packageItem=packageItem)) def reload(self) -> None: + self.packageItems = [] self.scoopLoaded = False self.wingetLoaded = False self.chocoLoaded = False From 8f015e8c292c8755a7d623096d9eb9a7817b36e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sat, 21 Jan 2023 14:50:48 +0100 Subject: [PATCH 2/3] reimplement sorting mechanism and improve autoload for widgets --- wingetui/uiSections.py | 55 +++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/wingetui/uiSections.py b/wingetui/uiSections.py index aaf677349..b2b6da9c2 100644 --- a/wingetui/uiSections.py +++ b/wingetui/uiSections.py @@ -133,9 +133,10 @@ def __init__(self, parent = None): self.packageList.setVerticalScrollMode(QTreeWidget.ScrollPerPixel) self.packageList.setIconSize(QSize(24, 24)) self.packageList.itemDoubleClicked.connect(lambda item, column: self.openInfo(item.text(0), item.text(1), item.text(3), item) if not getSettings("InstallOnDoubleClick") else self.fastinstall(item.text(0), item.text(1), item.text(3))) + self.packageList.currentItemChanged.connect(lambda: self.addItemsToTreeWidget() if self.packageList.indexOfTopLevelItem(self.packageList.currentItem())+20 > self.packageList.topLevelItemCount() else None) sct = QShortcut(Qt.Key.Key_Return, self.packageList) - sct.activated.connect(lambda: self.packageList.itemDoubleClicked.emit(self.packageList.currentItem(), 0)) + sct.activated.connect(lambda: self.packageList.itemDoubleClicked.emit(self.packageList.currentItem(), 0) if self.packageList.hasFocus() else None) def showMenu(pos: QPoint): if not self.packageList.currentItem(): @@ -181,6 +182,7 @@ def showMenu(pos: QPoint): header.setSectionResizeMode(1, QHeaderView.Stretch) header.setSectionResizeMode(2, QHeaderView.Fixed) header.setSectionResizeMode(3, QHeaderView.Fixed) + header.sectionClicked.connect(lambda: self.finishFiltering(self.query.text())) self.packageList.setColumnWidth(2, 150) self.packageList.setColumnWidth(3, 150) @@ -383,28 +385,27 @@ def importPackages(self): def finishLoadingIfNeeded(self, store: str) -> None: if(store == "winget"): - self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount()))) - if self.packageList.topLevelItemCount() == 0: + self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(len(self.packageItems)))) + if len(self.packageItems) == 0: self.packageList.label.setText(self.countLabel.text()) else: self.packageList.label.setText("") self.wingetLoaded = True self.reloadButton.setEnabled(True) - self.filter() + self.finishFiltering(self.query.text()) self.searchButton.setEnabled(True) self.query.setEnabled(True) self.addItemsToTreeWidget() elif(store == "scoop"): - self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount()))) - if self.packageList.topLevelItemCount() == 0: + self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(len(self.packageItems)))) + if len(self.packageItems) == 0: self.packageList.label.setText(self.countLabel.text()) else: self.packageList.label.setText("") self.scoopLoaded = True self.reloadButton.setEnabled(True) - self.filter() + self.finishFiltering(self.query.text()) self.searchButton.setEnabled(True) - self.addItemsToTreeWidget() self.query.setEnabled(True) elif("chocolatey" in store): msg = store.split("-")[-1] @@ -414,24 +415,23 @@ def finishLoadingIfNeeded(self, store: str) -> None: if msg == "finishedcache": self.reload() self.cachingChocoLabel.hide() - self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(self.packageList.topLevelItemCount()))) - if self.packageList.topLevelItemCount() == 0: + self.countLabel.setText(_("Found packages: {0}, not finished yet...").format(str(len(self.packageItems)))) + if len(self.packageItems) == 0: self.packageList.label.setText(self.countLabel.text()) else: self.packageList.label.setText("") self.chocoLoaded = True self.reloadButton.setEnabled(True) - self.filter() + self.finishFiltering(self.query.text()) self.searchButton.setEnabled(True) - self.addItemsToTreeWidget() self.query.setEnabled(True) if(self.wingetLoaded and self.scoopLoaded and self.chocoLoaded): self.reloadButton.setEnabled(True) - self.filter() + self.finishFiltering(self.query.text()) self.loadingProgressBar.hide() - self.countLabel.setText(_("Found packages: {0}").format(str(self.packageList.topLevelItemCount()))) + self.countLabel.setText(_("Found packages: {0}").format(str(len(self.packageItems)))) self.packageList.label.setText("") - print("🟢 Total packages: "+str(self.packageList.topLevelItemCount())) + print("🟢 Total packages: "+str(len(self.packageItems))) def resizeEvent(self, event: QResizeEvent): self.adjustWidgetsSize() @@ -473,8 +473,7 @@ def addItemsToTreeWidget(self, reset: bool = False): else: nextItem = self.packageList.topLevelItemCount() addedItems = 0 - while addedItems < 500: - cprint(len(self.showableItems)) + while addedItems < 100: if nextItem >= len(self.showableItems): break itemToAdd = self.showableItems[nextItem] @@ -496,10 +495,32 @@ def containsQuery(self, item: QTreeWidgetItem, text: str) -> bool: return text.lower() in item.text(0).lower() or text.lower() in item.text(1).lower() def finishFiltering(self, text: str): + def getTitle(item: QTreeWidgetItem) -> str: + return item.text(0) + def getID(item: QTreeWidgetItem) -> str: + return item.text(1) + def getVersion(item: QTreeWidgetItem) -> str: + return item.text(2) + def getSource(item: QTreeWidgetItem) -> str: + return item.text(3) + if self.query.text() != text: return self.showableItems = [] found = 0 + + sortColumn = self.packageList.sortColumn() + descendingSort = self.packageList.header().sortIndicatorOrder() == Qt.SortOrder.DescendingOrder + match sortColumn: + case 0: + self.packageItems.sort(key=getTitle, reverse=descendingSort) + case 1: + self.packageItems.sort(key=getID, reverse=descendingSort) + case 2: + self.packageItems.sort(key=getVersion, reverse=descendingSort) + case 3: + self.packageItems.sort(key=getSource, reverse=descendingSort) + for item in self.packageItems: try: if self.containsQuery(item, text): From 3f1428499c649eea1f6a465c6ea8b0b3ae48fa7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Sat, 21 Jan 2023 14:51:05 +0100 Subject: [PATCH 3/3] remove dummy label --- wingetui/uiSections.py | 1 - 1 file changed, 1 deletion(-) diff --git a/wingetui/uiSections.py b/wingetui/uiSections.py index b2b6da9c2..efbe87bbb 100644 --- a/wingetui/uiSections.py +++ b/wingetui/uiSections.py @@ -485,7 +485,6 @@ def addItemsToTreeWidget(self, reset: bool = False): if currentItem != None: if self.containsQuery(currentItem, self.query.text()): self.packageList.addTopLevelItem(currentItem) - self.countLabel.setText(str(self.packageList.topLevelItemCount())) def filter(self) -> None: print(f"🟢 Searching for string \"{self.query.text()}\"")