Icons themes, Portrait mode, bugfixes
[someplayer] / src / libraryform.cpp
1 /*
2  * SomePlayer - An alternate music player for Maemo 5
3  * Copyright (C) 2010 Nikolay (somebody) Tischenko <niktischenko@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19
20 #include "libraryform.h"
21 #include "ui_libraryform.h"
22 #include "library.h"
23 #include <QStandardItemModel>
24 #include <QStandardItem>
25 #include <QModelIndex>
26 #include <QModelIndexList>
27 #include "track.h"
28 #include "playlist.h"
29 #include <QTime>
30 #include <QQueue>
31 #include <QMessageBox>
32 #include "config.h"
33
34 using namespace SomePlayer::DataObjects;
35 using namespace SomePlayer::Storage;
36
37 inline QString __format_track_string(TrackMetadata meta) {
38         int minutes = meta.length() / 60;
39         int seconds = meta.length() % 60;
40         QTime time(0, minutes, seconds);
41         return QString("[%1] %2").arg(time.toString("mm:ss")).arg(meta.title());
42
43 }
44
45 inline void __fill_model(QStandardItemModel *model, QList<QString> data) {
46         model->clear();
47         int count = data.count();
48         model->setRowCount(count);
49         for (int i = 0; i < count; i++) {
50                 model->setItem(i, 0, new QStandardItem(data.at(i)));
51         }
52 }
53
54 inline void __fill_model_tracks (QStandardItemModel *model, QList<Track> tracks) {
55         int count = tracks.count();
56         model->setRowCount(count);
57         Config config;
58         bool show_lenght = (config.getValue("ui/showtracklenght").toString() != "no");
59         for (int i = 0; i < count; i++) {
60                 TrackMetadata meta = tracks.at(i).metadata();
61                 if (show_lenght)
62                         model->setItem(i, 0, new QStandardItem(__format_track_string(meta)));
63                 else
64                         model->setItem(i, 0, new QStandardItem(meta.title()));
65         }
66 }
67
68 LibraryForm::LibraryForm(Library *lib, QWidget *parent) :
69     QWidget(parent),
70     ui(new Ui::LibraryForm)
71 {
72         _lib = lib;
73         _model = new QStandardItemModel(this);
74         _state = STATE_NONE;
75         ui->setupUi(this);
76         connect(ui->playerButton, SIGNAL(clicked()), this, SLOT(_player()));
77         connect(ui->viewButton, SIGNAL(clicked()), this, SLOT(_view_button()));
78         connect(ui->playlistsButton, SIGNAL(clicked()), this, SLOT(_playlists_button()));
79         connect(ui->dynamicButton, SIGNAL(clicked()), this, SLOT(_dynamic_button()));
80         connect(ui->listView, SIGNAL(clicked(QModelIndex)), this, SLOT(_process_list_click(QModelIndex)));
81         connect(ui->addButton, SIGNAL(clicked()), this, SLOT(_add_button()));
82         connect(ui->selectAllButton, SIGNAL(clicked()), this, SLOT(_toggle_select_all_button()));
83         connect(ui->backButton, SIGNAL(clicked()), this, SLOT(_back_button()));
84         connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(_delete_button()));
85         connect(ui->useButton, SIGNAL(clicked()), this, SLOT(_use_button()));
86         _view_button();
87         Config config;
88         _icons_theme = config.getValue("ui/iconstheme").toString();
89         _current_playlist_changed = true;
90 }
91
92 LibraryForm::~LibraryForm()
93 {
94         _lib->saveCurrentPlaylist(_lib->getCurrentPlaylist()); // wtf?
95         _current_playlist_changed = true;
96         delete ui;
97 }
98
99 void LibraryForm::_player() {
100         emit player(_current_playlist_changed);
101         _current_playlist_changed = false;
102 }
103
104 void LibraryForm::_view_button() {
105         QList<QString> artitst = _lib->getArtists();
106         __fill_model(_model, artitst);
107         ui->listView->setModel(_model);
108         _state = STATE_ARTIST;
109         ui->backButton->hide();
110         ui->listLabel->setText("Artists");
111         ui->addButton->show();
112         ui->deleteButton->hide();
113         ui->useButton->hide();
114 }
115
116 void LibraryForm::_dynamic_button() {
117         ui->useButton->hide();
118         ui->backButton->hide();
119         ui->addButton->show();
120         ui->deleteButton->hide();
121         _model->clear();
122         _model->setRowCount(4);
123         _model->setItem(0, new QStandardItem("Favorites"));
124         _model->setItem(1, new QStandardItem("Most played"));
125         _model->setItem(2, new QStandardItem("Never played"));
126         _model->setItem(3, new QStandardItem("Recently added"));
127         _state = STATE_DYNAMIC;
128 }
129
130 void LibraryForm::_process_list_click(QModelIndex index) {
131         if (_state == STATE_NONE) return;
132         QString data = index.data().toString();
133         switch (_state) {
134         case STATE_ARTIST:
135                 __fill_model(_model, _lib->getAlbumsForArtist(data));
136                 ui->listView->scrollToTop();
137                 _current_artist = data;
138                 _state = STATE_ALBUM;
139                 ui->backButton->show();
140                 ui->listLabel->setText(QString("Albums by \"%1\"").arg(_current_artist));
141                 break;
142         case STATE_ALBUM:
143                 _current_album = data;
144                 _current_tracks = _lib->getTracksForAlbum(data, _current_artist);
145                 __fill_model_tracks(_model, _current_tracks);
146                 ui->listView->scrollToTop();
147                 _state = STATE_TRACK;
148                 ui->backButton->show();
149                 ui->listLabel->setText(QString("Tracks from \"%1\" by \"%2\"").arg(_current_album).arg(_current_artist));
150                 break;
151         case STATE_PLAYLIST:
152                 {
153                         _current_playlist = _lib->getPlaylist(data);
154                         _current_tracks = _current_playlist.tracks();
155                         __fill_model_tracks(_model, _current_tracks);
156                         ui->listView->scrollToTop();
157                         _state = STATE_PLAYLIST_TRACK;
158                         ui->backButton->show();
159                         ui->deleteButton->show();
160                         ui->useButton->show();
161                         ui->listLabel->setText(QString("Tracks in playlist \"%1\"").arg(data));
162                 }
163                 break;
164         case STATE_DYNAMIC:
165                 {
166                         switch(index.row()) {
167                         case 0: //favorites
168                                 _current_playlist = _lib->getFavorites();
169                                 break;
170                         case 1: //most played
171                                 _current_playlist = _lib->getMostPlayed();
172                                 break;
173                         case 2: //never played
174                                 _current_playlist = _lib->getNeverPlayed();
175                         case 3: //recently added
176                                 _current_playlist = _lib->getRecentlyAdded();
177                                 break;
178                         default:
179                                 return;
180                         }
181                         _current_tracks = _current_playlist.tracks();
182                         __fill_model_tracks(_model, _current_tracks);
183                         ui->listView->scrollToTop();
184                         _state = STATE_PLAYLIST_TRACK;
185                         ui->backButton->show();
186                         ui->useButton->show();
187                         ui->addButton->show();
188                         ui->listLabel->setText(_current_playlist.name());
189                 }
190         default:
191                 return;
192         }
193 }
194
195 void LibraryForm::_add_button() {
196         if (_state == STATE_NONE) return;
197         QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
198         ui->listView->selectionModel()->clearSelection();
199         emit busy(QString("<H1>Adding... Please wait</H1>"));
200         switch (_state) {
201         case STATE_ARTIST:
202                 foreach (QModelIndex id, selected) {
203                         _add_artist(id.data().toString());
204                 }
205                 break;
206         case STATE_ALBUM:
207                 foreach (QModelIndex id, selected) {
208                         _add_album(_current_artist, id.data().toString());
209                 }
210                 break;
211         case STATE_TRACK:
212                 foreach (QModelIndex id, selected) {
213                         _add_track(_current_tracks.at(id.row()));
214                 }
215                 break;
216         case STATE_PLAYLIST:
217                 foreach (QModelIndex id, selected) {
218                         _add_playlist(id.data().toString());
219                 }
220                 break;
221         case STATE_PLAYLIST_TRACK:
222                 foreach (QModelIndex id, selected) {
223                         _add_track(_current_tracks.at(id.row()));
224                 }
225                 break;
226         default:
227                 emit done();
228                 return;
229         }
230         emit done();
231 }
232
233
234 void LibraryForm::_add_artist(QString artist) {
235         QList<QString> albums = _lib->getAlbumsForArtist(artist);
236         foreach(QString album, albums) {
237                 _add_album(artist, album);
238         }
239 }
240
241 void LibraryForm::_add_album(QString artist, QString album) {
242         QList<Track> tracks = _lib->getTracksForAlbum(album, artist);
243         foreach(Track track, tracks) {
244                 _add_track(track);
245         }
246 }
247
248 void LibraryForm::_add_track(Track track) {
249         Playlist current = _lib->getCurrentPlaylist();
250         current.addTrack(track);
251         _lib->saveCurrentPlaylist(current);
252         _current_playlist_changed = true;
253 }
254
255 void LibraryForm::_add_playlist(QString name) {
256         Playlist playlist = _lib->getPlaylist(name);
257         QList<Track> tracks = playlist.tracks();
258         foreach (Track track, tracks) {
259                 _add_track(track);
260         }
261 }
262
263 void LibraryForm::_back_button() {
264         switch (_state) {
265         case STATE_ALBUM:
266                 _view_button();
267                 ui->listView->scrollToTop();
268                 break;
269         case STATE_TRACK:
270                 __fill_model(_model, _lib->getAlbumsForArtist(_current_artist));
271                 ui->listView->scrollToTop();
272                 _state = STATE_ALBUM;
273                 ui->listLabel->setText(QString("Albums by \"%1\"").arg(_current_artist));
274                 break;
275         case STATE_PLAYLIST_TRACK:
276                 _playlists_button();
277                 ui->listView->scrollToTop();
278         default:
279                 return;
280         }
281 }
282
283 void LibraryForm::_playlists_button() {
284         QList<QString> playlists = _lib->getPlaylistsNames();
285         __fill_model(_model, playlists);
286         ui->listView->setModel(_model);
287         _state = STATE_PLAYLIST;
288         ui->backButton->hide();
289         ui->listLabel->setText("Playlists");
290         ui->addButton->hide();
291         ui->deleteButton->show();
292         ui->useButton->hide();
293 }
294
295 void LibraryForm::_delete_button() {
296         if (_state == STATE_PLAYLIST_TRACK) {
297                 QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
298                 ui->listView->selectionModel()->clearSelection();
299                 QQueue<int> to_delete;
300                 foreach (QModelIndex id, selected) {
301                         to_delete.append(id.row());
302                 }
303                 qSort(to_delete);
304                 int count = to_delete.count();
305                 for (int i = count-1; i >= 0; i--) {
306                         _current_playlist.removeTrackAt(to_delete.at(i));
307                 }
308                 _current_tracks = _current_playlist.tracks();
309                 _lib->savePlaylist(_current_playlist);
310                 __fill_model_tracks(_model, _current_tracks);
311         } else if (_state == STATE_PLAYLIST) {
312                 QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
313                 QQueue<int> to_delete;
314                 foreach (QModelIndex id, selected) {
315                         to_delete.append(id.row());
316                 }
317                 qSort(to_delete);
318                 int count = to_delete.count();
319                 for (int i = count-1; i >= 0; i--) {
320                         QString name = _model->item(to_delete.at(i))->text();
321                         if (name != _CURRENT_PLAYLIST_SUBST_) {
322                                 _lib->removePlaylist(name);
323                                 _model->removeRow(to_delete.at(i));
324                         }
325                 }
326         }
327 }
328
329 void LibraryForm::_delete_track(Track track) {
330         Playlist current = _lib->getCurrentPlaylist();
331         current.removeTrack(track);
332         _lib->saveCurrentPlaylist(current);
333         _current_playlist_changed = true;
334 }
335
336 void LibraryForm::_use_button() {
337         _lib->saveCurrentPlaylist(_current_playlist);
338         _current_playlist_changed = true;
339         _current_playlist = _lib->getCurrentPlaylist();
340 }
341
342 void LibraryForm::search(QString &pattern) {
343         _search_pattern = pattern;
344         _search_current_id = -1;
345         nextItem();
346 }
347
348 void LibraryForm::nextItem() {
349         QString data = _model->index(_search_current_id, 0).data().toString();
350         for (int i = _search_current_id+1; i < _model->rowCount(); i++) {
351                 data = _model->index(i, 0).data().toString();
352                 if (data.contains(_search_pattern, Qt::CaseInsensitive)) {
353                         _search_current_id = i;
354                         break;
355                 }
356         }
357         QModelIndex id = _model->index(_search_current_id, 0);
358         ui->listView->selectionModel()->clearSelection();
359         ui->listView->selectionModel()->select(id, QItemSelectionModel::Select);
360         ui->listView->scrollTo(id);
361 }
362
363 void LibraryForm::prevItem() {
364         QString data = _model->index(_search_current_id, 0).data().toString();
365         for (int i = _search_current_id-1; i >= 0; i--) {
366                 data = _model->index(i, 0).data().toString();
367                 if (data.contains(_search_pattern, Qt::CaseInsensitive)) {
368                         _search_current_id = i;
369                         break;
370                 }
371         }
372         QModelIndex id = _model->index(_search_current_id, 0);
373         ui->listView->selectionModel()->clearSelection();
374         ui->listView->selectionModel()->select(id, QItemSelectionModel::Select);
375         ui->listView->scrollTo(id);
376 }
377
378 void LibraryForm::cancelSearch() {
379         _search_pattern = "";
380         ui->listView->selectionModel()->clearSelection();
381 }
382
383 void LibraryForm::refresh() {
384         switch (_state) {
385         case STATE_ARTIST:
386                 _view_button();
387                 break;
388         case STATE_ALBUM:
389                 __fill_model(_model, _lib->getAlbumsForArtist(_current_artist));
390                 break;
391         case STATE_PLAYLIST:
392                 _playlists_button();
393                 break;
394         case STATE_DYNAMIC:
395                 _dynamic_button();
396                 break;
397         case STATE_PLAYLIST_TRACK:
398                 _current_playlist = _lib->getPlaylist(_current_playlist.name());
399                 _current_tracks = _current_playlist.tracks();
400                 __fill_model_tracks(_model, _current_tracks);
401                 break;
402         case STATE_TRACK:
403                 _current_tracks = _lib->getTracksForAlbum(_current_album, _current_artist);
404                 __fill_model_tracks(_model, _current_tracks);
405                 break;
406         default:
407                 return;
408         }
409 }
410
411 void LibraryForm::_toggle_select_all_button() {
412         if (ui->listView->selectionModel()->selectedIndexes().count() == ui->listView->model()->rowCount()) {
413                 ui->listView->selectionModel()->clearSelection();
414                 ui->selectAllButton->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png"));
415         } else {
416                 ui->listView->selectAll();
417                 ui->selectAllButton->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"));
418         }
419 }
420
421 void LibraryForm::updateIcons() {
422         Config config;
423         _icons_theme = config.getValue("ui/iconstheme").toString();
424         ui->backButton->setIcon(QIcon(":/icons/"+_icons_theme+"/back.png"));
425         if (ui->listView->selectionModel()->selectedIndexes().count() == ui->listView->model()->rowCount())
426                 ui->selectAllButton->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"));
427         else
428                 ui->selectAllButton->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png"));
429         ui->addButton->setIcon(QIcon(":/icons/"+_icons_theme+"/add.png"));
430         ui->deleteButton->setIcon(QIcon(":/icons/"+_icons_theme+"/delete.png"));
431         ui->useButton->setIcon(QIcon(":/icons/"+_icons_theme+"/use.png"));
432         ui->playerButton->setIcon(QIcon(":/icons/"+_icons_theme+"/player.png"));
433         ui->viewButton->setIcon(QIcon(":/icons/"+_icons_theme+"/artists.png"));
434         ui->dynamicButton->setIcon(QIcon(":/icons/"+_icons_theme+"/dynamic.png"));
435         ui->playlistsButton->setIcon(QIcon(":/icons/"+_icons_theme+"/playlists.png"));
436 }