-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPlaylistManager.cpp
More file actions
311 lines (289 loc) · 10.1 KB
/
Copy pathPlaylistManager.cpp
File metadata and controls
311 lines (289 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*
* Pink Audio Player - simple audio file player.
* Copyright (C) <2020-2021> Artur Wawrowski
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* Author can be contacted through github issues at
* https://github.com/artwaw/Pink-Audio-Player
*/
#include "PlaylistManager.h"
/*!
* \brief C'tor, initializes internal structures.
* \param parent Optional parent pointer
*/
PlaylistManager::PlaylistManager(QObject *parent) : QObject(parent)
{
initPlaylists();
setupHeaders();
}
/*!
* \brief Preallocates new playlist structures.
* \param aname QString ID for the playlist
*/
void PlaylistManager::addNew(const QString &aname) {
if (aname.isEmpty()) { return; }
QStandardItemModel *proxy = new QStandardItemModel(0,10,this);
mPlaylists.insert(uniqueName(aname),proxy);
}
/*!
* \brief Retrieves pointer to the playlist by name
* \param pname Unique QString identifier
* \return Pointer to QStandardItemModel for the playlist.
*/
QStandardItemModel* PlaylistManager::retrieve(const QString &pname) {
if (pname.isEmpty()) { return live; }
return mPlaylists.value(pname);
}
/*!
* \brief Removes the playlist and deallocates resources.
* \param pname Unique name of the playlist
* \return FALSE if the playlist name could not be found, otherwise TRUE
*/
bool PlaylistManager::remove(const QString &pname) {
if (pname.isEmpty()) { return true; }
QStandardItemModel *proxy = retrieve(pname);
bool ret = mPlaylists.remove(pname);
if (proxy!=nullptr) { delete proxy; }
mPlaylists.squeeze();
return ret;
}
/*!
* \brief Returns all stored, user created playlist names
* \return QStringList with names. Can be empty if only "live view" playlist is present.
*/
QStringList PlaylistManager::getAll() const {
return mPlaylists.keys();
}
/*!
* \brief Routine forces resetting header names. Called upon a language change event.
*/
void PlaylistManager::retranslateHeaders() {
setupHeaders();
}
/*!
* \brief Renames existing playlist.
* \param oldName Old name of the playlist
* \param newName New name of the playlist
* \return Always TRUE
* \todo There is no error checking. I don't foresee any edge cases but some error checking would be in order.
*/
bool PlaylistManager::rename(const QString &oldName, const QString &newName) {
if (oldName.isEmpty()||newName.isEmpty()) { return true; }
if (oldName == newName) { return true; }
QStandardItemModel* item = mPlaylists.value(oldName);
mPlaylists.remove(oldName);
mPlaylists.insert(newName,item);
return true;
}
/*!
* \brief Retrives all the column names in the currently set locale.
* \return QStringList with the column names for the current locale.
*/
QStringList PlaylistManager::getColumnNames() const {
const QStringList headers = {
tr("Playing"), tr("Title"), tr("Artist"), tr("Duration"), tr("Genre"), tr("Comment"), tr("Album"), tr("Track"),
tr("Date"), tr("File path")
};
return headers;
}
/*!
* \brief Adds element to the specified playlist.
* \param rec Absolute file path.
* \param pname Playlist name to which the file is being added.
* \return Always TRUE.
*/
bool PlaylistManager::addEntryToPlaylist(const QString &rec, const QString &pname) {
if (rec.isEmpty()) { return false; }
mediaRader.getInfo(rec);
QStandardItemModel* model;
pname.isEmpty()?model=live:model=mPlaylists.value(pname);
QList<QStandardItem*> items;
items.append(new QStandardItem(QString()));
items.append(new QStandardItem(mediaRader.getTitle()));
items.append(new QStandardItem(mediaRader.getArtist()));
items.append(new QStandardItem(mediaRader.getDuration()));
items.append(new QStandardItem(mediaRader.getGenre()));
items.append(new QStandardItem(mediaRader.getComment()));
items.append(new QStandardItem(mediaRader.getAlbum()));
items.append(new QStandardItem(mediaRader.getTrack()));
items.append(new QStandardItem(mediaRader.getYear()));
items.append(new QStandardItem(rec));
model->appendRow(items);
return true;
}
/*!
* \brief Adds multiple local entries to the playlist.
* \param recs QStringList with absolute file paths
* \param pname Playlist to which add to.
* \return Always TRUE
* \sa PlaylistManager::addEntryToPlaylist()
*/
bool PlaylistManager::addEntriesToPlaylist(const QStringList &recs, const QString &pname) {
if (recs.isEmpty()) { return false; }
bool ret = true;
for (auto x=0;x<recs.size();++x) {
ret = ret && addEntryToPlaylist(recs.at(x),pname);
}
return ret;
}
/*!
* \brief Returns number of items in the current playlist.
* \param playlist Playlist in question. Can be empty string.
* \param isLive Indication if current is "live view".
* \return An int with item count.
*/
int PlaylistManager::itemCountForPlaylist(const QString &playlist, bool isLive) const {
return isLive?live->rowCount():mPlaylists.value(playlist)->rowCount();
}
/*!
* \brief Returns the label with the name of the "live view".
* \return QString with tab label.
*/
QString PlaylistManager::getLiveTitle() const {
return liveTitle;
}
/*!
* \brief Writes playlists and their content to the db file.
*
* Internally, QDataStream is used to read from the binary file. Stream versioning is used
* as a means to introduce changes between the versions.
* The file is closed once the write is done.
* \sa PlaylistManager::initPlaylists()
* \todo Write it ;)
*/
void PlaylistManager::sync() {
//
}
/*!
* \brief Sets the "currently playling" indicator on the currently played item.
* \param item Absolute path of the item.
* \param pname Playlist to which item belogns to, active playlist.
* \sa PlaylistManager::clearPlaying()
*/
void PlaylistManager::setPlaying(const QString &item, const QString &pname) {
QStandardItemModel *model = pname.isEmpty()?live:mPlaylists.value(pname);
for (auto x=0;x<model->rowCount();++x) {
if (model->data(model->index(x,9)).toString()==item) {
model->setItem(x,0,new QStandardItem(">"));
break;
}
}
}
/*!
* \brief Clears the "currently playing" idicator from playlist.
* \param pname Currently active playlist name.
* \sa PlaylistManager::setPlaying()
*/
void PlaylistManager::clearPlaying(const QString &pname) {
QStandardItemModel *model = pname.isEmpty()?live:mPlaylists.value(pname);
for (auto x=0;x<model->rowCount();++x) {
if (!model->data(model->index(x,0)).toString().isEmpty()) {
model->setItem(x,0,new QStandardItem());
break;
}
}
}
/*!
* \brief Clears (removes) all the items from the selected playlist.
* \param pname Playlist name to clear, if empty "live view" is used.
*/
void PlaylistManager::clearPlaylist(const QString &pname = QString()) {
pname.isEmpty()?live->setRowCount(0):mPlaylists.value(pname)->setRowCount(0);
}
/*!
* \brief Method assigning translated headers to the views
* \sa PlaylistManager::getColumnNames()
*/
void PlaylistManager::setupHeaders() {
const QStringList headers = getColumnNames();
live->setHorizontalHeaderLabels(headers);
for (auto it=mPlaylists.constBegin();it!=mPlaylists.constEnd();++it) {
it.value()->setHorizontalHeaderLabels(headers);
}
}
/*!
* \brief Reads the stored playists and their contents from the db file.
*
* Internally, QDataStream is used to read from the binary file. Stream versioning is used
* as a means to introduce changes between the versions.
* The file is closed once the read is done.
*
* \sa PlaylsitManager::sync()
* \todo Remove Q_ASSERT, make error checking.
*/
void PlaylistManager::initPlaylists() {
QDir fpath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
if (!fpath.exists()) {
fpath.mkpath(fpath.absolutePath());
}
QFile file(fpath.absolutePath()+"/"+dataFile);
QDataStream stream;
if (!file.exists()) {
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::critical(nullptr,tr("File access error"),tr("Can't open file %1 for writing. Program will work but playlsits will not save.").arg(file.fileName()));
return;
}
stream.setDevice(&file);
stream.setVersion(QDataStream::Qt_6_2);
stream << QString("Live view");
stream << 0;
stream << 0;
file.close();
}
live = new QStandardItemModel(this);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(nullptr,tr("File access error"),tr("Playlist database file %1 can't be open for reading. Playlists will not be saved.").arg(file.fileName()));
return;
}
stream.setDevice(&file);
stream.setVersion(QDataStream::Qt_6_2);
stream >> liveTitle;
int liveCount;
stream >> liveCount;
QStringList items;
if (liveCount>0) {
stream >> items;
addEntriesToPlaylist(items);
}
int all;
stream >> all;
if (all>0) {
QString title;
for (auto x=0;x<all;++x) {
stream >> title;
stream >> items;
addNew(title);
addEntriesToPlaylist(items,title);
}
}
file.close();
}
/*!
* \brief Method returns the unique name for the new playlist.
* \param aname Proposed name of the new playlist.
* \return Unique name. Can be same as aname.
*/
QString PlaylistManager::uniqueName(const QString &aname) const {
if (!mPlaylists.contains(aname)) { return aname; }
int x=1;
QString name = QString("%1 %2").arg(aname,QString::number(x));
while (mPlaylists.contains(name)) {
++x;
name = QString("%1 %2").arg(aname,QString::number(x));
}
return name;
}