1 /****************************************************************************************
2 * Copyright (c) 2007 Ian Monroe <ian@monroe.nu> *
3 * Copyright (c) 2008 Seb Ruiz <ruiz@kde.org> *
4 * Copyright (c) 2008 Soren Harward <stharward@gmail.com> *
5 * Copyright (c) 2009,2010 Téo Mrnjavac <teo@kde.org> *
6 * *
7 * This program is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU General Public License as published by the Free Software *
9 * Foundation; either version 2 of the License, or (at your option) version 3 or *
10 * any later version accepted by the membership of KDE e.V. (or its successor approved *
11 * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of *
12 * version 3 of the license. *
13 * *
14 * This program is distributed in the hope that it will be useful, but WITHOUT ANY *
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
16 * PARTICULAR PURPOSE. See the GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License along with *
19 * this program. If not, see <http://www.gnu.org/licenses/>. *
20 ****************************************************************************************/
21
22 #ifndef AMAROK_PLAYLISTCONTROLLER_H
23 #define AMAROK_PLAYLISTCONTROLLER_H
24
25 #include "UndoCommands.h"
26 #include "amarok_export.h"
27 #include "core/meta/forward_declarations.h"
28 #include "core/playlists/Playlist.h"
29
30 #include <QObject>
31
32 class QUndoStack;
33
34 namespace Playlist
35 {
36 class AbstractModel;
37
38 /**
39 * No options means: append at the end of the playlist (without touching playing
40 * state)
41 */
42 enum AddOption
43 {
44 Replace = 1, ///< replaces the playlist instead of default appending (or queueing)
45 Queue = 2, ///< inserts media into the queue after the currentTrack instead of default
46 /// appending to the end of the playlist
47 PrependToQueue = Queue | 4, ///< prepends media to the queue (after current track), implies Queue
48 DirectPlay = PrependToQueue | 8, ///< start playback of the first item in the list, implies PrependToQueue
49 RemotePlaylistsAreStreams = 16, ///< treat remote urls pointing to playlists as streams.
50 /// only has sense for methods that accept urls or playlists
51 StartPlayIfConfigured = 32, ///< start playing the first added track if Amarok is
52 /// configured so and nothing else is already playing
53
54 // following are "consistency convenience enums" so that it is easy for us to make the
55 // bahaviour of similarly-looking UI elements the same. These enums are the preferred
56 // ones on calling sites. Feel free to add a new one if you find another UI element
57 // that appears on multiple places. Prefix these with On*.
58 OnDoubleClickOnSelectedItems = StartPlayIfConfigured,
59 OnMiddleClickOnSelectedItems = DirectPlay,
60 OnReturnPressedOnSelectedItems = StartPlayIfConfigured, // append, should be kept same as double-click
61
62 OnPlayMediaAction = DirectPlay,
63 OnAppendToPlaylistAction = 0, // double-click is always available, so don't add StartPlayIfConfigured here
64 OnReplacePlaylistAction = Replace | StartPlayIfConfigured,
65 OnQueueToPlaylistAction = Queue | StartPlayIfConfigured,
66 };
Q_DECLARE_FLAGS(AddOptions,AddOption)67 Q_DECLARE_FLAGS( AddOptions, AddOption )
68
69 /** The Playlist::Controller allows to add, remove or otherwise change tracks to the playlist.
70 Instead of directly talking to The::Playlist or PlaylistModelStack this object
71 should be used. It will take care of correctly placing the tracks (even
72 if the playlist is sorted) and will handle undo and redo operations.
73 */
74 class AMAROK_EXPORT Controller : public QObject
75 {
76 Q_OBJECT
77
78 public:
79 /**
80 * Accessor for the singleton pattern.
81 * @return a pointer to the only instance of Playlist::Controller.
82 */
83 static Controller *instance();
84
85 /**
86 * Singleton destructor.
87 */
88 static void destroy();
89
90 public Q_SLOTS:
91 /**
92 * Handles the insertion of one single track into the playlist, considering a set of
93 * options that handle the specifics of the operation.
94 * @param track the track to be inserted.
95 * @param options the set of options to be applied to the operation.
96 * @see enum AddOptions.
97 */
98 void insertOptioned( Meta::TrackPtr track, AddOptions options = 0 );
99
100 /**
101 * Handles the insertion of one or more tracks into the playlist, considering a set of
102 * options that handle the specifics of the operation.
103 * @param list the list of tracks to be inserted.
104 * @param options the set of options to be applied to the operation.
105 * @see enum AddOptions.
106 */
107 void insertOptioned( Meta::TrackList list, AddOptions options = 0 );
108 void insertOptioned( Playlists::PlaylistPtr playlist, AddOptions options = 0 );
109 void insertOptioned( Playlists::PlaylistList list, AddOptions options = 0 );
110 void insertOptioned( const QUrl &url, AddOptions options = 0 );
111 void insertOptioned( QList<QUrl> &urls, AddOptions options = 0 );
112
113 /**
114 * Handles the insertion of one or more tracks into the playlist on a specific row.
115 * The rows are always considered as topmost playlist model rows.
116 * @param topModelRow the insertion row in the topmost model.
117 * @param track the track to be inserted.
118 */
119 void insertTrack( int topModelRow, Meta::TrackPtr track );
120 void insertTracks( int topModelRow, Meta::TrackList list );
121 void insertPlaylist( int topModelRow, Playlists::PlaylistPtr playlist );
122 void insertPlaylists( int topModelRow, Playlists::PlaylistList playlists );
123 void insertUrls( int topModelRow, QList<QUrl> &urls );
124
125 /**
126 * Handles the removal of a single track from the playlist.
127 * The rows are considered as topmost playlist model rows.
128 * @param topModelRow the row to remove in the topmost model.
129 */
130 void removeRow( int topModelRow );
131
132 /**
133 * Handles the removal of tracks from the playlist.
134 * The rows are considered as topmost playlist model rows.
135 * @param topModelRow the row to remove in the topmost model.
136 * @param count the number of rows to remove.
137 */
138 void removeRows( int topModelRow, int count );
139
140 /**
141 * Handles the removal of a list of tracks from the playlist.
142 * The rows are considered as topmost playlist model rows.
143 * @param topModelRows the list of row numbers to remove.
144 */
145 void removeRows( QList<int>& topModelRows );
146
147 /**
148 * Removes unplayable and duplicate entries in the topmost playlist model, i.e.
149 * respects playlist filters.
150 */
151 void removeDeadAndDuplicates();
152
153 /**
154 * Moves a track from one row to another in the playlist.
155 * @param topModelFrom the row containing the track that is about to be moved.
156 * @param topModelTo the target row where the track should be moved.
157 */
158 void moveRow( int topModelFrom, int topModelTo );
159
160 /**
161 * Moves a list of tracks to a specified row in the playlist.
162 * This function returns the real starting location where the rows ended up.
163 * For example, if you start with the following playlist:
164 * 0 Alpha
165 * 1 Bravo
166 * 2 Charlie
167 * 3 Delta
168 * 4 Echo
169 * 5 Foxtrot
170 * and you call moveRows( [0,1,2], 4 ) then the playlist will end up with
171 * 0 Delta
172 * 1 Echo
173 * 2 Alpha
174 * 3 Bravo
175 * 4 Charlie
176 * 5 Foxtrot
177 * and the function will return 2, because that's where the rows really ended up.
178 * @param topModelFrom the list of rows containing the tracks that are about to be moved.
179 * @param topModelTo the target row where the tracks should be moved.
180 * @return the first row where the tracks ended up in the new list.
181 */
182 int moveRows( QList<int>& topModelFrom, int topModelTo );
183
184 /**
185 * Reorders tracks in the playlist. For each i, track at position
186 * topModelFrom[i] is moved to the position topModelTo[i]. Note that when track
187 * on position A is moved to the position B, the track from position B needs to
188 * be moved as well. As a consequence, every track position appearing
189 * in topModelFrom needs to appear in topModelTo.
190 * @param topModelFrom the list containing positions of tracks to be moved
191 * @param topModelTo the list containing positions the tracks should be moved to
192 */
193 void reorderRows( const QList<int> &topModelFrom, const QList<int> &topModelTo );
194
195 void undo();
196 void redo();
197 void clear();
198
199 Q_SIGNALS:
200 void canRedoChanged( bool );
201 void canUndoChanged( bool );
202
203 void changed();
204
205 void replacingPlaylist();
206
207 private Q_SLOTS:
208 void slotLoaderWithOptionsFinished( const Meta::TrackList &tracks );
209 void slotLoaderWithRowFinished( const Meta::TrackList &tracks );
210
211 private:
212 Controller();
213
214 ~Controller() override;
215
216 static Controller *s_instance; //!< Instance member.
217
218 /**
219 * Converts a row number in 'm_topModel' to a row in 'm_bottomModel', for purposes of
220 * insert. This is not useful for remove/move.
221 */
222 int insertionTopRowToBottom( int topModelRow );
223
224 /**
225 * Handles the insertion of a list of tracks into the playlist on a specific row.
226 * The row number is always in the *bottom* playlist model, in contrast to most other
227 * functions in this class.
228 * @param bottomModelRow the insertion row in the bottom model.
229 * @param tl the Meta::TrackList to be inserted.
230 */
231 void insertionHelper( int bottomModelRow, Meta::TrackList& tl );
232
233 AbstractModel* m_topModel;
234 AbstractModel* m_bottomModel;
235
236 QUndoStack* m_undoStack;
237 };
238 }
239
240 Q_DECLARE_OPERATORS_FOR_FLAGS( Playlist::AddOptions )
Q_DECLARE_METATYPE(Playlist::AddOptions)241 Q_DECLARE_METATYPE( Playlist::AddOptions )
242
243 namespace The
244 {
245 AMAROK_EXPORT Playlist::Controller* playlistController();
246 }
247
248 #endif
249