Repository: napari/napari

Issue:
Plugin install filter feature inconsistent depending on timing
## 🐛 Bug
See discussion at https://napari.zulipchat.com/#narrow/stream/212875-general/topic/.E2.9C.94.20Plugin.20installation

I think there are a few subtle issues going on in the plugin install filter field, such that depending on when you start typing, results may or may not appear, or, the filter may or may not be applied? 
To reproduce, start napari, open the plugin installer, and try to start typing into the field quickly (for instance "redlionfish" as in the zulip convo).  Try a few times, with different "latency-to-type", and you might see different results.

cc @goanpeca 



Discussion:
Yep I think that is another easter egg you have found 🤪

Will look into it !

Resolving patch:
diff --git a/napari/_qt/dialogs/qt_plugin_dialog.py b/napari/_qt/dialogs/qt_plugin_dialog.py
--- a/napari/_qt/dialogs/qt_plugin_dialog.py
+++ b/napari/_qt/dialogs/qt_plugin_dialog.py
@@ -554,6 +554,7 @@ def filter(self, text: str):
 class QtPluginDialog(QDialog):
     def __init__(self, parent=None):
         super().__init__(parent)
+        self.already_installed = set()
         self.installer = Installer()
         self.setup_ui()
         self.installer.set_output_widget(self.stdout_text)
@@ -591,18 +592,18 @@ def refresh(self):
 
         plugin_manager.discover()  # since they might not be loaded yet
 
-        already_installed = set()
+        self.already_installed = set()
 
         for plugin_name, mod_name, distname in plugin_manager.iter_available():
             # not showing these in the plugin dialog
             if plugin_name in ('napari_plugin_engine',):
                 continue
 
-            if distname in already_installed:
+            if distname in self.already_installed:
                 continue
 
             if distname:
-                already_installed.add(distname)
+                self.already_installed.add(distname)
                 meta = standard_metadata(distname)
             else:
                 meta = {}
@@ -621,20 +622,15 @@ def refresh(self):
             )
         self.installed_label.setText(
             trans._(
-                "Installed Plugins ({amount})", amount=len(already_installed)
+                "Installed Plugins ({amount})",
+                amount=len(self.already_installed),
             )
         )
 
         # fetch available plugins
         self.worker = create_worker(iter_napari_plugin_info)
 
-        def _handle_yield(project_info):
-            if project_info.name in already_installed:
-                self.installed_list.tag_outdated(project_info)
-            else:
-                self.available_list.addItem(project_info)
-
-        self.worker.yielded.connect(_handle_yield)
+        self.worker.yielded.connect(self._handle_yield)
         self.worker.finished.connect(self.working_indicator.hide)
         self.worker.finished.connect(self._update_count_in_label)
         self.worker.start()
@@ -776,6 +772,24 @@ def _install_packages(self, packages: Sequence[str] = ()):
         if packages:
             self.installer.install(packages)
 
+    def _handle_yield(self, project_info):
+        if project_info.name in self.already_installed:
+            self.installed_list.tag_outdated(project_info)
+        else:
+            self.available_list.addItem(project_info)
+
+        self.filter()
+
+    def filter(self, text: str = None) -> None:
+        """Filter by text or set current text as filter."""
+        if text is None:
+            text = self.packages_filter.text()
+        else:
+            self.packages_filter.setText(text)
+
+        self.installed_list.filter(text)
+        self.available_list.filter(text)
+
 
 if __name__ == "__main__":
     from qtpy.QtWidgets import QApplication


Test patch: