Implemented search
[someplayer] / src / libraryform.cpp
1 #include "libraryform.h"
2 #include "ui_libraryform.h"
3 #include "library.h"
4 #include <QStandardItemModel>
5 #include <QStandardItem>
6 #include <QModelIndex>
7 #include <QModelIndexList>
8 #include "track.h"
9 #include "playlist.h"
10 #include <QDebug>
11 #include <QTime>
12 #include <QQueue>
13
14 using namespace SomePlayer::DataObjects;
15
16 inline QString __format_track_string(TrackMetadata meta) {
17         int minutes = meta.length() / 60;
18         int seconds = meta.length() % 60;
19         QTime time(0, minutes, seconds);
20         return QString("[%1] %2").arg(time.toString("mm:ss")).arg(meta.title());
21
22 }
23
24 inline void __fill_model(QStandardItemModel *model, QList<QString> data) {
25         model->clear();
26         int count = data.count();
27         model->setRowCount(count);
28         for (int i = 0; i < count; i++) {
29                 model->setItem(i, 0, new QStandardItem(data.at(i)));
30         }
31 }
32
33 inline void __fill_model_tracks (QStandardItemModel *model, QList<Track> tracks) {
34         int count = tracks.count();
35         model->setRowCount(count);
36         for (int i = 0; i < count; i++) {
37                 TrackMetadata meta = tracks.at(i).metadata();
38                 model->setItem(i, 0, new QStandardItem(__format_track_string(meta)));
39         }
40 }
41
42 LibraryForm::LibraryForm(Library *lib, QWidget *parent) :
43     QWidget(parent),
44     ui(new Ui::LibraryForm)
45 {
46         _lib = lib;
47         _model = new QStandardItemModel(this);
48         _state = STATE_NONE;
49     ui->setupUi(this);
50         connect(ui->playerButton, SIGNAL(clicked()), this, SLOT(_player()));
51         connect(ui->viewButton, SIGNAL(clicked()), this, SLOT(_view_button()));
52         connect(ui->playlistsButton, SIGNAL(clicked()), this, SLOT(_playlists_button()));
53         connect(ui->dynamicButton, SIGNAL(clicked()), this, SLOT(_dynamic_button()));
54         connect(ui->listView, SIGNAL(clicked(QModelIndex)), this, SLOT(_process_list_click(QModelIndex)));
55         connect(ui->addButton, SIGNAL(clicked()), this, SLOT(_add_button()));
56         connect(ui->backButton, SIGNAL(clicked()), this, SLOT(_back_button()));
57         connect(ui->deleteButton, SIGNAL(clicked()), this, SLOT(_delete_button()));
58         connect(ui->useButton, SIGNAL(clicked()), this, SLOT(_use_button()));
59         _view_button();
60 }
61
62 LibraryForm::~LibraryForm()
63 {
64         _lib->saveCurrentPlaylist(_lib->getCurrentPlaylist());
65     delete ui;
66 }
67
68 void LibraryForm::_player() {
69         emit player();
70 }
71
72 void LibraryForm::_view_button() {
73         QList<QString> artitst = _lib->getArtists();
74         __fill_model(_model, artitst);
75         ui->listView->setModel(_model);
76         _state = STATE_ARTIST;
77         ui->backButton->hide();
78         ui->listLabel->setText("Artists");
79         ui->addButton->show();
80         ui->deleteButton->hide();
81         ui->useButton->hide();
82 }
83
84 void LibraryForm::_dynamic_button() {
85         ui->useButton->hide();
86         ui->backButton->hide();
87         ui->addButton->show();
88         ui->deleteButton->hide();
89         _model->clear();
90         _model->setRowCount(4);
91         _model->setItem(0, new QStandardItem("Favorites"));
92         _model->setItem(1, new QStandardItem("Most played"));
93         _model->setItem(2, new QStandardItem("Never played"));
94         _model->setItem(3, new QStandardItem("Recently added"));
95         _state = STATE_DYNAMIC;
96 }
97
98 void LibraryForm::_process_list_click(QModelIndex index) {
99         if (_state == STATE_NONE) return;
100         QString data = index.data().toString();
101         switch (_state) {
102         case STATE_ARTIST:
103                 __fill_model(_model, _lib->getAlbumsForArtist(data));
104                 _current_artist = data;
105                 _state = STATE_ALBUM;
106                 ui->backButton->show();
107                 ui->listLabel->setText(QString("Albums by \"%1\"").arg(_current_artist));
108                 break;
109         case STATE_ALBUM:
110                 _current_album = data;
111                 _current_tracks = _lib->getTracksForAlbum(data, _current_artist);
112                 __fill_model_tracks(_model, _current_tracks);
113                 _state = STATE_TRACK;
114                 ui->backButton->show();
115                 ui->listLabel->setText(QString("Tracks from \"%1\" by \"%2\"").arg(_current_album).arg(_current_artist));
116                 break;
117         case STATE_PLAYLIST:
118                 {
119                         _current_playlist = _lib->getPlaylist(data);
120                         _current_tracks = _current_playlist.tracks();
121                         __fill_model_tracks(_model, _current_tracks);
122                         _state = STATE_PLAYLIST_TRACK;
123                         ui->backButton->show();
124                         ui->deleteButton->show();
125                         ui->useButton->show();
126                         ui->listLabel->setText(QString("Tracks in playlist \"%1\"").arg(data));
127                 }
128                 break;
129         case STATE_DYNAMIC:
130                 {
131                         switch(index.row()) {
132                         case 0: //favorites
133                                 _current_playlist = _lib->getFavorites();
134                                 break;
135                         case 1: //most played
136                                 _current_playlist = _lib->getMostPlayed();
137                                 break;
138                         case 2: //never played
139                                 _current_playlist = _lib->getNeverPlayed();
140                         case 3: //recently added
141                                 _current_playlist = _lib->getRecentlyAdded();
142                                 break;
143                         default:
144                                 return;
145                         }
146                         _current_tracks = _current_playlist.tracks();
147                         __fill_model_tracks(_model, _current_tracks);
148                         _state = STATE_PLAYLIST_TRACK;
149                         ui->backButton->show();
150                         ui->useButton->show();
151                         ui->addButton->show();
152                         ui->listLabel->setText(_current_playlist.name());
153                 }
154         default:
155                 return;
156         }
157 }
158
159 void LibraryForm::_add_button() {
160         if (_state == STATE_NONE) return;
161         QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
162         ui->listView->selectionModel()->clearSelection();
163         emit busy(QString("<H1>Adding... Please wait</H1>"));
164         switch (_state) {
165         case STATE_ARTIST:
166                 foreach (QModelIndex id, selected) {
167                         _add_artist(id.data().toString());
168                 }
169                 break;
170         case STATE_ALBUM:
171                 foreach (QModelIndex id, selected) {
172                         _add_album(_current_artist, id.data().toString());
173                 }
174                 break;
175         case STATE_TRACK:
176                 foreach (QModelIndex id, selected) {
177                         _add_track(_current_tracks.at(id.row()));
178                 }
179                 break;
180         case STATE_PLAYLIST:
181                 foreach (QModelIndex id, selected) {
182                         _add_playlist(id.data().toString());
183                 }
184                 break;
185         case STATE_PLAYLIST_TRACK:
186                 foreach (QModelIndex id, selected) {
187                         _add_track(_current_tracks.at(id.row()));
188                 }
189                 break;
190         default:
191                 emit done();
192                 return;
193         }
194         emit done();
195 }
196
197
198 void LibraryForm::_add_artist(QString artist) {
199         QList<QString> albums = _lib->getAlbumsForArtist(artist);
200         foreach(QString album, albums) {
201                 _add_album(artist, album);
202         }
203 }
204
205 void LibraryForm::_add_album(QString artist, QString album) {
206         QList<Track> tracks = _lib->getTracksForAlbum(album, artist);
207         foreach(Track track, tracks) {
208                 _add_track(track);
209         }
210 }
211
212 void LibraryForm::_add_track(Track track) {
213         Playlist current = _lib->getCurrentPlaylist();
214         current.addTrack(track);
215         _lib->saveCurrentPlaylist(current);
216 }
217
218 void LibraryForm::_add_playlist(QString name) {
219         Playlist playlist = _lib->getPlaylist(name);
220         QList<Track> tracks = playlist.tracks();
221         foreach (Track track, tracks) {
222                 _add_track(track);
223         }
224 }
225
226 void LibraryForm::_back_button() {
227         switch (_state) {
228         case STATE_ALBUM:
229                 _view_button();
230                 break;
231         case STATE_TRACK:
232                 __fill_model(_model, _lib->getAlbumsForArtist(_current_artist));
233                 _state = STATE_ALBUM;
234                 ui->listLabel->setText(QString("Albums by \"%1\"").arg(_current_artist));
235                 break;
236         case STATE_PLAYLIST_TRACK:
237                 _playlists_button();
238         default:
239                 return;
240         }
241 }
242
243 void LibraryForm::_playlists_button() {
244         QList<QString> playlists = _lib->getPlaylistsNames();
245         __fill_model(_model, playlists);
246         ui->listView->setModel(_model);
247         _state = STATE_PLAYLIST;
248         ui->backButton->hide();
249         ui->listLabel->setText("Playlists");
250         ui->addButton->hide();
251         ui->deleteButton->show();
252         ui->useButton->hide();
253 }
254
255 void LibraryForm::_delete_button() {
256         if (_state == STATE_PLAYLIST_TRACK) {
257                 QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
258                 ui->listView->selectionModel()->clearSelection();
259                 QQueue<int> to_delete;
260                 foreach (QModelIndex id, selected) {
261                         _delete_track(_current_tracks.at(id.row()));
262                         to_delete.append(id.row());
263                 }
264                 qSort(to_delete);
265                 int count = to_delete.count();
266                 for (int i = count-1; i >= 0; i--) {
267                         _current_tracks.removeAt(to_delete.at(i));
268                 }
269                 __fill_model_tracks(_model, _current_tracks);
270         } else if (_state == STATE_PLAYLIST) {
271                 QModelIndexList selected = ui->listView->selectionModel()->selectedIndexes();
272                 QQueue<int> to_delete;
273                 foreach (QModelIndex id, selected) {
274                         to_delete.append(id.row());
275                 }
276                 qSort(to_delete);
277                 int count = to_delete.count();
278                 for (int i = count-1; i >= 0; i--) {
279                         QString name = _model->item(to_delete.at(i))->text();
280                         if (name != _CURRENT_PLAYLIST_SUBST_) {
281                                 qDebug() << "deleting " << name;
282                                 _lib->removePlaylist(name);
283                                 _model->removeRow(to_delete.at(i));
284                         }
285                 }
286         }
287 }
288
289 void LibraryForm::_delete_track(Track track) {
290         Playlist current = _lib->getCurrentPlaylist();
291         current.removeTrack(track);
292         _lib->saveCurrentPlaylist(current);
293 }
294
295 void LibraryForm::_use_button() {
296         _lib->saveCurrentPlaylist(_current_playlist);
297 }
298
299 void LibraryForm::search(QString &pattern) {
300         _search_pattern = pattern;
301         _search_current_id = -1;
302         nextItem();
303 }
304
305 void LibraryForm::nextItem() {
306         QString data = _model->index(_search_current_id, 0).data().toString();
307         for (int i = _search_current_id+1; i < _model->rowCount(); i++) {
308                 data = _model->index(i, 0).data().toString();
309                 if (data.contains(_search_pattern, Qt::CaseInsensitive)) {
310                         _search_current_id = i;
311                         break;
312                 }
313         }
314         QModelIndex id = _model->index(_search_current_id, 0);
315         ui->listView->selectionModel()->clearSelection();
316         ui->listView->selectionModel()->select(id, QItemSelectionModel::Select);
317         ui->listView->scrollTo(id);
318 }
319
320 void LibraryForm::prevItem() {
321         QString data = _model->index(_search_current_id, 0).data().toString();
322         for (int i = _search_current_id-1; i >= 0; i--) {
323                 data = _model->index(i, 0).data().toString();
324                 if (data.contains(_search_pattern, Qt::CaseInsensitive)) {
325                         _search_current_id = i;
326                         break;
327                 }
328         }
329         QModelIndex id = _model->index(_search_current_id, 0);
330         ui->listView->selectionModel()->clearSelection();
331         ui->listView->selectionModel()->select(id, QItemSelectionModel::Select);
332         ui->listView->scrollTo(id);
333 }
334
335 void LibraryForm::cancelSearch() {
336         _search_pattern = "";
337         ui->listView->selectionModel()->clearSelection();
338 }