1 /**
2  * \file playlistcreator.h
3  * Playlist creator.
4  *
5  * \b Project: Kid3
6  * \author Urs Fleisch
7  * \date 21 Sep 2009
8  *
9  * Copyright (C) 2009-2018  Urs Fleisch
10  *
11  * This file is part of Kid3.
12  *
13  * Kid3 is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * Kid3 is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 #pragma once
28 
29 #include <QString>
30 #include <QMap>
31 #include <QScopedPointer>
32 #include "playlistconfig.h"
33 
34 class QModelIndex;
35 class QPersistentModelIndex;
36 class TaggedFile;
37 class ImportTrackData;
38 
39 /**
40  * Playlist creator.
41  * Creates playlists from added items according to a playlist configuration.
42  */
43 class PlaylistCreator {
44 public:
45   /**
46    * An item from the file list which can be added to a playlist.
47    * The item will only be added to the playlist if add() is called.
48    */
49   class Item {
50   public:
51     /**
52      * Constructor.
53      *
54      * @param index model index
55      * @param ctr  associated playlist creator
56      */
57     Item(const QModelIndex& index, PlaylistCreator& ctr);
58 
59     /**
60      * Destructor.
61      */
62     ~Item() = default;
63 
64     /**
65      * Check if item is a directory.
66      * @return true if item is directory.
67      */
isDir()68     bool isDir() const { return m_isDir; }
69 
70     /**
71      * Check if item is a tagged file.
72      * @return true if item is file.
73      */
isFile()74     bool isFile() const { return m_taggedFile != nullptr; }
75 
76     /**
77      * Get the directory of the item.
78      * @return directory path with trailing separator.
79      */
getDirName()80     QString getDirName() const { return m_dirName; }
81 
82     /**
83      * Add item to playlist.
84      * This operation will write a playlist if the configuration is set to write
85      * a playlist in every directory and a new directory is entered.
86      *
87      * @return true if ok.
88      */
89     bool add();
90 
91     /**
92      * Get additional information for item.
93      * @param info additional information is returned here
94      * @param duration the duration of the track is returned here
95      */
96     void getInfo(QString& info, unsigned long& duration);
97 
98   private:
99     /**
100      * Format string using tags and properties of item.
101      *
102      * @param format format string
103      *
104      * @return string with percent codes replaced.
105      */
106     QString formatString(const QString& format);
107 
108     PlaylistCreator& m_ctr;
109     TaggedFile* m_taggedFile;
110     QScopedPointer<ImportTrackData> m_trackData;
111     QString m_dirName;
112     bool m_isDir;
113   };
114 
115   /**
116    * Constructor.
117    *
118    * @param topLevelDir top-level directory of playlist
119    * @param cfg         playlist configuration
120    */
121   PlaylistCreator(const QString& topLevelDir, const PlaylistConfig& cfg);
122 
123   /**
124    * Write playlist containing added Entry elements.
125    *
126    * @return true if ok.
127    */
128   bool write();
129 
130   /**
131    * Write a playlist from a list of model indexes.
132    * @param playlistPath file path to be used for playlist
133    * @param indexes indexes in FileProxyModel
134    * @return true if ok.
135    */
136   bool write(const QString& playlistPath,
137              const QList<QPersistentModelIndex>& indexes);
138 
139   /**
140    * Read playlist from file
141    * @param playlistPath path to playlist file
142    * @param filePaths absolute paths to the playlist files are returned here
143    * @param format the playlist format is returned here
144    * @param hasFullPath true is returned here if the files use absolute paths
145    * @param hasInfo true is returned here if the playlist contains additional
146    *                information
147    * @return true if ok.
148    */
149   bool read(const QString& playlistPath, QStringList& filePaths,
150             PlaylistConfig::PlaylistFormat& format,
151             bool& hasFullPath, bool& hasInfo) const;
152 
153 private:
154   friend class Item;
155 
156   struct Entry {
EntryEntry157     Entry() : duration(0) {}
158     unsigned long duration;
159     QString filePath;
160     QString info;
161   };
162 
163   bool write(const QList<Entry>& entries);
164 
165   const PlaylistConfig& m_cfg;
166   QString m_playlistDirName;
167   QString m_playlistFileName;
168   QMap<QString, Entry> m_entries;
169 };
170