1 /****************************************************************************************
2  * Copyright (c) 2008 Daniel Jones <danielcjones@gmail.com>                             *
3  * Copyright (c) 2009-2010 Leo Franchi <lfranchi@kde.org>                               *
4  * Copyright (c) 2011 Ralf Engels <ralf-engels@gmx.de>                                  *
5  *                                                                                      *
6  * This program is free software; you can redistribute it and/or modify it under        *
7  * the terms of the GNU General Public License as published by the Free Software        *
8  * Foundation; either version 2 of the License, or (at your option) any later           *
9  * version.                                                                             *
10  *                                                                                      *
11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
13  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
14  *                                                                                      *
15  * You should have received a copy of the GNU General Public License along with         *
16  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
17  ****************************************************************************************/
18 
19 #ifndef DYNAMICMODEL_H
20 #define DYNAMICMODEL_H
21 
22 #include "Bias.h"
23 #include "DynamicPlaylist.h"
24 
25 #include "amarok_export.h" // we are exporting it for the tests
26 
27 #include <QAbstractItemModel>
28 #include <QList>
29 #include <QString>
30 
31 class TestDynamicModel;
32 
33 namespace Dynamic {
34 
35 class BiasedPlaylist;
36 
37 class AMAROK_EXPORT DynamicModel : public QAbstractItemModel
38 {
39     Q_OBJECT
40     public:
41         // role used for the model
42         enum Roles
43         {
44             // WidgetRole = 0xf00d,
45             PlaylistRole = 0xf00e,
46             BiasRole = 0xf00f,
47 
48             BiasPercentage = 0xf010, // for sub-biases underneath a part bias
49             BiasOperation = 0xf011   // for sub-biases underneath a and-bias
50         };
51 
52         static DynamicModel* instance();
53 
54         ~DynamicModel() override;
55 
56         // void changePlaylist( int i );
57 
58         /** Returns the currently active playlist.
59             Don't free this pointer
60         */
61         Dynamic::DynamicPlaylist* activePlaylist() const;
62         int activePlaylistIndex() const;
63 
64         /** Find the playlist with name, make it active and return it */
65         Dynamic::DynamicPlaylist* setActivePlaylist( int );
66 
67         int playlistIndex( Dynamic::DynamicPlaylist* playlist ) const;
68 
69         /** Inserts a playlist at the given index.
70             If the playlist is already in the model it will be moved
71             to the position
72         */
73         QModelIndex insertPlaylist( int index, Dynamic::DynamicPlaylist* playlist );
74 
75         /** Inserts a bias at the given index.
76             The bias must not be part of a model. When in doubt call bias->replace(BiasPtr())
77             to remove the bias from it's current position.
78         */
79         QModelIndex insertBias( int row, const QModelIndex &parentIndex, const Dynamic::BiasPtr &bias );
80 
81         Qt::DropActions supportedDropActions() const override;
82 
83         // --- QAbstractItemModel functions ---
84         QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override;
85         bool setData( const QModelIndex& index, const QVariant& value, int role = Qt::EditRole ) override;
86         Qt::ItemFlags flags( const QModelIndex& index ) const override;
87         QModelIndex index( int row, int column, const QModelIndex& parent = QModelIndex() ) const override;
88         QModelIndex parent(const QModelIndex& index) const override;
89         int rowCount( const QModelIndex& parent = QModelIndex() ) const override;
90         int columnCount( const QModelIndex& parent = QModelIndex() ) const override;
91 
92         QStringList mimeTypes() const override;
93         QMimeData* mimeData(const QModelIndexList &indexes) const override;
94         bool dropMimeData(const QMimeData *data,
95                           Qt::DropAction action,
96                           int row, int column, const QModelIndex &parent) override;
97 
98         // ---
99 
100         /** Returns the index for the bias
101             @return Returns an invalid index if the bias is not in the model.
102         */
103         QModelIndex index( const Dynamic::BiasPtr &bias ) const;
104 
105         /** Returns the index for the playlist
106             @return Returns an invalid index if the playlist is not in the model.
107         */
108         QModelIndex index( Dynamic::DynamicPlaylist* playlist ) const;
109 
110         /** Returns a representation of the whole model for debugging */
111         QString toString();
112 
113     Q_SIGNALS:
114         void activeChanged( int index ); // active row changed
115 
116     public Q_SLOTS:
117         /** Saves all playlists to disk */
118         void savePlaylists();
119 
120         /** Loads the last saved playlists form disk */
121         void loadPlaylists();
122 
123         /** Removes the playlist or bias at the given index. */
124         void removeAt( const QModelIndex& index );
125 
126         /** Clone the playlist or bias at the given index. */
127         QModelIndex cloneAt( const QModelIndex& index );
128 
129         /** Creates a new playlist and returns the index to it. */
130         QModelIndex newPlaylist();
131 
132     private:
133         // two functions to search for parents
134         QModelIndex parent( int row, Dynamic::BiasedPlaylist* list, const Dynamic::BiasPtr &bias ) const;
135         QModelIndex parent( int row, const Dynamic::BiasPtr &parent, const Dynamic::BiasPtr &bias ) const;
136 
137         /** Writes the index to the data stream */
138         void serializeIndex( QDataStream *stream, const QModelIndex& index ) const;
139 
140         /** Gets an index from the data stream */
141         QModelIndex unserializeIndex( QDataStream *stream ) const;
142 
143         Dynamic::BiasedPlaylist* cloneList( Dynamic::BiasedPlaylist* list );
144         Dynamic::BiasPtr cloneBias( Dynamic::BiasPtr bias );
145 
146         // -- model change signals ---
147         // The following functions are called by the biases to
148         // notify the model about changes.
149 
150         void playlistChanged( Dynamic::DynamicPlaylist* playlist );
151         void biasChanged( const Dynamic::BiasPtr &bias );
152 
153         void beginRemoveBias( Dynamic::BiasedPlaylist* parent );
154         void beginRemoveBias( const Dynamic::BiasPtr &parent, int index );
155         void endRemoveBias();
156 
157         void beginInsertBias( Dynamic::BiasedPlaylist* parent );
158         void beginInsertBias( const Dynamic::BiasPtr &parent, int index );
159         void endInsertBias();
160 
161         void beginMoveBias( const Dynamic::BiasPtr &parent, int from, int to );
162         void endMoveBias();
163 
164         // ----
165 
166         bool savePlaylists( const QString &filename );
167         bool loadPlaylists( const QString &filename );
168         void initPlaylists();
169 
170         DynamicModel(QObject* parent = nullptr);
171         static DynamicModel* s_instance;
172 
173         int m_activePlaylistIndex;
174 
175         /** Contains all the dynamic playlists.  */
176         QList<Dynamic::DynamicPlaylist*> m_playlists;
177 
178         friend class Dynamic::DynamicPlaylist;
179         friend class Dynamic::BiasedPlaylist;
180         friend class Dynamic::AndBias;
181 
182         friend class ::TestDynamicModel;
183 };
184 
185 }
186 
187 #endif
188 
189