File indexing completed on 2024-05-05 04:48:29
0001 /**************************************************************************************** 0002 * Copyright (c) 2008 Daniel Jones <danielcjones@gmail.com> * 0003 * Copyright (c) 2009 Leo Franchi <lfranchi@kde.org> * 0004 * Copyright (c) 2010, 2011 Ralf Engels <ralf-engels@gmx.de> * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify it under * 0007 * the terms of the GNU General Public License as published by the Free Software * 0008 * Foundation; either version 2 of the License, or (at your option) version 3 or * 0009 * any later version accepted by the membership of KDE e.V. (or its successor approved * 0010 * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of * 0011 * version 3 of the license. * 0012 * * 0013 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0014 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0015 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0016 * * 0017 * You should have received a copy of the GNU General Public License along with * 0018 * this program. If not, see <http://www.gnu.org/licenses/>. * 0019 ****************************************************************************************/ 0020 0021 #ifndef AMAROK_BIAS_H 0022 #define AMAROK_BIAS_H 0023 0024 #include "amarok_export.h" 0025 #include "dynamic/TrackSet.h" 0026 0027 #include <QMetaType> 0028 #include <QObject> 0029 #include <QRect> 0030 #include <QWidget> 0031 #include <QSharedData> 0032 #include <QExplicitlySharedDataPointer> 0033 0034 class QPainter; 0035 class QXmlStreamReader; 0036 class QXmlStreamWriter; 0037 0038 namespace Collections { 0039 class Collection; 0040 } 0041 0042 namespace Dynamic 0043 { 0044 class AbstractBias; 0045 0046 typedef QExplicitlySharedDataPointer<Dynamic::AbstractBias> BiasPtr; 0047 typedef QList<Dynamic::BiasPtr> BiasList; 0048 0049 /** A bias is essentially just a function that evaluates the suitability of a 0050 playlist in some arbitrary way. 0051 It's function is to return new tracks for a playlist. For this it can 0052 only rely on previous tracks in the playlist (because of the way the 0053 playlists are generated). 0054 0055 0056 All biases are shared data to prevent problems when they are removed while the 0057 BiasSolver is running at the same time. 0058 */ 0059 class AMAROK_EXPORT AbstractBias : public QObject, public QSharedData 0060 { 0061 Q_OBJECT 0062 0063 public: 0064 AbstractBias(); 0065 ~AbstractBias() override; 0066 0067 /** Reads the contents of this object from an xml stream */ 0068 virtual void fromXml( QXmlStreamReader *reader ); 0069 0070 /** Writes the contents of this object to an xml stream. 0071 Only the content is written and no enclosing tags. 0072 This is done to make it mirror the constructor which does not read those 0073 tags either. 0074 */ 0075 virtual void toXml( QXmlStreamWriter *writer ) const; 0076 0077 /** Creates a new bias (with all sub-biases) that is a copy of this. 0078 * 0079 * This function does a deep copy by writing and reading back from xml. 0080 * Should work for all biases. 0081 */ 0082 BiasPtr clone() const; 0083 0084 /** Returns the name of this bias. 0085 The name is used for reading and writing to xml. 0086 */ 0087 static QString sName(); 0088 0089 /** The same as sName just not static */ 0090 virtual QString name() const; 0091 0092 /** The textual representation of this bias (localized) */ 0093 virtual QString toString() const = 0; 0094 0095 /** Create a widget appropriate for editing the bias. 0096 */ 0097 virtual QWidget* widget( QWidget* parent = nullptr ); 0098 0099 /** Paints an operator (like "and" or a progress bar") in front of a bias item */ 0100 virtual void paintOperator( QPainter* painter, const QRect &rect, Dynamic::AbstractBias* bias ); 0101 0102 /** Returns the tracks that would fit at the end of the given playlist. 0103 The function can also return an "outstanding" Track set and return 0104 later with a resultReady signal. 0105 In such a case "matchingTracks" cannot be called again until 0106 the result was received or invalidate called. 0107 @param playlist The current playlist context for the track. 0108 @param contextCount The number of songs that are already fixed. 0109 @param finalCount The number of tracks that the playlist should finally contain (including the contextCount) 0110 @param universe A TrackCollectionPtr to be used for the resulting TrackSet 0111 */ 0112 virtual TrackSet matchingTracks( const Meta::TrackList& playlist, 0113 int contextCount, int finalCount, 0114 const TrackCollectionPtr &universe ) const = 0; 0115 0116 /** Returns true if indicated track fits that position. 0117 The function might block until a result is ready. 0118 @param position The position inside the playlist that we search a track for. 0119 The position can be larger than the number of playlist entries 0120 if we search a track for the end of the playlist. 0121 @param playlist The current playlist context for the track. 0122 @param contextCount The number of songs that are already fixed. 0123 */ 0124 virtual bool trackMatches( int position, 0125 const Meta::TrackList& playlist, int contextCount ) const = 0; 0126 0127 Q_SIGNALS: 0128 /** This signal is emitted when the bias is changed. 0129 e.g. an internal variable is set so that the bias will return different tracks. 0130 this can also happen if the bias depends on the current track and this 0131 track changed. 0132 */ 0133 void changed( Dynamic::BiasPtr thisBias ); 0134 0135 /** This signal is emitted when this bias should be replaced by a new one. */ 0136 void replaced( Dynamic::BiasPtr oldBias, Dynamic::BiasPtr newBias ); 0137 0138 /** Emitted when the result to a previously called matchingTracks is ready */ 0139 void resultReady( const Dynamic::TrackSet &set ); 0140 0141 public Q_SLOTS: 0142 /** This slot is called when the bias should discard cached results. 0143 This will be done in case a new playlist is requested for an updated 0144 collection. 0145 */ 0146 virtual void invalidate(); 0147 0148 /** Call this function when this bias should be replaced by a new one. 0149 @param newBias The bias that replaces this bias. If you give 0150 an empty BiasPtr as argument the bias will be removed. 0151 */ 0152 virtual void replace( const Dynamic::BiasPtr &newBias ); 0153 }; 0154 0155 /** A bias that returns all the tracks in the universe as possible tracks */ 0156 class AMAROK_EXPORT RandomBias : public AbstractBias 0157 { 0158 Q_OBJECT 0159 0160 public: 0161 RandomBias(); 0162 ~RandomBias() override; 0163 0164 static QString sName(); 0165 QString name() const override; 0166 QString toString() const override; 0167 0168 QWidget* widget( QWidget* parent = nullptr ) override; 0169 0170 TrackSet matchingTracks( const Meta::TrackList& playlist, 0171 int contextCount, int finalCount, 0172 const TrackCollectionPtr &universe ) const override; 0173 0174 bool trackMatches( int position, 0175 const Meta::TrackList& playlist, 0176 int contextCount ) const override; 0177 0178 private: 0179 Q_DISABLE_COPY(RandomBias) 0180 }; 0181 0182 0183 /** An and bias 0184 The And Bias currently serves as a base class for all biases 0185 with children. 0186 */ 0187 class AMAROK_EXPORT AndBias : public AbstractBias 0188 { 0189 Q_OBJECT 0190 0191 public: 0192 /** Create a new And bias. 0193 */ 0194 AndBias(); 0195 ~AndBias() override; 0196 0197 void fromXml( QXmlStreamReader *reader ) override; 0198 void toXml( QXmlStreamWriter *writer ) const override; 0199 0200 static QString sName(); 0201 QString name() const override; 0202 QString toString() const override; 0203 0204 QWidget* widget( QWidget* parent = nullptr ) override; 0205 void paintOperator( QPainter* painter, const QRect &rect, Dynamic::AbstractBias* bias ) override; 0206 0207 TrackSet matchingTracks( const Meta::TrackList& playlist, 0208 int contextCount, int finalCount, 0209 const TrackCollectionPtr &universe ) const override; 0210 0211 bool trackMatches( int position, 0212 const Meta::TrackList& playlist, 0213 int contextCount ) const override; 0214 0215 /** Appends a bias to this bias. 0216 This object will take ownership of the bias and free it when destroyed. 0217 */ 0218 virtual void appendBias( const Dynamic::BiasPtr &bias ); 0219 virtual void moveBias( int from, int to ); 0220 0221 BiasList biases() const 0222 { return m_biases; } 0223 0224 Q_SIGNALS: 0225 void biasAppended( Dynamic::BiasPtr bias ); 0226 void biasRemoved( int pos ); 0227 void biasMoved( int from, int to ); 0228 0229 public Q_SLOTS: 0230 void invalidate() override; 0231 0232 protected Q_SLOTS: 0233 virtual void resultReceived( const Dynamic::TrackSet &tracks ); 0234 virtual void biasReplaced( const Dynamic::BiasPtr &oldBias, const Dynamic::BiasPtr &newBias ); 0235 virtual void biasChanged( const Dynamic::BiasPtr &bias ); 0236 0237 protected: 0238 BiasList m_biases; 0239 0240 mutable TrackSet m_tracks; 0241 mutable int m_outstandingMatches; 0242 0243 private: 0244 Q_DISABLE_COPY(AndBias) 0245 }; 0246 0247 class AMAROK_EXPORT OrBias : public AndBias 0248 { 0249 Q_OBJECT 0250 0251 public: 0252 OrBias(); 0253 0254 static QString sName(); 0255 QString name() const override; 0256 QString toString() const override; 0257 0258 void paintOperator( QPainter* painter, const QRect &rect, Dynamic::AbstractBias* bias ) override; 0259 0260 TrackSet matchingTracks( const Meta::TrackList& playlist, 0261 int contextCount, int finalCount, 0262 const TrackCollectionPtr &universe ) const override; 0263 0264 bool trackMatches( int position, 0265 const Meta::TrackList& playlist, 0266 int contextCount ) const override; 0267 0268 protected Q_SLOTS: 0269 void resultReceived( const Dynamic::TrackSet &tracks ) override; 0270 0271 private: 0272 Q_DISABLE_COPY(OrBias) 0273 }; 0274 0275 } 0276 0277 Q_DECLARE_METATYPE( Dynamic::BiasPtr ) 0278 0279 #endif