File indexing completed on 2024-05-19 04:49:27
0001 /**************************************************************************************** 0002 * Copyright (c) 2007-2008 Maximilian Kossick <maximilian.kossick@googlemail.com> * 0003 * Copyright (c) 2008 Jason A. Donenfeld <Jason@zx2c4.com> * 0004 * Copyright (c) 2010 Casey Link <unnamedrambler@gmail.com> * 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) any later * 0009 * version. * 0010 * * 0011 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0013 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License along with * 0016 * this program. If not, see <http://www.gnu.org/licenses/>. * 0017 ****************************************************************************************/ 0018 0019 #ifndef AMAROK_COLLECTIONLOCATION_H 0020 #define AMAROK_COLLECTIONLOCATION_H 0021 0022 #include "core/amarokcore_export.h" 0023 #include "core/meta/forward_declarations.h" 0024 #include "core/transcoding/TranscodingConfiguration.h" 0025 0026 #include <QList> 0027 #include <QObject> 0028 0029 #include <QUrl> 0030 0031 namespace Collections { 0032 class Collection; 0033 class QueryMaker; 0034 0035 /** 0036 This base class defines the methods necessary to allow the copying and moving 0037 of tracks between different collections in a generic way. 0038 0039 This class should be used as follows in client code: 0040 - select a source and a destination CollectionLocation 0041 - call prepareCopy or prepareMove on the source CollectionLocation 0042 - forget about the rest of the workflow 0043 0044 Implementations which are writable must reimplement the following methods 0045 - prettyLocation() 0046 - isWritable() 0047 - remove( Meta::Track ) 0048 - copyUrlsToCollection( QMap<Meta::TrackPtr, QUrl> ) 0049 0050 Writable collections that are also organizable should reimplement isOrganizable(). 0051 Organizable means that the user is able to decide (to varying degrees, the details 0052 depend on the actual collection) where the files are stored in the filesystem (or some 0053 kind of VFS). An example would be the local collection, where the user can select the directory 0054 structure that Amarok uses to store the files. An example for a writable collection that is not 0055 organizable are ipods, where the user has no control about the actual location of the music files 0056 (they are automatically stored in a not human-readable form). 0057 0058 Implementations which are only readable can reimplement getKIOCopyableUrls( Meta::TrackList ) 0059 if it is necessary, but can use the default implementations if possible. 0060 0061 Implementations that have a string expressable location(s), such as a URL or path on disk 0062 should reimplement actualLocation(). 0063 0064 Implementations that need additional information provided by the user have to implement 0065 showSourceDialog() and showDestinationDialog(), depending on whether the information is required 0066 in the source, the destination, or both. 0067 0068 The methods will be called in the following order: 0069 startWorkflow (source) 0070 showSourceDialog (source) (reimplementable) 0071 slotShowSourceDialogDone (source) 0072 slotPrepareOperation (destination) 0073 showDestinationDialog (destination) (reimplementable) 0074 slotShowDestinationDialogDone (destination) 0075 slotOperationPrepared (source) 0076 getKIOCopyableUrls (source) (reimplementable) 0077 slotGetKIOCopyableUrlsDone (source) 0078 slotStartCopy (destination) 0079 copyUrlsToCollection (destination) (reimplementable) 0080 slotCopyOperationFinished (destination) 0081 slotFinishCopy (source) 0082 0083 To provide removal ability, it is required to reimplement removeUrlsFromCollection, 0084 and this function must call slotRemoveOperationFinished() when it is done. Optionally, 0085 showRemoveDialog can be reimplemented to customize the warning displayed before a removal, 0086 and this function must call slotShowRemoveDialogDone when finished. 0087 0088 The methods for remove will be called in the following order: 0089 startRemoveWorkflow 0090 showRemoveDialog (reimplementable) 0091 slotShowRemoveDialogDone 0092 slotStartRemove 0093 removeUrlsFromCollection (reimplementable) 0094 slotRemoveOperationFinished 0095 slotFinishRemove 0096 */ 0097 0098 class AMAROKCORE_EXPORT CollectionLocation : public QObject 0099 { 0100 Q_OBJECT 0101 0102 //testing only do not use these properties in anything but tests 0103 Q_PROPERTY( bool removeSources 0104 READ getRemoveSources 0105 WRITE setRemoveSources 0106 DESIGNABLE false 0107 SCRIPTABLE false ) 0108 0109 public: 0110 CollectionLocation(); 0111 explicit CollectionLocation( Collections::Collection *parentCollection ); 0112 ~CollectionLocation() override; 0113 0114 /** 0115 Returns a pointer to the collection location's corresponding collection. 0116 @return a pointer to the collection location's corresponding collection 0117 */ 0118 virtual Collections::Collection *collection() const; 0119 0120 /** 0121 a displayable string representation of the collection location. use the return 0122 value of this method to display the collection location to the user. 0123 @return a string representation of the collection location 0124 */ 0125 virtual QString prettyLocation() const; 0126 0127 /** 0128 Returns a list of machine usable strings representing the collection location. 0129 For example, a local collection would return a list of paths where tracks are 0130 stored, while an Ampache collection would return a list with one string 0131 containing the URL of an ampache server. An iPod collection and a MTP device 0132 collection are examples of collections that do not need to reimplement this method. 0133 */ 0134 virtual QStringList actualLocation() const; 0135 0136 /** 0137 Returns whether the collection location is writable or not. For example, a 0138 local collection or an ipod collection would return true, a daap collection 0139 or a service collection false. The value returned by this method indicates 0140 if it is possible to copy tracks to the collection, and if it is generally 0141 possible to remove/delete files from the collection. 0142 @return @c true if the collection location is writable 0143 @return @c false if the collection location is not writable 0144 */ 0145 virtual bool isWritable() const; 0146 0147 /** 0148 Returns whether the collection is organizable or not. Organizable collections 0149 allow move operations where the source and destination collection are the same. 0150 @return @c true if the collection location is organizable, false otherwise 0151 */ 0152 virtual bool isOrganizable() const; 0153 0154 /** 0155 Convenience method for copying a single track. 0156 @see prepareCopy( Meta::TrackList, CollectionLocation* ) 0157 */ 0158 void prepareCopy( const Meta::TrackPtr &track, CollectionLocation *destination ); 0159 /** 0160 Schedule copying of @p tracks to collection location @p destination. 0161 This method takes ownership of the @p destination, you may not reference 0162 or delete it after this call. This method returns immediately and the actual 0163 copy is performed in the event loop and/or another thread. 0164 @param tracks tracks 0165 @param destination the collection location destination 0166 */ 0167 void prepareCopy( const Meta::TrackList &tracks, CollectionLocation *destination ); 0168 /** 0169 Convenience method for copying tracks based on QueryMaker results, 0170 takes ownership of the @p qm. 0171 @param qm the QueryMaker query 0172 @param destination the collection destination 0173 @see prepareCopy( Meta::TrackList, CollectionLocation* ) 0174 */ 0175 void prepareCopy( Collections::QueryMaker *qm, CollectionLocation *destination ); 0176 0177 /** 0178 * Convenience method for moving a single track. 0179 * @see prepareMove( Meta::TrackList, CollectionLocation* ) 0180 */ 0181 void prepareMove( const Meta::TrackPtr &track, CollectionLocation *destination ); 0182 /** 0183 Schedule moving of @p tracks to collection location @p destination. 0184 This method takes ownership of the @p destination, you may not reference 0185 or delete it after this call. This method returns immediately and the actual 0186 move is performed in the event loop and/or another thread. 0187 @param tracks tracks 0188 @param destination the collection location destination 0189 */ 0190 void prepareMove( const Meta::TrackList &tracks, CollectionLocation *destination ); 0191 /** 0192 Convenience method for moving tracks based on QueryMaker results, 0193 takes ownership of the @p qm. 0194 @param qm the QueryMaker query 0195 @param destination the collection destination 0196 @see prepareMove( Meta::TrackList, CollectionLocation* ) 0197 */ 0198 void prepareMove( Collections::QueryMaker *qm, CollectionLocation *destination ); 0199 0200 /** 0201 Starts workflow for removing tracks. 0202 */ 0203 void prepareRemove( const Meta::TrackList &tracks ); 0204 /** 0205 Convenience method for removing tracks selected by QueryMaker, 0206 takes ownership of the @p qm. 0207 @param qm the QueryMaker query 0208 @see prepareRemove( Meta::TrackList ) 0209 */ 0210 void prepareRemove( Collections::QueryMaker *qm ); 0211 0212 /** 0213 * Adds or merges a track to the collection (not to the disk) 0214 * Inserts a set of TrackPtrs directly into the database without needing to actual move any files 0215 * @param track track 0216 * @param path path 0217 * This is a hack required by the DatabaseImporter 0218 * TODO: Remove this hack 0219 * @return true if the database entry was inserted, false otherwise 0220 */ 0221 virtual bool insert( const Meta::TrackPtr &track, const QString &path ); 0222 0223 /** 0224 explicitly inform the source collection of successful transfer. 0225 The source collection will only remove files (if necessary) 0226 for which this method was called. 0227 @param track track 0228 */ 0229 void transferSuccessful( const Meta::TrackPtr &track ); 0230 0231 /** 0232 * tells the source location that an error occurred during the transfer of the file 0233 * @param track track 0234 * @param error error 0235 */ 0236 virtual void transferError( const Meta::TrackPtr &track, const QString &error ); 0237 0238 Q_SIGNALS: 0239 void startCopy( const QMap<Meta::TrackPtr, QUrl> &sources, 0240 const Transcoding::Configuration & ); 0241 void finishCopy(); 0242 void startRemove(); 0243 void finishRemove(); 0244 void prepareOperation( const Meta::TrackList &tracks, bool removeSources, 0245 const Transcoding::Configuration & ); 0246 void operationPrepared(); 0247 void aborted(); 0248 0249 protected: 0250 /** 0251 * aborts the workflow 0252 */ 0253 void abort(); 0254 0255 /** 0256 * allows the destination location to access the source CollectionLocation. 0257 * note: subclasses do not take ownership of the pointer 0258 */ 0259 CollectionLocation* source() const; 0260 0261 /** 0262 * allows the source location to access the destination CollectionLocation. 0263 * Pointer may be null! 0264 * note: subclasses do not take ownership of the pointer 0265 */ 0266 CollectionLocation* destination() const; 0267 0268 /** 0269 this method is called on the source location, and should return a list of urls 0270 which the destination location can copy using KIO. You must call 0271 slotGetKIOCopyableUrlsDone( QMap<Meta::TrackPtr, QUrl> ) after retrieving the 0272 urls. The order of urls passed to that method has to be the same as the order 0273 of the tracks passed to this method. 0274 */ 0275 virtual void getKIOCopyableUrls( const Meta::TrackList &tracks ); 0276 /** 0277 this method is called on the destination. reimplement it if your implementation 0278 is writable. You must call slotCopyOperationFinished() when you are done copying 0279 the files. 0280 0281 Before calling slotCopyOperationFinished(), you should call 0282 source()->transferSuccessful() for every source track that was for sure 0283 successfully copied to destination collection. Only such marked tracks are 0284 then removed in case of a "move" action. 0285 */ 0286 virtual void copyUrlsToCollection( const QMap<Meta::TrackPtr, QUrl> &sources, 0287 const Transcoding::Configuration &configuration ); 0288 0289 /** 0290 this method is called on the collection you want to remove tracks from. it must 0291 be reimplemented if your collection is writable and you wish to implement 0292 removing tracks. You must call slotRemoveOperationFinished() when you are done 0293 removing the files. 0294 0295 Before calling slotRemoveOperationFinished(), you should call transferSuccessful() 0296 for every track that was successfully deleted. CollectionLocation then scans 0297 directories of such tracks and allows user to remove empty ones. 0298 */ 0299 virtual void removeUrlsFromCollection( const Meta::TrackList &sources ); 0300 0301 /** 0302 * this method is called on the source. It allows the source CollectionLocation to 0303 * show a dialog. Classes that reimplement this method must call 0304 * slotShowSourceDialogDone() after they have acquired all necessary information from the user. 0305 * 0306 * Default implementation calls getDestinationTranscodingConfig() which may ask 0307 * user. If you reimplement this you may (or not) call this base method instead 0308 * of calling slotShowDestinationDialogDone() to support transcoding. 0309 */ 0310 virtual void showSourceDialog( const Meta::TrackList &tracks, bool removeSources ); 0311 0312 /** 0313 * Get transcoding configuration to use when transferring tracks to destination. 0314 * If destination collection doesn't support transcoding, JUST_COPY configuration 0315 * is returned, otherwise preferred configuration is read or user is asked. 0316 * Returns invalid configuration in case user has hit cancel or closed the dialog. 0317 * 0318 * This method is meant to be called by source collection. 0319 */ 0320 virtual Transcoding::Configuration getDestinationTranscodingConfig(); 0321 0322 /** 0323 * This method is called on the destination. It allows the destination 0324 * CollectionLocation to show a dialog. Classes that reimplement this method 0325 * must call slotShowDestinationDialogDone() after they have acquired all necessary 0326 * information from the user. 0327 * 0328 * Default implementation calls setGoingToRemoveSources( removeSources ) so that 0329 * isGoingToRemoveSources() is available on destination, too and then calls 0330 * slotShowDestinationDialogDone() 0331 */ 0332 virtual void showDestinationDialog( const Meta::TrackList &tracks, 0333 bool removeSources, 0334 const Transcoding::Configuration &configuration ); 0335 0336 /** 0337 * this methods allows the collection to show a warning dialog before tracks are removed, 0338 * rather than using the default provided. Classes that reimplement this method must call 0339 * slotShowRemoveDialogDone() after they are finished. 0340 */ 0341 0342 virtual void showRemoveDialog( const Meta::TrackList &tracks ); 0343 0344 /** 0345 * Get nice localised string describing the current operation based on transcoding 0346 * configuration and isGoingToRemoveSources(); meant to be called by destination 0347 * collection. 0348 * 0349 * @return "Copy Tracks", "Transcode and Organize Tracks" etc. 0350 */ 0351 QString operationText( const Transcoding::Configuration &configuration ); 0352 0353 /** 0354 * Get nice localised string that can be used as progress bar text for the current 0355 * operation; meant to be called by the destination collection. 0356 * 0357 * @param configuration the transcoding configuration 0358 * @param trackCount number of tracks in the transfer 0359 * @param destinationName pretty localised name of the destination collection; 0360 * prettyLocation() is used if the string is empty or not specified 0361 * 0362 * @return "Transcoding and moving <trackCount> tracks to <destinationName>" etc. 0363 */ 0364 QString operationInProgressText( const Transcoding::Configuration &configuration, 0365 int trackCount, QString destinationName = QString() ); 0366 0367 /** 0368 * Sets or gets whether some source files may be removed 0369 */ 0370 virtual bool isGoingToRemoveSources() const; 0371 virtual void setGoingToRemoveSources( bool removeSources ); 0372 0373 /** 0374 * Sets or gets whether to stifle the removal confirmation 0375 */ 0376 virtual bool isHidingRemoveConfirm() const; 0377 virtual void setHidingRemoveConfirm( bool hideRemoveConfirm ); 0378 0379 protected Q_SLOTS: 0380 /** 0381 * this slot has to be called from getKIOCopyableUrls( Meta::TrackList ) 0382 * Please note: the order of urls in the argument has to be the same as in the 0383 * tracklist 0384 */ 0385 void slotGetKIOCopyableUrlsDone( const QMap<Meta::TrackPtr, QUrl> &sources ); 0386 void slotCopyOperationFinished(); 0387 void slotRemoveOperationFinished(); 0388 void slotShowSourceDialogDone(); 0389 void slotShowRemoveDialogDone(); 0390 void slotShowDestinationDialogDone(); 0391 0392 private Q_SLOTS: 0393 void slotShowSourceDialog(); // trick to show dialog in next mainloop iteration 0394 void slotPrepareOperation( const Meta::TrackList &tracks, bool removeSources, 0395 const Transcoding::Configuration &configuration ); 0396 void slotOperationPrepared(); 0397 void slotStartCopy( const QMap<Meta::TrackPtr, QUrl> &sources, 0398 const Transcoding::Configuration &configuration ); 0399 void slotFinishCopy(); 0400 void slotStartRemove(); 0401 void slotFinishRemove(); 0402 void slotAborted(); 0403 void resultReady( const Meta::TrackList &tracks ); 0404 void queryDone(); 0405 0406 private: 0407 void setupConnections(); 0408 void setupRemoveConnections(); 0409 void startWorkflow( const Meta::TrackList &tracks, bool removeSources ); 0410 void startRemoveWorkflow( const Meta::TrackList &tracks ); 0411 void removeSourceTracks( const Meta::TrackList &tracks ); 0412 void setSource( CollectionLocation *source ); 0413 0414 //only used in the source CollectionLocation 0415 CollectionLocation *m_destination; 0416 //only used in destination CollectionLocation 0417 CollectionLocation *m_source; 0418 0419 Meta::TrackList getSourceTracks() const { return m_sourceTracks; } 0420 void setSourceTracks( const Meta::TrackList &tracks ) { m_sourceTracks = tracks; } 0421 Meta::TrackList m_sourceTracks; 0422 0423 Collections::Collection *m_parentCollection; 0424 0425 bool getRemoveSources() const { return m_removeSources; } 0426 void setRemoveSources( bool removeSources ) { m_removeSources = removeSources; } 0427 bool m_removeSources; 0428 bool m_isRemoveAction; 0429 bool m_noRemoveConfirmation; 0430 Transcoding::Configuration m_transcodingConfiguration; 0431 //used by the source collection to store the tracks that were successfully 0432 //copied by the destination and can be removed as part of a move 0433 Meta::TrackList m_tracksSuccessfullyTransferred; 0434 QMap<Meta::TrackPtr, QString> m_tracksWithError; 0435 }; 0436 0437 } //namespace Collections 0438 0439 #endif