From 764a0961c9c9b2f018431e2581888dc582a3aea4 Mon Sep 17 00:00:00 2001
From: Shaowen Yin <cosven@users.noreply.github.com>
Date: Wed, 20 Dec 2023 00:46:00 +0800
Subject: [PATCH] gui: introduce UISupportsDiscovery protocol (#740)

---
 feeluown/gui/provider_ui.py    | 17 ++++++++++++++++-
 feeluown/gui/uimain/sidebar.py |  9 +++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/feeluown/gui/provider_ui.py b/feeluown/gui/provider_ui.py
index 490399e94d..192cad265c 100644
--- a/feeluown/gui/provider_ui.py
+++ b/feeluown/gui/provider_ui.py
@@ -1,6 +1,8 @@
 from abc import abstractmethod, ABC
 from typing import TYPE_CHECKING, runtime_checkable, Protocol, Dict, Optional, List
 
+from PyQt5.QtCore import pyqtSignal, QObject
+
 from feeluown.library import ProviderV2
 from feeluown.gui.widgets.provider import ProvidersModel
 from feeluown.utils.dispatch import Signal
@@ -17,6 +19,14 @@ def login_or_go_home(self):
         ...
 
 
+@runtime_checkable
+class UISupportsDiscovery(Protocol):
+
+    @abstractmethod
+    def discovery(self):
+        ...
+
+
 class AbstractProviderUi(ABC):
     """Abstract base class for provider ui."""
 
@@ -33,9 +43,12 @@ def provider(self) -> ProviderV2:
         ...
 
 
-class CurrentProviderUiManager:
+class CurrentProviderUiManager(QObject):
+
+    changed = pyqtSignal([object, object])
 
     def __init__(self, app: 'GuiApp'):
+        super().__init__(parent=app)
         self._app = app
         self._current: Optional[AbstractProviderUi] = None
 
@@ -48,7 +61,9 @@ def get(self):
 
     def set(self, provider_ui: AbstractProviderUi):
         self._current_item = None
+        old = self._current
         self._current = provider_ui
+        self.changed.emit(provider_ui, old)
 
     def get_either(self):
         return self._current or self._current_item
diff --git a/feeluown/gui/uimain/sidebar.py b/feeluown/gui/uimain/sidebar.py
index c94c84e21d..ffc3da9170 100644
--- a/feeluown/gui/uimain/sidebar.py
+++ b/feeluown/gui/uimain/sidebar.py
@@ -19,9 +19,11 @@
     PlusButton,
     TriagleButton,
 )
+from feeluown.gui.provider_ui import UISupportsDiscovery
 from feeluown.gui.widgets.playlists import PlaylistsView
 from feeluown.gui.components import CollectionListView
 from feeluown.gui.widgets.my_music import MyMusicView
+from feeluown.gui.helpers import disconnect_slots_if_has
 
 if TYPE_CHECKING:
     from feeluown.app.gui_app import GuiApp
@@ -166,6 +168,8 @@ def __init__(self, app: 'GuiApp', parent=None):
         self.collections_con.create_btn.clicked.connect(
             self.popup_collection_adding_dialog)
         self.playlists_con.create_btn.clicked.connect(self._create_playlist)
+        self._app.current_pvd_ui_mgr.changed.connect(
+            self.on_current_pvd_ui_changed)
 
     def popup_collection_adding_dialog(self):
         dialog = QDialog(self)
@@ -273,3 +277,8 @@ def do():
                           QMessageBox.Yes | QMessageBox.No, self)
         box.accepted.connect(do)
         box.open()
+
+    def on_current_pvd_ui_changed(self, pvd_ui, _):
+        disconnect_slots_if_has(self.discovery_btn)
+        if isinstance(pvd_ui, UISupportsDiscovery):
+            self.discovery_btn.clicked.connect(pvd_ui.discovery)