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