1 /****************************************************************************************
2  * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com>            *
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 AMAROK_COLLECTION_QUERYMAKER_H
18 #define AMAROK_COLLECTION_QUERYMAKER_H
19 
20 #include "core/amarokcore_export.h"
21 #include "core/meta/forward_declarations.h"
22 #include "core/meta/support/MetaConstants.h"
23 
24 #include <QObject>
25 #include <QStringList>
26 #include <QtGlobal>
27 
28 namespace Collections {
29 
30 class AMAROKCORE_EXPORT QueryMaker : public QObject
31 {
32     Q_OBJECT
33 
34     public:
35         enum AlbumQueryMode {
36             AllAlbums,
37             OnlyCompilations ,
38             OnlyNormalAlbums
39         };
40 
41         enum LabelQueryMode {
42             NoConstraint,
43             OnlyWithLabels,
44             OnlyWithoutLabels
45         };
46 
47         enum ArtistMatchBehaviour {
48             TrackArtists,
49             AlbumArtists,
50             AlbumOrTrackArtists
51         };
52 
53         /**
54          * Filters that the QueryMaker accepts for searching.
55          * not all implementations will accept all filter levels, so make it possible to
56          * specify which ones make sense for a given qm. Add to this as needed
57          */
58         enum ValidFilters {
59             TitleFilter = 1,
60             AlbumFilter = 2,
61             ArtistFilter = 4,
62             AlbumArtistFilter = 8,
63             GenreFilter = 16,
64             ComposerFilter = 32,
65             YearFilter = 64,
66             UrlFilter = 128,
67             AllFilters = 65535
68         };
69 
70         enum ReturnFunction {
71             Count,
72             Sum,
73             Max,
74             Min
75         };
76 
77         enum NumberComparison {
78             Equals,
79             GreaterThan,
80             LessThan
81         };
82 
83         enum QueryType {
84             None, // Set to facilitate using this in subclasses
85             Track,
86             Artist,
87             Album,
88             AlbumArtist,
89             Genre,
90             Composer,
91             Year,
92             Custom,
93             Label
94         };
95         QueryMaker();
96         ~QueryMaker() override;
97 
98         /**
99          *  starts the query. This method returns immediately. All processing is done in one or more
100          *  separate worker thread(s). One of the newResultReady signals will be emitted at least once,
101          *  followed by the queryDone() signal exactly once.
102          */
103         virtual void run() = 0;
104         /**
105          *  aborts a running query. Calling this method aborts a running query as soon as possible.
106          *  This method returns immediately. No signals will be emitted after calling this method.
107          *  This method has no effect if no query is running.
108          */
109         virtual void abortQuery() = 0;
110 
111         /**
112          * Sets the type of objects the querymaker will query for.  These are mutually
113          * exclusive.  The results of the query will be returned as objects of the
114          * appropriate type, therefore it is necessary to connect the client to the
115          * newResultReady( Meta::Type ) signal
116          *
117          * if you set QueryType custom, this starts a custom query. Unlike other query types, you have to set up the return
118          * values yourself using addReturnValue( qint64 ) and addReturnFunction(). The results will
119          * be returned as a QStringList. Therefore you have to connect to the
120          * newResultReady( QStringList ) signal to receive the results.
121          * @return this
122          */
123         virtual QueryMaker* setQueryType( QueryType type ) = 0;
124 
125         /**
126           * only works after starting a custom query with setQueryType( Custom )
127           * Use this to inform the query maker you are looking for results of type @p value.
128           * @param value the type of the results
129           * @return this
130           */
131         virtual QueryMaker* addReturnValue( qint64 value ) = 0;
132         /**
133          * Returns the output of the function specified by function.
134          * Only works after starting a custom query
135          * @return this
136          */
137         virtual QueryMaker* addReturnFunction( ReturnFunction function, qint64 value ) = 0;
138         /**
139          * Return results sorted by @p value.
140          * @return this
141          */
142         virtual QueryMaker* orderBy( qint64 value, bool descending = false ) = 0;
143 
144         virtual QueryMaker* addMatch( const Meta::TrackPtr &track ) = 0;
145         /**
146          * Match given artist. Depending on @param behaviour matches:
147          *   @p track artist if TrackArtists is given,
148          *   @p album artist if AlbumArtists is given,
149          *   any of track or album artist if AlbumOrTrackArtists is given.
150          *
151          * By default matches only track artist.
152          * @param artist the track artist.
153          */
154         virtual QueryMaker* addMatch( const Meta::ArtistPtr &artist, ArtistMatchBehaviour behaviour = TrackArtists ) = 0;
155         virtual QueryMaker* addMatch( const Meta::AlbumPtr &album ) = 0;
156         virtual QueryMaker* addMatch( const Meta::ComposerPtr &composer ) = 0;
157         virtual QueryMaker* addMatch( const Meta::GenrePtr &genre ) = 0;
158         virtual QueryMaker* addMatch( const Meta::YearPtr &year ) = 0;
159         virtual QueryMaker* addMatch( const Meta::LabelPtr &label );
160 
161         /**
162          * Add a filter of type @p value and value @p filter. The querymaker applies this to all queries.
163          * @param value the type of the filter
164          * @param filter the text to match
165          * @param matchBegin If set then wildcard match the beginning of @p text (*text)
166          * @param matchEnd If set then wildcard match the end of @p text (text*)
167          * @return this
168          */
169         virtual QueryMaker* addFilter( qint64 value, const QString &filter, bool matchBegin = false, bool matchEnd = false ) = 0;
170         /**
171          * Exclude filter of type @p value and value @p filter. The querymaker applies this to all queries.
172          * @param value the type of the filter
173          * @param filter the text to match
174          * @param matchBegin If set then wildcard match the beginning of @p text (*text)
175          * @param matchEnd If set then wildcard match the end of @p text (text*)
176          * @return this
177          */
178         virtual QueryMaker* excludeFilter( qint64 value, const QString &filter, bool matchBegin = false, bool matchEnd = false ) = 0;
179 
180         virtual QueryMaker* addNumberFilter( qint64 value, qint64 filter, NumberComparison compare ) = 0;
181         virtual QueryMaker* excludeNumberFilter( qint64 value, qint64 filter, NumberComparison compare ) = 0;
182 
183         /**
184          *  limit the maximum number of items in a result. the result will have [0..@p size ] items. When this function
185          *  is not used, the result size is unbounded. Note: the maximum size applies to each result individually, so if
186          *  the newResultReady signal is emitted multiple times, each result may have up to @p size items.
187          */
188         virtual QueryMaker* limitMaxResultSize( int size ) = 0;
189 
190         /**
191          * select the mode for querying albums. If this method is not called,
192          * QueryMaker defaults to AlbumQueryMode::AllAlbums.
193          */
194         virtual QueryMaker* setAlbumQueryMode( AlbumQueryMode mode );
195 
196         /**
197           * Sets the label query mode. This method restricts a query to tracks
198           * that have labels assigned to them, no labels assigned to them, or no constraint.
199           * The default is no constraint.
200           * @param mode The LabelQueryMode that will be used by the query.
201           * @see LabelQueryMode
202           */
203         virtual QueryMaker* setLabelQueryMode( LabelQueryMode mode );
204 
205         virtual QueryMaker* beginAnd() = 0;
206         virtual QueryMaker* beginOr() = 0;
207         virtual QueryMaker* endAndOr() = 0;
208 
209         /**
210          * Choose whether the query maker instance should delete itself after the query.
211          * By passing true the query maker instance will delete itself after emitting queryDone().
212          * Otherwise it is the responsibility of the owner (the code which called \::queryMaker() usually) to delete the instance
213          * when it is not needed anymore.
214          *
215          * Defaults to false, i.e. the querymaker instance will not delete itself.
216          */
217         QueryMaker* setAutoDelete( bool autoDelete );
218 
219         virtual int validFilterMask();
220 
221     Q_SIGNALS:
222         /**
223          * newResultReady will be emitted every time new results from the query maker are received.
224          * This signal can be emitted zero times (in case of no results) one (the usual case) or multiple times
225          * (e.g. in case when the result is received in several batches).
226          * The results will be terminated by a queryDone signal.
227          */
228         void newResultReady( const QStringList &);
229         void newTracksReady( const Meta::TrackList &);
230         void newArtistsReady( const Meta::ArtistList &);
231         void newAlbumsReady( const Meta::AlbumList &);
232         void newGenresReady( const Meta::GenreList &);
233         void newComposersReady( const Meta::ComposerList &);
234         void newYearsReady( const Meta::YearList &);
235         void newLabelsReady( const Meta::LabelList &);
236         void newDataReady( const Meta::DataList &);
237 
238         /**
239          * This signal is emitted after all the results have been submitted via zero or more newResultReady signals.
240          */
241         void queryDone();
242 };
243 
244 } //namespace Collections
245 
246 Q_DECLARE_METATYPE( Collections::QueryMaker* )
247 
248 #endif /* AMAROK_COLLECTION_QUERYMAKER_H */
249 
250