1 /****************************************************************************************
2  * Copyright (c) 2007 Nikolaj Hald Nielsen <nhn@kde.org>                                *
3  *                                                                                      *
4  * This program is free software; you can redistribute it and/or modify it under        *
5  * the terms of the GNU General Public License as published by the Free Software        *
6  * Foundation; either version 2 of the License, or (at your option) any later           *
7  * version.                                                                             *
8  *                                                                                      *
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
11  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
12  *                                                                                      *
13  * You should have received a copy of the GNU General Public License along with         *
14  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
15  ****************************************************************************************/
16 
17 #ifndef AMAROKSERVICEBASE_H
18 #define AMAROKSERVICEBASE_H
19 
20 #include "browsers/BrowserCategory.h"
21 #include "core/support/Amarok.h"
22 #include "core/support/PluginFactory.h"
23 #include "InfoParserBase.h"
24 #include "ServiceCollectionTreeView.h"
25 #include "ServiceMetaBase.h"
26 #include "amarok_export.h"
27 #include "core-impl/meta/proxy/MetaProxy.h"
28 #include "widgets/PrettyTreeView.h"
29 
30 #include <KLocalizedString>
31 
32 #include <QAbstractItemModel>
33 #include <QPushButton>
34 #include <QQueue>
35 #include <QSortFilterProxyModel>
36 #include <QSplitter>
37 
38 class BoxWidget;
39 class ServiceBase;
40 class SearchWidget;
41 class QMenuBar;
42 /**
43 A virtual base class for factories for creating and handling the different types of service plugins
44 
45 @author Nikolaj Hald Nielsen <nhn@kde.org>
46  */
47 class AMAROK_EXPORT ServiceFactory : public Plugins::PluginFactory, public Collections::TrackProvider
48 {
49     Q_OBJECT
50     public:
51         /**
52          * Constructor.
53          */
54         ServiceFactory();
55 
56         /**
57          * Destructor.
58          */
59         ~ServiceFactory() override;
60 
61         /**
62          * Get the name of this service type. Reimplemented by subclasses.
63          * @return The name.
64          */
65         virtual QString name() = 0;
66 
67         /**
68          * Get a KConfigGroup object containing the config for this type of service. Reimplemented by subclasses.
69          * @return
70          */
71         virtual KConfigGroup config() = 0;
72 
73         /**
74          * Get a best guess if a service of the type generated by this factory will be likely to be able to provide tracks
75          * for a given url. This is needed in order to allow on.demand loading of service plugins to handle a url. Reimplemented by subclasses.
76          * @param url The url to test.
77          * @return A bool representing whether the ServiceFactory believes that a service of this kind can process the given url.
78          */
possiblyContainsTrack(const QUrl & url)79         bool possiblyContainsTrack( const QUrl &url ) const override { Q_UNUSED( url ); return false; }
80 
81         /**
82          * Attempt to create a Meta::Track object from a given url. This method is meant as a proxy that will forward this call to one or more
83          * services managed by this factory. If init has not been called ( no services of this kind has been loaded ) they can now be loaded on
84          * demand.
85          * @param url The url to test.
86          * @return A Meta::TrackPtr based one the url, or empty if nothing was known about the url.
87          */
88         Meta::TrackPtr trackForUrl( const QUrl &url ) override;
89 
90         /**
91          * Clear the list of active services created by this factory. Used when unloading services.
92          */
93         void clearActiveServices();
94 
activeServices()95         QList<ServiceBase *> activeServices() { return m_activeServices.toList(); }
96 
97     public Q_SLOTS:
98         /**
99          * The service is ready!
100          */
101         void slotServiceReady();
102 
103     Q_SIGNALS:
104         /**
105          * This signal is emitted whenever a new service has been loaded.
106          * @param newService The service that has been loaded.
107          */
108         void newService( ServiceBase *newService );
109 
110         /**
111          * This signal is emitted whenever a service is removed. ServiceFactory deletes
112          * the service in next event loop iteration.
113          *
114          * @param removedService The service that has been removed
115          */
116         void removeService( ServiceBase *removedService );
117 
118     private Q_SLOTS:
119         void slotNewService( ServiceBase *newService );
120         void slotRemoveService( ServiceBase *service );
121 
122     private:
123         QSet<ServiceBase *> m_activeServices;
124         QQueue<MetaProxy::TrackPtr> m_tracksToLocate;
125 };
126 
127 
128 /**
129 A composite widget used as a base for building service browsers. It contains a home button ( to return to the list of services ), a name label, a tree view, grouping and filtering widgets and other conveniences that handle much of the layout of a new service. Some of these items can be shown or hidden as needed.
130 
131 @author Nikolaj Hald Nielsen <nhn@kde.org>
132 */
133 class AMAROK_EXPORT ServiceBase : public BrowserCategory
134 {
135     Q_OBJECT
136 
137 public:
138 
139      /**
140       * Constructor.
141       */
142      ServiceBase( const QString &name, ServiceFactory* parent, bool useCollectionTreeView = true, const QString &m_prettyName = QString() );
143 
144     /**
145      * Destructor.
146      */
147     ~ServiceBase() override;
148 
149     /**
150      * Set the SingleCollectionTreeItemModel that will be used to populate the tree view.
151      * @param model The model.
152      */
153     void setModel( QAbstractItemModel * model );
154 
155     /**
156      * Get the model that is used for displaying items in the tree view.
157      * @return The model.
158      */
159     QAbstractItemModel * model();
160 
161     /**
162     * Set the SingleCollectionTreeItemModel that will be used to populate the tree view.
163     * @param model The model.
164     */
165     void setView( QTreeView * model );
166 
167     /**
168     * Get the model that is used for displaying items in the tree view.
169     * @return The model.
170     */
171     QTreeView * view();
172 
173     /**
174      * Set if it should be possible to add the tracks shown in the tree view to the playlist. This method is a bit of a hack and might be removed!
175      * @param playable Are tracks playable.
176      */
177     void setPlayableTracks( bool playable );
178 
179     /**
180      * Set the info parser that will be used to show information about selected items in the service info context applet.
181      * @param infoParser The info parser to use.
182      */
183     void setInfoParser( InfoParserBase * infoParser );
184 
185     /**
186      * Get the info parser used to show information about selected items in the service info context applet.
187      * @return The info parser.
188      */
189     InfoParserBase * infoParser();
190 
191     /**
192      * Return the Collection used by this service.
193      * @return The collection.
194      */
195     virtual Collections::Collection * collection() = 0;
196 
197     /**
198      * Do expensive initialization. This method is called when the service is first shown.
199      */
200     void polish() override = 0;
201 
202     /**
203      * ??????
204      * @return
205      */
updateContextView()206     virtual bool updateContextView() { return false; }
207 
208     /**
209      * Apply a filter to the tree view.
210      * @param filter The filter to apply.
211      */
212     void setFilter( const QString &filter ) override;
213 
214     /**
215      * Returns a list of the messages that the current service accepts. Default implementation does not
216      * accept any.
217      * @return A string containing a description of accepted messages.
218      */
219     virtual QString messages();
220 
221     /**
222      * Send a message to this service. Default implementation returns an error as no messages are
223      * accepted
224      * @param message The message to send to the service
225      * @return The reply to the message
226      */
227     virtual QString sendMessage( const QString &message );
228 
229     /**
230      * Returns whether the service is ready or not.
231      * @return true if the status is ready, false if it is not ready
232      */
233     bool serviceReady() const;
234     //virtual void reset() = 0;
235 
236     /**
237      * Returns the service's parent factory.
238      * @return the service's Factory
239      */
240     ServiceFactory* parent() const;
241 
242     QString filter() const override;
243     QList<CategoryId::CatMenuId> levels() const override;
244 
245 public Q_SLOTS:
246     //void treeViewSelectionChanged( const QItemSelection & selected );
247     /**
248      * New info should be shown in the service info applet ( if present ).
249      * @param infoHtml The html formatted info to show.
250      */
251     void infoChanged ( const QString &infoHtml );
252 
253     /**
254      * Set sorting in the tree view to be "Artist-Album".
255      */
256     void sortByArtistAlbum();
257 
258     /**
259      * Set sorting in the tree view to be "Artist".
260      */
261     void sortByArtist();
262 
263     /**
264      * Set sorting in the tree view to be "Album".
265      */
266     void sortByAlbum();
267 
268     /**
269      * Set sorting in the tree view to be "Genre-Artist".
270      */
271     void sortByGenreArtist();
272 
273     /**
274      * Set sorting in the tree view to be "Genre-Artist-Album".
275      */
276     void sortByGenreArtistAlbum();
277 
278     void setLevels( const QList<CategoryId::CatMenuId> &levels ) override;
279 
280 Q_SIGNALS:
281     /**
282      * Signal emitted when the service wants to be hidden and the service browser list shown instead, for instance when the "Home" button is clicked.
283      */
284     void home();
285 
286     /**
287      * Signal emitted when the selection in the tree view has changed ( and is only a single item ).
288      * @param item The selected item
289      */
290     void selectionChanged( CollectionTreeItem *item );
291 
292     /**
293      * Signal emitted when the service is ready to be used. You don't need to Q_EMIT this
294      * manually, just call setServiceReady() as appropriate.
295      */
296     void ready();
297 
298 protected Q_SLOTS:
299     /**
300      * Slot called when an item in the tree view has been activated
301      * @param index The index of the activated item
302      */
303     void itemActivated ( const QModelIndex & index );
304 
305      /**
306      * Slot called when the selection in the tree view has changed ( and is only a single item ).
307      * @param item The selected item
308      */
309     void itemSelected( CollectionTreeItem * item  );
310 
311 protected:
312     /**
313      * Generate info to show in the service info applet. useful for showing initial info before any items are selected and hence
314      * trigger the info parser.
315      * @param html
316      */
317     virtual void generateWidgetInfo( const QString &html = QString() ) const;
318 
319     /**
320      * sets serviceReady() and emits a signal ready() as appropriate.
321      */
322     void setServiceReady( bool ready );
323 
324     static ServiceBase *s_instance;
325     QTreeView *m_contentView;
326     ServiceFactory *m_parentFactory;
327 
328     BoxWidget    *m_topPanel;
329     BoxWidget    *m_bottomPanel;
330     bool         m_polished;
331 
332     bool m_useCollectionTreeView;
333 
334     QList<QUrl>   m_urlsToInsert;
335 
336     InfoParserBase * m_infoParser;
337 
338     QMenuBar *m_menubar;
339     QMenu *m_filterMenu;
340     SearchWidget * m_searchWidget;
341 
342     //void addToPlaylist( CollectionTreeItem * item );
343 
344 private: // need to move stuff here
345     bool m_serviceready;
346 
347     QAbstractItemModel *m_model;
348     QSortFilterProxyModel *m_filterModel;
349 };
350 
351 
352 #endif
353