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