Version bump
[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 <QTimer>
31 #include <QQueue>
32 #include <QMessageBox>
33 #include "config.h"
34 #include <QSpacerItem>
35 #include <QDebug>
36
37 using namespace SomePlayer::DataObjects;
38 using namespace SomePlayer::Storage;
39
40 inline QString __format_track_string(TrackMetadata meta) {
41         int minutes = meta.length() / 60;
42         int seconds = meta.length() % 60;
43         QTime time(0, minutes, seconds);
44         return QString("[%1] %2").arg(time.toString("mm:ss")).arg(meta.title());
45
46 }
47
48 inline void __fill_model(QStandardItemModel *model, QList<QString> data, QString icons_theme) {
49         model->clear();
50         int count = data.count();
51         model->setRowCount(count);
52         for (int i = 0; i < count; i++) {
53                 model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+icons_theme+"/deselect_all.png"), ""));
54                 model->setItem(i, 1, new QStandardItem(data.at(i)));
55         }
56 }
57
58 inline void __fill_model_album(QStandardItemModel *model, QMap<QString, int> data, QString icons_theme) {
59         model->clear();
60         int count = data.count();
61         model->setRowCount(count+1);
62         int i = 0;
63         Config config;
64         model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+icons_theme+"/deselect_all.png"), ""));
65         model->setItem(i, 1, new QStandardItem(QObject::tr("All tracks")));
66         i++;
67         if (config.getValue("ui/albumsorting").toString() == "date") {
68                 QMap<int, QList<QString> > years;
69                 foreach (QString name, data.keys()) {
70                         years[data[name]].append(name);
71                 }
72                 QList<int> keys = years.keys();
73                 qSort(keys);
74
75                 foreach (int year, keys) {
76                         foreach (QString name, years[year]) {
77                                 model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+icons_theme+"/deselect_all.png"), ""));
78                                 model->setItem(i, 1, new QStandardItem(QString("[%1] %2").arg(year).arg(name)));
79                                 i++;
80                         }
81                 }
82         } else {
83                 QList<QString> names = data.keys();
84                 foreach (QString name, names) {
85                         model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+icons_theme+"/deselect_all.png"), ""));
86                         model->setItem(i, 1, new QStandardItem(QString("[%1] %2").arg(data[name]).arg(name)));
87                         i++;
88                 }
89         }
90 }
91
92 inline void __fill_model_tracks (QStandardItemModel *model, QList<Track> tracks, QString icons_theme) {
93         int count = tracks.count();
94         model->setRowCount(count);
95         Config config;
96         bool show_lenght = (config.getValue("ui/showtracklenght").toString() != "no");
97         for (int i = 0; i < count; i++) {
98                 TrackMetadata meta = tracks.at(i).metadata();
99                 if (show_lenght) {
100                         model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+icons_theme+"/deselect_all.png"), ""));
101                         model->setItem(i, 1, new QStandardItem(__format_track_string(meta)));
102                 } else {
103                         model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+icons_theme+"/deselect_all.png"), ""));
104                         model->setItem(i, 1, new QStandardItem(meta.title()));
105                 }
106         }
107 }
108
109 LibraryForm::LibraryForm(Library *lib, QWidget *parent) :
110     QWidget(parent),
111     ui(new Ui::LibraryForm)
112 {
113         _lib = lib;
114         Config config;
115         _icons_theme = config.getValue("ui/iconstheme").toString();
116         _model = new QStandardItemModel(this);
117         _model->setColumnCount(2);
118         _state = STATE_NONE;
119         _tools_widget = new ToolsWidget(this);
120         _search_in_library_button = new QPushButton(QIcon(":/icons/"+_icons_theme+"/search.png"), "", _tools_widget);
121         _search_in_library_button->setFlat(true);
122         _search_in_library_button->setCheckable(true);
123         _tools_widget->layout()->addItem(new QSpacerItem(20, 20));
124         _tools_widget->layout()->addWidget(_search_in_library_button);
125         ui->setupUi(this);
126         ui->listView->setModel(_model);
127         ui->listView->setColumnWidth(0, 70);
128         ui->toolsLayout->addWidget(_tools_widget);
129         _tools_widget->hideFSButton();
130         _tools_widget->hide();
131         connect(ui->viewButton, SIGNAL(clicked()), this, SLOT(_view_button()));
132         connect(ui->playlistsButton, SIGNAL(clicked()), this, SLOT(_playlists_button()));
133         connect(ui->dynamicButton, SIGNAL(clicked()), this, SLOT(_dynamic_button()));
134         connect(ui->listView, SIGNAL(clicked(QModelIndex)), this, SLOT(_process_list_click(QModelIndex)));
135         connect(ui->listView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(_process_dblclick(QModelIndex)));
136         connect(ui->listView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
137                 this, SLOT(_process_selection(QItemSelection,QItemSelection)));
138         connect(ui->addButton, SIGNAL(clicked()), this, SLOT(_add_button()));
139         connect(ui->selectAllButton, SIGNAL(clicked()), this, SLOT(_toggle_select_all_button()));
140         connect(ui->backButton, SIGNAL(clicked()), this, SLOT(_back_button()));
141         connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(_delete_button()));
142         connect(ui->useButton, SIGNAL(clicked()), this, SLOT(_use_button()));
143         connect(_tools_widget, SIGNAL(search(QString)), this, SLOT(search(QString)));
144         connect(_tools_widget, SIGNAL(nextSearch()), this, SLOT(nextItem()));
145         connect(_tools_widget, SIGNAL(prevSearch()), this, SLOT(prevItem()));
146         connect(ui->moreButton, SIGNAL(clicked()), this, SLOT(_more_button()));
147         connect(_search_in_library_button, SIGNAL(toggled(bool)), this, SLOT(_search_button(bool)));
148         connect(ui->playerButton, SIGNAL(clicked()), this, SLOT(hide()));
149         _view_button();
150         _top_gradient = ui->topWidget->styleSheet();
151         _bottom_gradient = ui->bottomWidget->styleSheet();
152         _is_dynamic = false;
153         _is_favorites = false;
154         setAttribute(Qt::WA_Maemo5StackedWindow);
155         setWindowFlags(Qt::Window | windowFlags());
156         ui->addButton->setEnabled(false);
157         ui->addButton->setIcon(QIcon());
158         ui->deleteButton->setEnabled(false);
159         ui->deleteButton->setIcon(QIcon());
160 }
161
162 LibraryForm::~LibraryForm()
163 {
164         delete ui;
165 }
166
167 void LibraryForm::_view_button() {
168         QList<QString> artitst = _lib->getArtists();
169         __fill_model(_model, artitst, _icons_theme);
170         ui->listView->setColumnWidth(0, 70);
171         _state = STATE_ARTIST;
172         ui->backButton->setEnabled(false);
173         ui->backButton->setIcon(QIcon());
174         ui->listLabel->setText(tr("Artists"));
175         ui->useButton->setEnabled(false);
176         ui->useButton->setIcon(QIcon());
177         ui->addButton->setEnabled(false);
178         ui->addButton->setIcon(QIcon());
179         ui->deleteButton->setEnabled(false);
180         ui->deleteButton->setIcon(QIcon());
181 }
182
183 void LibraryForm::_dynamic_button() {
184         ui->useButton->setEnabled(false);
185         ui->useButton->setIcon(QIcon());
186         ui->backButton->setEnabled(false);
187         ui->backButton->setIcon(QIcon());
188         ui->deleteButton->setEnabled(false);
189         ui->deleteButton->setIcon(QIcon());
190         _model->clear();
191         _model->setRowCount(4);
192         _model->setItem(0, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), ""));
193         _model->setItem(0, 1, new QStandardItem("Favorites"));
194         _model->setItem(1, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), ""));
195         _model->setItem(1, 1, new QStandardItem("Most played"));
196         _model->setItem(2, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), ""));
197         _model->setItem(2, 1, new QStandardItem("Never played"));
198         _model->setItem(3, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), ""));
199         _model->setItem(3, 1, new QStandardItem("Recently added"));
200         ui->listView->setColumnWidth(0, 70);
201         ui->listLabel->setText(tr("Dynamic playlists"));
202         _state = STATE_DYNAMIC;
203         ui->addButton->setEnabled(false);
204         ui->addButton->setIcon(QIcon());
205         ui->deleteButton->setEnabled(false);
206         ui->deleteButton->setIcon(QIcon());
207 }
208
209 void LibraryForm::_process_list_click(QModelIndex index) {
210         if (index.column() == 0) {
211                 return;
212         }
213         if (_state == STATE_NONE) return;
214         QString data = index.data().toString();
215         QRegExp regexp("\\[\\d+\\]\\ (.*)");
216         switch (_state) {
217         case STATE_ARTIST:
218                 _artist_row_for_scroll_to = index.row();
219                 __fill_model_album(_model, _lib->getAlbumsForArtist(data), _icons_theme);
220                 ui->listView->setColumnWidth(0, 70);
221                 ui->listView->scrollToTop();
222                 _current_artist = data;
223                 _state = STATE_ALBUM;
224                 ui->backButton->setEnabled(true);
225                 ui->backButton->setIcon(QIcon(":/icons/"+_icons_theme+"/back.png"));
226                 ui->listLabel->setText(QString(tr("Albums by \"%1\"")).arg(_current_artist));
227                 break;
228         case STATE_ALBUM:
229                 _album_row_for_scroll_to = index.row();
230                 if (regexp.indexIn(data) != -1) {
231                         _current_album = regexp.cap(1).trimmed();
232                         _current_tracks = _lib->getTracksForAlbum(_current_album, _current_artist);
233                         __fill_model_tracks(_model, _current_tracks, _icons_theme);
234                         ui->listView->setColumnWidth(0, 70);
235                         ui->listView->scrollToTop();
236                         _state = STATE_TRACK;
237                         ui->backButton->setEnabled(true);
238                         ui->backButton->setIcon(QIcon(":/icons/"+_icons_theme+"/back.png"));
239                         ui->listLabel->setText(QString(tr("Tracks from \"%1\" by \"%2\"")).arg(_current_album).arg(_current_artist));
240                 } else {
241                         if (index.row() == 0) { // all tracks
242                                 _current_tracks = _lib->getAllTracksForArtist(_current_artist);
243                                 __fill_model_tracks(_model, _current_tracks, _icons_theme);
244                                 ui->listView->setColumnWidth(0, 70);
245                                 ui->listView->scrollToTop();
246                                 _state = STATE_TRACK;
247                                 ui->backButton->setEnabled(true);
248                                 ui->backButton->setIcon(QIcon(":/icons/"+_icons_theme+"/back.png"));
249                                 ui->listLabel->setText(QString(tr("All tracks by \"%1\"")).arg(_current_artist));
250                         }
251                 }
252                 break;
253         case STATE_PLAYLIST:
254                 {
255                         _playlist_row_for_scroll_to = index.row();
256                         _current_playlist = _lib->getPlaylist(data);
257                         _current_tracks = _current_playlist.tracks();
258                         __fill_model_tracks(_model, _current_tracks, _icons_theme);
259                         ui->listView->setColumnWidth(0, 70);
260                         ui->listView->scrollToTop();
261                         _state = STATE_PLAYLIST_TRACK;
262                         _is_dynamic = false;
263                         ui->backButton->setEnabled(true);
264                         ui->backButton->setIcon(QIcon(":/icons/"+_icons_theme+"/back.png"));
265                         ui->useButton->setEnabled(true);
266                         ui->useButton->setIcon(QIcon(":/icons/"+_icons_theme+"/use.png"));
267                         ui->listLabel->setText(QString(tr("Tracks in playlist \"%1\"")).arg(data));
268                 }
269                 break;
270         case STATE_DYNAMIC:
271                 {
272                         switch(index.row()) {
273                         case 0: //favorites
274                                 _current_playlist = _lib->getFavorites();
275                                 _is_favorites = true;
276                                 break;
277                         case 1: //most played
278                                 _current_playlist = _lib->getMostPlayed();
279                                 _is_favorites = false;
280                                 break;
281                         case 2: //never played
282                                 _current_playlist = _lib->getNeverPlayed();
283                                 _is_favorites = false;
284                                 break;
285                         case 3: //recently added
286                                 _current_playlist = _lib->getRecentlyAdded();
287                                 _is_favorites = false;
288                                 break;
289                         default:
290                                 return;
291                         }
292                         _current_tracks = _current_playlist.tracks();
293                         __fill_model_tracks(_model, _current_tracks, _icons_theme);
294                         ui->listView->setColumnWidth(0, 70);
295                         ui->listView->scrollToTop();
296                         _state = STATE_PLAYLIST_TRACK;
297                         _is_dynamic = true;
298                         ui->backButton->setEnabled(true);
299                         ui->backButton->setIcon(QIcon(":/icons/"+_icons_theme+"/back.png"));
300                         ui->useButton->setEnabled(true);
301                         ui->useButton->setIcon(QIcon(":/icons/"+_icons_theme+"/use.png"));
302                         ui->listLabel->setText(_current_playlist.name());
303                 }
304         default:
305                 return;
306         }
307         ui->addButton->setEnabled(false);
308         ui->addButton->setIcon(QIcon());
309         ui->useButton->setEnabled(false);
310         ui->useButton->setIcon(QIcon());
311         ui->deleteButton->setEnabled(false);
312         ui->deleteButton->setIcon(QIcon());
313         QTimer::singleShot(100, ui->listView, SLOT(clearSelection())); // workaround
314 }
315
316 void LibraryForm::_add_button() {
317         if (_state == STATE_NONE) return;
318         QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
319         ui->listView->selectionModel()->clearSelection();
320         Playlist cur = _lib->getCurrentPlaylist();
321         QRegExp regexp("\\[\\d+\\]\\ (.*)");
322         switch (_state) {
323         case STATE_ARTIST:
324                 foreach (QModelIndex id, selected) {
325                         _add_artist(&cur, id.data().toString());
326                 }
327                 _lib->saveCurrentPlaylist(cur);
328                 emit refreshPlayer();
329                 break;
330         case STATE_ALBUM:
331                 foreach (QModelIndex id, selected) {
332                         if (regexp.indexIn(id.data().toString()) != -1) {
333                                 _add_album(&cur, _current_artist, regexp.cap(1).trimmed());
334                         }
335                 }
336                 _lib->saveCurrentPlaylist(cur);
337                 emit refreshPlayer();
338                 break;
339         case STATE_TRACK:
340                 foreach (QModelIndex id, selected) {
341                         _add_track(&cur, _current_tracks.at(id.row()));
342                 }
343                 _lib->saveCurrentPlaylist(cur);
344                 emit refreshPlayer();
345                 break;
346         case STATE_PLAYLIST:
347                 foreach (QModelIndex id, selected) {
348                         _add_playlist(&cur, id.data().toString());
349                 }
350                 _lib->saveCurrentPlaylist(cur);
351                 emit refreshPlayer();
352                 break;
353         case STATE_DYNAMIC:
354
355                 break;
356         case STATE_PLAYLIST_TRACK:
357                 foreach (QModelIndex id, selected) {
358                         _add_track(&cur, _current_tracks.at(id.row()));
359                 }
360                 _lib->saveCurrentPlaylist(cur);
361                 emit refreshPlayer();
362                 break;
363         case STATE_SEARCH:
364                 foreach (QModelIndex id, selected) {
365                         _add_track(&cur, _current_tracks.at(id.row()));
366                 }
367                 _lib->saveCurrentPlaylist(cur);
368                 emit refreshPlayer();
369                 break;
370         default:
371                 return;
372         }
373 }
374
375
376 void LibraryForm::_add_artist(Playlist *cur, QString artist) {
377         QMap<QString, int> albums = _lib->getAlbumsForArtist(artist);
378         foreach(QString album, albums.keys()) {
379                 _add_album(cur, artist, album);
380         }
381 }
382
383 void LibraryForm::_add_album(Playlist *cur, QString artist, QString album) {
384         QList<Track> tracks = _lib->getTracksForAlbum(album, artist);
385         foreach(Track track, tracks) {
386                 _add_track(cur, track);
387         }
388 }
389
390 void LibraryForm::_add_track(Playlist *cur, Track track) {
391         cur->addTrack(track);
392 }
393
394 void LibraryForm::_add_playlist(Playlist *cur, QString name) {
395         Playlist playlist = _lib->getPlaylist(name);
396         QList<Track> tracks = playlist.tracks();
397         foreach (Track track, tracks) {
398                 _add_track(cur, track);
399         }
400 }
401
402 void LibraryForm::_back_button() {
403         switch (_state) {
404         case STATE_ALBUM:
405                 _view_button();
406                 if (_model->rowCount() != 0) {
407                         ui->listView->scrollTo(_model->index(_artist_row_for_scroll_to, 1), QAbstractItemView::PositionAtCenter);
408                 }
409                 break;
410         case STATE_TRACK:
411                 __fill_model_album(_model, _lib->getAlbumsForArtist(_current_artist), _icons_theme);
412                 ui->listView->setColumnWidth(0, 70);
413                 if (_model->rowCount() != 0) {
414                         ui->listView->scrollTo(_model->index(_album_row_for_scroll_to, 1), QAbstractItemView::PositionAtCenter);
415                 }
416                 _state = STATE_ALBUM;
417                 ui->listLabel->setText(QString(tr("Albums by \"%1\"")).arg(_current_artist));
418                 break;
419         case STATE_PLAYLIST_TRACK:
420                 if (_is_dynamic) {
421                         _dynamic_button();
422                         _is_dynamic = false;
423                 } else {
424                         _playlists_button();
425                 }
426                 if (_model->rowCount() != 0 && !_is_dynamic) {
427                         ui->listView->scrollTo(_model->index(_playlist_row_for_scroll_to, 1), QAbstractItemView::PositionAtCenter);
428                 }
429         default:
430                 return;
431         }
432 }
433
434 void LibraryForm::_playlists_button() {
435         QList<QString> playlists = _lib->getPlaylistsNames();
436         __fill_model(_model, playlists, _icons_theme);
437         ui->listView->setColumnWidth(0, 70);
438         _state = STATE_PLAYLIST;
439         ui->backButton->setEnabled(false);
440         ui->backButton->setIcon(QIcon());
441         ui->listLabel->setText(tr("Playlists"));
442         ui->useButton->setEnabled(false);
443         ui->useButton->setIcon(QIcon());
444         ui->addButton->setEnabled(false);
445         ui->addButton->setIcon(QIcon());
446         ui->deleteButton->setEnabled(false);
447         ui->deleteButton->setIcon(QIcon());
448 }
449
450 void LibraryForm::_delete_button() {
451         if (_state == STATE_PLAYLIST_TRACK) {
452                 QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
453                 ui->listView->selectionModel()->clearSelection();
454                 QQueue<int> to_delete;
455                 foreach (QModelIndex id, selected) {
456                         if (!to_delete.contains(id.row()))
457                                 to_delete.append(id.row());
458                 }
459                 qSort(to_delete);
460                 int count = to_delete.count();
461                 if (_is_dynamic && _is_favorites) {
462                         _current_tracks = _lib->getFavorites().tracks();
463                         for (int i = count-1; i >= 0; i--) {
464                                 _lib->removeFromFavorites(_current_tracks.at(to_delete.at(i)));
465                         }
466                         _current_playlist = _lib->getFavorites();
467                         _current_tracks = _current_playlist.tracks();
468                 } else {
469                         for (int i = count-1; i >= 0; i--) {
470                                 _current_playlist.removeTrackAt(to_delete.at(i));
471                         }
472                         _current_tracks = _current_playlist.tracks();
473                         _lib->savePlaylist(_current_playlist);
474                         emit refreshPlayer();
475                 }
476                 __fill_model_tracks(_model, _current_tracks, _icons_theme);
477                 ui->listView->setColumnWidth(0, 70);
478         } else if (_state == STATE_PLAYLIST) {
479                 QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
480                 QQueue<int> to_delete;
481                 foreach (QModelIndex id, selected) {
482                         if (!to_delete.contains(id.row()))
483                                 to_delete.append(id.row());
484                 }
485                 qSort(to_delete);
486                 int count = to_delete.count();
487                 for (int i = count-1; i >= 0; i--) {
488                         QString name = _model->item(to_delete.at(i), 1)->text();
489                         if (name != _CURRENT_PLAYLIST_SUBST_) {
490                                 _lib->removePlaylist(name);
491                                 _model->removeRow(to_delete.at(i));
492                         }
493                 }
494         }
495 }
496
497 void LibraryForm::_delete_track(Track track) {
498         Playlist current = _lib->getCurrentPlaylist();
499         current.removeTrack(track);
500         _lib->saveCurrentPlaylist(current);
501         emit refreshPlayer();
502 }
503
504 void LibraryForm::_use_button() {
505         if (_state == STATE_PLAYLIST_TRACK) {
506                 _lib->saveCurrentPlaylist(_current_playlist);
507                 emit refreshPlayer();
508                 _current_playlist = _lib->getCurrentPlaylist();
509                 return;
510         }
511
512         if (_state == STATE_NONE) return;
513         QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
514         ui->listView->selectionModel()->clearSelection();
515         Playlist cur;
516         QRegExp regexp("\\[\\d+\\]\\ (.*)");
517         switch (_state) {
518         case STATE_ARTIST:
519                 foreach (QModelIndex id, selected) {
520                         _add_artist(&cur, id.data().toString());
521                 }
522                 _lib->saveCurrentPlaylist(cur);
523                 emit refreshPlayer();
524                 break;
525         case STATE_ALBUM:
526                 foreach (QModelIndex id, selected) {
527                         if (regexp.indexIn(id.data().toString()) != -1) {
528                                 _add_album(&cur, _current_artist, regexp.cap(1).trimmed());
529                         }
530                 }
531                 _lib->saveCurrentPlaylist(cur);
532                 emit refreshPlayer();
533                 break;
534         case STATE_TRACK:
535                 foreach (QModelIndex id, selected) {
536                         _add_track(&cur, _current_tracks.at(id.row()));
537                 }
538                 _lib->saveCurrentPlaylist(cur);
539                 emit refreshPlayer();
540                 break;
541         case STATE_PLAYLIST:
542                 foreach (QModelIndex id, selected) {
543                         _add_playlist(&cur, id.data().toString());
544                 }
545                 _lib->saveCurrentPlaylist(cur);
546                 emit refreshPlayer();
547                 break;
548         case STATE_DYNAMIC:
549
550                 break;
551         case STATE_SEARCH:
552                 foreach (QModelIndex id, selected) {
553                         _add_track(&cur, _current_tracks.at(id.row()));
554                 }
555                 _lib->saveCurrentPlaylist(cur);
556                 emit refreshPlayer();
557                 break;
558         default:
559                 return;
560         }
561 }
562
563 void LibraryForm::search(QString pattern) {
564         _search_pattern = pattern;
565         _search_current_id = -1;
566         nextItem();
567 }
568
569 void LibraryForm::nextItem() {
570         QString data = _model->index(_search_current_id, 0).data().toString();
571         for (int i = _search_current_id+1; i < _model->rowCount(); i++) {
572                 data = _model->index(i, 1).data().toString();
573                 if (data.contains(_search_pattern, Qt::CaseInsensitive)) {
574                         _search_current_id = i;
575                         break;
576                 }
577         }
578         QModelIndex id = _model->index(_search_current_id, 1);
579         ui->listView->selectionModel()->clearSelection();
580         ui->listView->selectRow(id.row());
581         ui->listView->scrollTo(id, QAbstractItemView::PositionAtCenter);
582 }
583
584 void LibraryForm::prevItem() {
585         QString data = _model->index(_search_current_id, 0).data().toString();
586         for (int i = _search_current_id-1; i >= 0; i--) {
587                 data = _model->index(i, 1).data().toString();
588                 if (data.contains(_search_pattern, Qt::CaseInsensitive)) {
589                         _search_current_id = i;
590                         break;
591                 }
592         }
593         QModelIndex id = _model->index(_search_current_id, 1);
594         ui->listView->selectionModel()->clearSelection();
595         ui->listView->selectRow(id.row());
596         ui->listView->scrollTo(id, QAbstractItemView::PositionAtCenter);
597 }
598
599 void LibraryForm::cancelSearch() {
600         _search_pattern = "";
601         ui->listView->selectionModel()->clearSelection();
602 }
603
604 void LibraryForm::refresh() {
605         switch (_state) {
606         case STATE_ARTIST:
607                 _view_button();
608                 break;
609         case STATE_ALBUM:
610                 __fill_model_album(_model, _lib->getAlbumsForArtist(_current_artist), _icons_theme);
611                 ui->listView->setColumnWidth(0, 70);
612                 break;
613         case STATE_PLAYLIST:
614                 _playlists_button();
615                 break;
616         case STATE_DYNAMIC:
617                 _dynamic_button();
618                 break;
619         case STATE_PLAYLIST_TRACK:
620                 _current_playlist = _lib->getPlaylist(_current_playlist.name());
621                 _current_tracks = _current_playlist.tracks();
622                 __fill_model_tracks(_model, _current_tracks, _icons_theme);
623                 ui->listView->setColumnWidth(0, 70);
624                 break;
625         case STATE_TRACK:
626                 _current_tracks = _lib->getTracksForAlbum(_current_album, _current_artist);
627                 __fill_model_tracks(_model, _current_tracks, _icons_theme);
628                 break;
629         default:
630                 return;
631         }
632 }
633
634 void LibraryForm::_toggle_select_all_button() {
635         if (ui->listView->selectionModel()->selectedIndexes().count() == _model->rowCount() * _model->columnCount()) {
636                 ui->listView->selectionModel()->clearSelection();
637                 ui->selectAllButton->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png"));
638         } else {
639                 disconnect(ui->listView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
640                            this, SLOT(_process_selection(QItemSelection,QItemSelection)));
641                 ui->listView->selectAll();
642                 int cnt = _model->rowCount();
643                 for (int i = 0; i < cnt; i++) {
644                         _model->item(i)->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png"));
645                 }
646                 connect(ui->listView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
647                            this, SLOT(_process_selection(QItemSelection,QItemSelection)));
648                 ui->selectAllButton->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"));
649                 if (_state != STATE_DYNAMIC) {
650                         ui->addButton->setIcon(QIcon(":/icons/"+_icons_theme+"/add.png"));
651                         ui->addButton->setEnabled(true);
652                         ui->useButton->setEnabled(true);
653                         ui->useButton->setIcon(QIcon(":/icons/"+_icons_theme+"/use.png"));
654                 }
655
656                 if (_state == STATE_PLAYLIST || (_state == STATE_PLAYLIST_TRACK && !_is_dynamic)
657                         || (_state == STATE_PLAYLIST_TRACK && _is_favorites)) {
658                         ui->deleteButton->setEnabled(true);
659                         ui->deleteButton->setIcon(QIcon(":/icons/"+_icons_theme+"/delete.png"));
660                 }
661         }
662 }
663
664 void LibraryForm::landscapeMode() {
665         landscape = true;
666         ui->topWidget->hide();
667         ui->bottomWidget->hide();
668
669         ui->lverticalLayout->removeItem(ui->lverticalSpacer_0);
670         ui->lverticalLayout->removeItem(ui->lverticalSpacer_1);
671         ui->lverticalLayout->removeItem(ui->lverticalSpacer_2);
672         ui->lverticalLayout->removeItem(ui->lverticalSpacer_3);
673         ui->lverticalLayout->addWidget(ui->backButton);
674         ui->lverticalLayout->addItem(ui->lverticalSpacer_0);
675         ui->lverticalLayout->addWidget(ui->addButton);
676         ui->lverticalLayout->addItem(ui->lverticalSpacer_1);
677         ui->lverticalLayout->addWidget(ui->deleteButton);
678         ui->lverticalLayout->addItem(ui->lverticalSpacer_2);
679         ui->lverticalLayout->addWidget(ui->useButton);
680         ui->lverticalLayout->addItem(ui->lverticalSpacer_3);
681         ui->lverticalLayout->addWidget(ui->playerButton);
682
683         ui->rverticalLayout->removeItem(ui->rverticalSpacer_0);
684         ui->rverticalLayout->removeItem(ui->rverticalSpacer_1);
685         ui->rverticalLayout->removeItem(ui->rverticalSpacer_2);
686         ui->rverticalLayout->removeItem(ui->rverticalSpacer_3);
687         ui->rverticalLayout->addWidget(ui->moreButton);
688         ui->rverticalLayout->addItem(ui->rverticalSpacer_0);
689         ui->rverticalLayout->addWidget(ui->selectAllButton);
690         ui->rverticalLayout->addItem(ui->rverticalSpacer_1);
691         ui->rverticalLayout->addWidget(ui->viewButton);
692         ui->rverticalLayout->addItem(ui->rverticalSpacer_2);
693         ui->rverticalLayout->addWidget(ui->dynamicButton);
694         ui->rverticalLayout->addItem(ui->rverticalSpacer_3);
695         ui->rverticalLayout->addWidget(ui->playlistsButton);
696
697         ui->lverticalWidget->show();
698         ui->rverticalWidget->show();
699
700         if (_tools_widget->isVisible()) {
701                 ui->moreButton->setIcon(QIcon(":/icons/"+_icons_theme+"/more_l.png"));
702         } else {
703                 ui->moreButton->setIcon(QIcon(":/icons/"+_icons_theme+"/unmore_l.png"));
704         }
705 }
706
707 void LibraryForm::portraitMode() {
708         landscape = false;
709
710         ui->lverticalWidget->hide();
711         ui->rverticalWidget->hide();
712
713         ui->lverticalLayout->removeItem(ui->lverticalSpacer_0);
714         ui->lverticalLayout->removeItem(ui->lverticalSpacer_1);
715         ui->lverticalLayout->removeItem(ui->lverticalSpacer_2);
716         ui->lverticalLayout->removeItem(ui->lverticalSpacer_3);
717
718         ui->rverticalLayout->removeItem(ui->rverticalSpacer_0);
719         ui->rverticalLayout->removeItem(ui->rverticalSpacer_1);
720         ui->rverticalLayout->removeItem(ui->rverticalSpacer_2);
721         ui->rverticalLayout->removeItem(ui->rverticalSpacer_3);
722
723         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_0);
724         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_1);
725         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_2);
726         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_3);
727         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_4);
728         ui->topWidget->layout()->addWidget(ui->backButton);
729         ui->topWidget->layout()->addItem(ui->thorizontalSpacer_0);
730         ui->topWidget->layout()->addWidget(ui->deleteButton);
731         ui->topWidget->layout()->addItem(ui->thorizontalSpacer_1);
732         ui->topWidget->layout()->addWidget(ui->addButton);
733         ui->topWidget->layout()->addItem(ui->thorizontalSpacer_2);
734         ui->topWidget->layout()->addWidget(ui->useButton);
735         ui->topWidget->layout()->addItem(ui->thorizontalSpacer_3);
736         ui->topWidget->layout()->addWidget(ui->selectAllButton);
737         ui->topWidget->layout()->addItem(ui->thorizontalSpacer_4);
738         ui->topWidget->layout()->addWidget(ui->moreButton);
739
740         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_0);
741         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_1);
742         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_2);
743         ui->bottomWidget->layout()->addWidget(ui->playerButton);
744         ui->bottomWidget->layout()->addItem(ui->bhorizontalSpacer_0);
745         ui->bottomWidget->layout()->addWidget(ui->viewButton);
746         ui->bottomWidget->layout()->addItem(ui->bhorizontalSpacer_1);
747         ui->bottomWidget->layout()->addWidget(ui->dynamicButton);
748         ui->bottomWidget->layout()->addItem(ui->bhorizontalSpacer_2);
749         ui->bottomWidget->layout()->addWidget(ui->playlistsButton);
750
751         ui->topWidget->show();
752         ui->bottomWidget->show();
753
754         if (_tools_widget->isVisible()) {
755                 ui->moreButton->setIcon(QIcon(":/icons/"+_icons_theme+"/unmore.png"));
756         } else {
757                 ui->moreButton->setIcon(QIcon(":/icons/"+_icons_theme+"/more.png"));
758         }
759 }
760
761 void LibraryForm::_more_button() {
762         if (_tools_widget->isVisible()) {
763                 ui->moreButton->setIcon(QIcon(landscape ? ":/icons/"+_icons_theme+"/unmore_l.png" : ":/icons/"+_icons_theme+"/more.png"));
764                 _tools_widget->hide();
765                 _tools_widget->reset();
766                 cancelSearch();
767         } else {
768                 ui->moreButton->setIcon(QIcon(landscape ? ":/icons/"+_icons_theme+"/more_l.png" : ":/icons/"+_icons_theme+"/unmore.png"));
769                 _tools_widget->show();
770                 _tools_widget->setFocus();
771         }
772 }
773
774
775 void LibraryForm::updateIcons() {
776         Config config;
777         _icons_theme = config.getValue("ui/iconstheme").toString();
778         _tools_widget->updateIcons();
779         if (!ui->addButton->icon().isNull()) {
780                 ui->addButton->setIcon(QIcon(":/icons/"+_icons_theme+"/add.png"));
781         }
782         if (!ui->deleteButton->icon().isNull()) {
783                 ui->deleteButton->setIcon(QIcon(":/icons/"+_icons_theme+"/delete.png"));
784         }
785         if (!ui->useButton->icon().isNull()) {
786                 ui->useButton->setIcon(QIcon(":/icons/"+_icons_theme+"/use.png"));
787         }
788         if (!ui->backButton->icon().isNull()) {
789                 ui->backButton->setIcon(QIcon(":/icons/"+_icons_theme+"/back.png"));
790         }
791         if (!ui->dynamicButton->icon().isNull()) {
792                 ui->dynamicButton->setIcon(QIcon(":/icons/"+_icons_theme+"/dynamic.png"));
793         }
794         if (_tools_widget->isVisible()) {
795                 ui->moreButton->setIcon(QIcon(landscape ? ":/icons/"+_icons_theme+"/more_l.png" : ":/icons/"+_icons_theme+"/unmore.png"));
796         } else {
797                 ui->moreButton->setIcon(QIcon(landscape ? ":/icons/"+_icons_theme+"/unmore_l.png" : ":/icons/"+_icons_theme+"/more.png"));
798         }
799         if (!ui->playlistsButton->icon().isNull()) {
800                 ui->playlistsButton->setIcon(QIcon(":/icons/"+_icons_theme+"/playlists.png"));
801         }
802         ui->playerButton->setIcon(QIcon(":/icons/"+_icons_theme+"/player.png"));
803         if (!ui->viewButton->icon().isNull()) {
804                 ui->viewButton->setIcon(QIcon(":/icons/"+_icons_theme+"/artists.png"));
805         }
806         if (ui->listView->selectionModel()->selectedRows().count() == _model->rowCount()) {
807                 ui->selectAllButton->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"));
808         } else {
809                 ui->selectAllButton->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png"));
810         }
811         _search_in_library_button->setIcon(QIcon(":/icons/"+_icons_theme+"/search.png"));
812         refresh();
813 }
814
815 void LibraryForm::checkGradient() {
816         Config config;
817         if (config.getValue("ui/gradient").toString() == "yes") {
818                 ui->bottomWidget->setStyleSheet(_bottom_gradient);
819                 ui->topWidget->setStyleSheet(_top_gradient);
820         } else {
821                 ui->topWidget->setStyleSheet("");
822                 ui->bottomWidget->setStyleSheet("");
823         }
824 }
825
826 void LibraryForm::_process_selection(QItemSelection selected, QItemSelection deselected) {
827         foreach (QModelIndex id, selected.indexes()) {
828                 if (id.column() == 0) {
829                         _model->item(id.row())->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png"));
830                 }
831                 ui->listView->selectionModel()->select(id, QItemSelectionModel::Select);
832         }
833         foreach (QModelIndex id, deselected.indexes()) {
834                 if (id.column() == 0) {
835                         _model->item(id.row())->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"));
836                 }
837                 ui->listView->selectionModel()->select(id, QItemSelectionModel::Deselect);
838         }
839         if (ui->listView->selectionModel()->selectedRows().count() > 0 ) {
840                 if (_state == STATE_DYNAMIC) {
841                         return;
842                 }
843                 ui->addButton->setEnabled(true);
844                 ui->addButton->setIcon(QIcon(":/icons/"+_icons_theme+"/add.png"));
845                 ui->useButton->setEnabled(true);
846                 ui->useButton->setIcon(QIcon(":/icons/"+_icons_theme+"/use.png"));
847                 if (_state == STATE_PLAYLIST || (_state == STATE_PLAYLIST_TRACK && !_is_dynamic)
848                         || (_state == STATE_PLAYLIST_TRACK && _is_favorites)) {
849                         ui->deleteButton->setEnabled(true);
850                         ui->deleteButton->setIcon(QIcon(":/icons/"+_icons_theme+"/delete.png"));
851                 }
852         } else {
853                 ui->addButton->setEnabled(false);
854                 ui->addButton->setIcon(QIcon());
855                 if (_state != STATE_PLAYLIST_TRACK) {
856                         ui->useButton->setEnabled(false);
857                         ui->useButton->setIcon(QIcon());
858                 }
859                 ui->deleteButton->setEnabled(false);
860                 ui->deleteButton->setIcon(QIcon());
861         }
862 }
863
864 void LibraryForm::_process_dblclick(QModelIndex id) {
865         if (id.column() == 0)
866                 return;
867         if (_state == STATE_TRACK || _state == STATE_PLAYLIST_TRACK || _state == STATE_SEARCH) {
868                 Playlist cur = _lib->getCurrentPlaylist();
869                 Track track = _current_tracks.at(id.row());
870                 cur.addTrack(track);
871                 _lib->saveCurrentPlaylist(cur);
872                 emit refreshPlayer();
873                 emit addAndPlay(track);
874                 ui->listView->clearSelection();
875         }
876 }
877
878 void LibraryForm::_search_button(bool state) {
879         ui->moreButton->setEnabled(!state);
880         _tools_widget->toggleArrows(!state);
881         ui->backButton->setEnabled(!state);
882         ui->backButton->setIcon(state ? QIcon() : QIcon(":/icons/"+_icons_theme+"/back.png"));
883         _tools_widget->setFocus();
884         _tools_widget->reset();
885         if (state) {
886                 ui->listLabel->setText(tr("Search in library"));
887                 ui->deleteButton->setIcon(QIcon());
888                 ui->deleteButton->setEnabled(false);
889                 ui->useButton->setIcon(QIcon());
890                 ui->useButton->setEnabled(false);
891                 ui->viewButton->setIcon(QIcon());
892                 ui->viewButton->setEnabled(false);
893                 ui->dynamicButton->setIcon(QIcon());
894                 ui->dynamicButton->setEnabled(false);
895                 ui->playlistsButton->setIcon(QIcon());
896                 ui->playlistsButton->setEnabled(false);
897                 disconnect(_tools_widget, SIGNAL(search(QString)), this, SLOT(search(QString)));
898                 connect(_tools_widget, SIGNAL(search(QString)), this, SLOT(_search_in_library(QString)));
899                 _model->clear();
900                 _state = STATE_SEARCH;
901         } else {
902                 ui->viewButton->setIcon(QIcon(":/icons/"+_icons_theme+"/artists.png"));
903                 ui->viewButton->setEnabled(true);
904                 ui->dynamicButton->setIcon(QIcon(":/icons/"+_icons_theme+"/dynamic.png"));
905                 ui->dynamicButton->setEnabled(true);
906                 ui->playlistsButton->setIcon(QIcon(":/icons/"+_icons_theme+"/playlists.png"));
907                 ui->playlistsButton->setEnabled(true);
908                 _view_button();
909                 connect(_tools_widget, SIGNAL(search(QString)), this, SLOT(search(QString)));
910                 disconnect(_tools_widget, SIGNAL(search(QString)), this, SLOT(_search_in_library(QString)));
911         }
912 }
913
914 void LibraryForm::_search_in_library(QString pattern) {
915         pattern = pattern.trimmed();
916         if (pattern.isEmpty()) {
917                 _model->clear();
918                 return;
919         }
920         _current_tracks = _lib->searchTracks(pattern);
921         __fill_model_tracks(_model, _current_tracks, _icons_theme);
922         ui->listView->setColumnWidth(0, 70);
923         ui->listView->scrollToTop();
924 }
925
926 void LibraryForm::updateTranslations() {
927         ui->retranslateUi(this);
928 }