File indexing completed on 2024-05-05 04:48:42

0001 /****************************************************************************************
0002  * Copyright (c) 2007 Ian Monroe <ian@monroe.nu>                                        *
0003  * Copyright (c) 2008 Seb Ruiz <ruiz@kde.org>                                           *
0004  * Copyright (c) 2008 Soren Harward <stharward@gmail.com>                               *
0005  * Copyright (c) 2009,2010 Téo Mrnjavac <teo@kde.org>                                   *
0006  *                                                                                      *
0007  * This program is free software; you can redistribute it and/or modify it under        *
0008  * the terms of the GNU General Public License as published by the Free Software        *
0009  * Foundation; either version 2 of the License, or (at your option) version 3 or        *
0010  * any later version accepted by the membership of KDE e.V. (or its successor approved  *
0011  * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of  *
0012  * version 3 of the license.                                                            *
0013  *                                                                                      *
0014  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0015  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0016  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0017  *                                                                                      *
0018  * You should have received a copy of the GNU General Public License along with         *
0019  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0020  ****************************************************************************************/
0021 
0022 #ifndef AMAROK_PLAYLISTCONTROLLER_H
0023 #define AMAROK_PLAYLISTCONTROLLER_H
0024 
0025 #include "UndoCommands.h"
0026 #include "amarok_export.h"
0027 #include "core/meta/forward_declarations.h"
0028 #include "core/playlists/Playlist.h"
0029 
0030 #include <QObject>
0031 
0032 class QUndoStack;
0033 
0034 namespace Playlist
0035 {
0036 class AbstractModel;
0037 
0038 /**
0039  * No options means: append at the end of the playlist (without touching playing
0040  * state)
0041  */
0042 enum AddOption
0043 {
0044     Replace = 1, ///< replaces the playlist instead of default appending (or queueing)
0045     Queue = 2, ///< inserts media into the queue after the currentTrack instead of default
0046                ///  appending to the end of the playlist
0047     PrependToQueue = Queue | 4, ///< prepends media to the queue (after current track), implies Queue
0048     DirectPlay = PrependToQueue | 8, ///< start playback of the first item in the list, implies PrependToQueue
0049     RemotePlaylistsAreStreams = 16, ///< treat remote urls pointing to playlists as streams.
0050                                     ///  only has sense for methods that accept urls or playlists
0051     StartPlayIfConfigured = 32, ///< start playing the first added track if Amarok is
0052                                 ///  configured so and nothing else is already playing
0053 
0054     // following are "consistency convenience enums" so that it is easy for us to make the
0055     // bahaviour of similarly-looking UI elements the same. These enums are the preferred
0056     // ones on calling sites. Feel free to add a new one if you find another UI element
0057     // that appears on multiple places. Prefix these with On*.
0058     OnDoubleClickOnSelectedItems = StartPlayIfConfigured,
0059     OnMiddleClickOnSelectedItems = DirectPlay,
0060     OnReturnPressedOnSelectedItems = StartPlayIfConfigured, // append, should be kept same as double-click
0061 
0062     OnPlayMediaAction = DirectPlay,
0063     OnAppendToPlaylistAction = 0, // double-click is always available, so don't add StartPlayIfConfigured here
0064     OnReplacePlaylistAction = Replace | StartPlayIfConfigured,
0065     OnQueueToPlaylistAction = Queue | StartPlayIfConfigured,
0066 };
0067 Q_DECLARE_FLAGS( AddOptions, AddOption )
0068 
0069 /** The Playlist::Controller allows to add, remove or otherwise change tracks to the playlist.
0070     Instead of directly talking to The::Playlist or PlaylistModelStack this object
0071     should be used. It will take care of correctly placing the tracks (even
0072     if the playlist is sorted) and will handle undo and redo operations.
0073 */
0074 class AMAROK_EXPORT Controller : public QObject
0075 {
0076     Q_OBJECT
0077 
0078 public:
0079     /**
0080      * Accessor for the singleton pattern.
0081      * @return a pointer to the only instance of Playlist::Controller.
0082      */
0083     static Controller *instance();
0084 
0085     /**
0086      * Singleton destructor.
0087      */
0088     static void destroy();
0089 
0090 public Q_SLOTS:
0091     /**
0092      * Handles the insertion of one single track into the playlist, considering a set of
0093      * options that handle the specifics of the operation.
0094      * @param track the track to be inserted.
0095      * @param options the set of options to be applied to the operation.
0096      * @see enum AddOptions.
0097      */
0098     void insertOptioned( Meta::TrackPtr track, AddOptions options = {} );
0099 
0100     /**
0101      * Handles the insertion of one or more tracks into the playlist, considering a set of
0102      * options that handle the specifics of the operation.
0103      * @param list the list of tracks to be inserted.
0104      * @param options the set of options to be applied to the operation.
0105      * @see enum AddOptions.
0106      */
0107     void insertOptioned( Meta::TrackList list, AddOptions options = {} );
0108     void insertOptioned( Playlists::PlaylistPtr playlist, AddOptions options = {} );
0109     void insertOptioned( Playlists::PlaylistList list, AddOptions options = {} );
0110     void insertOptioned( const QUrl &url, AddOptions options = {} );
0111     void insertOptioned( QList<QUrl> &urls, AddOptions options = {} );
0112 
0113     /**
0114      * Handles the insertion of one or more tracks into the playlist on a specific row.
0115      * The rows are always considered as topmost playlist model rows.
0116      * @param topModelRow the insertion row in the topmost model.
0117      * @param track the track to be inserted.
0118      */
0119     void insertTrack( int topModelRow, Meta::TrackPtr track );
0120     void insertTracks( int topModelRow, Meta::TrackList list );
0121     void insertPlaylist( int topModelRow, Playlists::PlaylistPtr playlist );
0122     void insertPlaylists( int topModelRow, Playlists::PlaylistList playlists );
0123     void insertUrls( int topModelRow, QList<QUrl> &urls );
0124 
0125     /**
0126      * Handles the removal of a single track from the playlist.
0127      * The rows are considered as topmost playlist model rows.
0128      * @param topModelRow the row to remove in the topmost model.
0129      */
0130     void removeRow( int topModelRow );
0131 
0132     /**
0133      * Handles the removal of tracks from the playlist.
0134      * The rows are considered as topmost playlist model rows.
0135      * @param topModelRow the row to remove in the topmost model.
0136      * @param count the number of rows to remove.
0137      */
0138     void removeRows( int topModelRow, int count );
0139 
0140     /**
0141      * Handles the removal of a list of tracks from the playlist.
0142      * The rows are considered as topmost playlist model rows.
0143      * @param topModelRows the list of row numbers to remove.
0144      */
0145     void removeRows( QList<int>& topModelRows );
0146 
0147     /**
0148      * Removes unplayable and duplicate entries in the topmost playlist model, i.e.
0149      * respects playlist filters.
0150      */
0151     void removeDeadAndDuplicates();
0152 
0153     /**
0154      * Moves a track from one row to another in the playlist.
0155      * @param topModelFrom the row containing the track that is about to be moved.
0156      * @param topModelTo the target row where the track should be moved.
0157      */
0158     void moveRow( int topModelFrom, int topModelTo );
0159 
0160     /**
0161      * Moves a list of tracks to a specified row in the playlist.
0162      * This function returns the real starting location where the rows ended up.
0163      * For example, if you start with the following playlist:
0164      *   0 Alpha
0165      *   1 Bravo
0166      *   2 Charlie
0167      *   3 Delta
0168      *   4 Echo
0169      *   5 Foxtrot
0170      * and you call moveRows( [0,1,2], 4 ) then the playlist will end up with
0171      *   0 Delta
0172      *   1 Echo
0173      *   2 Alpha
0174      *   3 Bravo
0175      *   4 Charlie
0176      *   5 Foxtrot
0177      * and the function will return 2, because that's where the rows really ended up.
0178      * @param topModelFrom the list of rows containing the tracks that are about to be moved.
0179      * @param topModelTo the target row where the tracks should be moved.
0180      * @return the first row where the tracks ended up in the new list.
0181      */
0182     int moveRows( QList<int>& topModelFrom, int topModelTo );
0183 
0184     /**
0185      * Reorders tracks in the playlist. For each i, track at position
0186      * topModelFrom[i] is moved to the position topModelTo[i]. Note that when track
0187      * on position A is moved to the position B, the track from position B needs to
0188      * be moved as well. As a consequence, every track position appearing
0189      * in topModelFrom needs to appear in topModelTo.
0190      * @param topModelFrom the list containing positions of tracks to be moved
0191      * @param topModelTo the list containing positions the tracks should be moved to
0192      */
0193     void reorderRows( const QList<int> &topModelFrom, const QList<int> &topModelTo );
0194 
0195     void undo();
0196     void redo();
0197     void clear();
0198 
0199 Q_SIGNALS:
0200     void canRedoChanged( bool );
0201     void canUndoChanged( bool );
0202 
0203     void changed();
0204 
0205     void replacingPlaylist();
0206 
0207 private Q_SLOTS:
0208     void slotLoaderWithOptionsFinished( const Meta::TrackList &tracks );
0209     void slotLoaderWithRowFinished( const Meta::TrackList &tracks );
0210 
0211 private:
0212     Controller();
0213 
0214     ~Controller() override;
0215 
0216     static Controller *s_instance;       //!< Instance member.
0217 
0218     /**
0219      * Converts a row number in 'm_topModel' to a row in 'm_bottomModel', for purposes of
0220      * insert. This is not useful for remove/move.
0221      */
0222     int insertionTopRowToBottom( int topModelRow );
0223 
0224     /**
0225      * Handles the insertion of a list of tracks into the playlist on a specific row.
0226      * The row number is always in the *bottom* playlist model, in contrast to most other
0227      * functions in this class.
0228      * @param bottomModelRow the insertion row in the bottom model.
0229      * @param tl the Meta::TrackList to be inserted.
0230      */
0231     void insertionHelper( int bottomModelRow, Meta::TrackList& tl );
0232 
0233     AbstractModel* m_topModel;
0234     AbstractModel* m_bottomModel;
0235 
0236     QUndoStack* m_undoStack;
0237 };
0238 }
0239 
0240 Q_DECLARE_OPERATORS_FOR_FLAGS( Playlist::AddOptions )
0241 Q_DECLARE_METATYPE( Playlist::AddOptions )
0242 
0243 namespace The
0244 {
0245     AMAROK_EXPORT Playlist::Controller* playlistController();
0246 }
0247 
0248 #endif