Ability to sort cur.playlist by long tap on it
[someplayer] / src / playlistsortform.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 "playlistsortform.h"
21 #include "ui_playlistsortform.h"
22 #include <QTime>
23 #include "track.h"
24 #include <QDebug>
25 #include "config.h"
26
27 using namespace SomePlayer::DataObjects;
28 using namespace SomePlayer::Storage;
29
30 inline void __fill_model(QStandardItemModel *_model, Playlist playlist) {
31         _model->clear();
32         QList<Track> tracks = playlist.tracks();
33         int count = tracks.count();
34         _model->setRowCount(count);
35         _model->setColumnCount(2);
36         QTime time;
37         for (int i = 0; i < count; i++) {
38                 TrackMetadata meta = tracks.at(i).metadata();
39                 time.setHMS(0, meta.length()/60, meta.length() % 60);
40                 QString t = meta.title()+"#_#"+meta.artist()+"#_#"+meta.album()+"#_#"+time.toString("mm:ss");
41                 _model->setItem(i, 1, new QStandardItem(t));
42                 _model->setItem(i, 0, new QStandardItem("##deselect_all.png"));
43         }
44 }
45
46 PlaylistSortForm::PlaylistSortForm(QWidget *parent) :
47                 QWidget(parent),
48                 ui(new Ui::PlaylistSortForm)
49 {
50         ui->setupUi(this);
51         setAttribute(Qt::WA_Maemo5StackedWindow);
52         setWindowFlags(Qt::Window | windowFlags());
53         _track_renderer = new TrackRenderer(this);
54         _track_renderer->setActiveRow(-1);
55         _track_renderer->setSearchRow(-1);
56         ui->playlistView->setItemDelegateForColumn(0, _track_renderer);
57         ui->playlistView->setItemDelegateForColumn(1, _track_renderer);
58         _model = new QStandardItemModel(this);
59         ui->playlistView->setModel(_model);
60         _top_gradient = ui->topWidget->styleSheet();
61         _bottom_gradient = ui->bottomWidget->styleSheet();
62
63         connect(ui->doneButton, SIGNAL(clicked()), this, SLOT(done()));
64         connect(ui->playlistView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
65                 this, SLOT(_process_selection(QItemSelection,QItemSelection)));
66         connect(ui->moveDownButton, SIGNAL(clicked()), this, SLOT(moveDown()));
67         connect(ui->moveTopButton, SIGNAL(clicked()), this, SLOT(moveUp()));
68         connect(ui->sortAlphAscButton, SIGNAL(clicked()), this, SLOT(sortAlphAsc()));
69         connect(ui->sortAlphDescButton, SIGNAL(clicked()), this, SLOT(sortAlphDesc()));
70         connect(ui->shuffleButton, SIGNAL(clicked()), this, SLOT(shuffle()));
71         connect(ui->artistsButton, SIGNAL(clicked()), this, SLOT(sortArtist()));
72 }
73
74 PlaylistSortForm::~PlaylistSortForm()
75 {
76         delete ui;
77 }
78
79 void PlaylistSortForm::done() {
80         emit playlistChanged();
81         hide();
82 }
83
84 void PlaylistSortForm::setPlaylist(Playlist playlist) {
85         _playlist = playlist;
86         updateView();
87 }
88
89 Playlist PlaylistSortForm::getPlaylist() {
90         return _playlist;
91 }
92
93 void PlaylistSortForm::updateView() {
94         __fill_model(_model, _playlist);
95         ui->playlistView->setColumnWidth(0, 50);
96 }
97
98 void PlaylistSortForm::_process_selection(QItemSelection selected, QItemSelection deselected) {
99         foreach (QModelIndex id, selected.indexes()) {
100                 if (id.column() == 0) {
101                         _model->item(id.row(), 0)->setText("##select_all.png");
102                 }
103                 ui->playlistView->selectionModel()->select(id, QItemSelectionModel::Select);
104         }
105         foreach (QModelIndex id, deselected.indexes()) {
106                 if (id.column() == 0) {
107                         _model->item(id.row(), 0)->setText("##deselect_all.png");
108                 }
109                 ui->playlistView->selectionModel()->select(id, QItemSelectionModel::Deselect);
110         }
111 }
112
113 void PlaylistSortForm::moveDown() {
114         QModelIndexList idx = ui->playlistView->selectionModel()->selectedIndexes();
115         if (idx.isEmpty()) {
116                 return;
117         }
118         QList<int> rows;
119         foreach (QModelIndex id, idx) {
120                 if (id.column() == 1) {
121                         rows << id.row();
122                 }
123         }
124         _move(rows, 1);
125 }
126
127 void PlaylistSortForm::moveUp() {
128         QModelIndexList idx = ui->playlistView->selectionModel()->selectedIndexes();
129         if (idx.isEmpty()) {
130                 return;
131         }
132         QList<int> rows;
133         foreach (QModelIndex id, idx) {
134                 if (id.column() == 1) {
135                         rows << id.row();
136                 }
137         }
138         _move(rows, -1);
139 }
140
141 void PlaylistSortForm::sortAlphAsc() {
142         QList<Track> tracks = _playlist.tracks();
143         qSort(tracks);
144         _playlist.setTracks(tracks);
145         updateView();
146 }
147
148 void PlaylistSortForm::sortAlphDesc() {
149         QList<Track> tracks = _playlist.tracks();
150         qSort(tracks);
151         for(int i = 0; i < (tracks.size()/2); i++) {
152                 tracks.swap(i,tracks.size()-(1+i));
153         }
154         _playlist.setTracks(tracks);
155         updateView();
156 }
157
158 void PlaylistSortForm::sortArtist() {
159         QList<Track> tracks = _playlist.tracks();
160         QList<Track> ntracks;
161         // first step: artists
162         QMap<QString, QList<Track> > artists_tracks;
163         foreach (Track t, tracks) {
164                 artists_tracks[t.metadata().artist()].append(t);;
165         }
166         // second step: albums;
167         QMap<QString, QList<Track> > album_tracks;
168         QList<QString> artists = artists_tracks.keys();
169         qSort(artists);
170         foreach (QString artist, artists) {
171                 album_tracks.clear();
172                 foreach (Track t, artists_tracks[artist]) {
173                         album_tracks[t.metadata().album()].append(t);
174                 }
175                 QList<QString> albums = album_tracks.keys();
176                 qSort(albums);
177                 foreach (QString album, albums) {
178                         qWarning() << album;
179                         foreach (Track t, album_tracks[album]) {
180                                 ntracks << t;
181                         }
182                 }
183         }
184         _playlist.setTracks(ntracks);
185         updateView();
186 }
187
188 void PlaylistSortForm::shuffle() {
189         qsrand(QTime::currentTime().msec());
190         QList<Track> tracks = _playlist.tracks();
191         QList<Track> ntracks;
192         int size = tracks.size();
193         int pos = 0;
194         for (int i = 0; i < size; i++) {
195                 pos = qrand() % tracks.count();
196                 ntracks << tracks.at(pos);
197                 tracks.removeAt(pos);
198         }
199         _playlist.setTracks(ntracks);
200         updateView();
201 }
202
203 void PlaylistSortForm::_move(QList<int> rows, int diff) {
204         qSort(rows);
205         QList<Track> tracks = _playlist.tracks();
206         if ((diff > 0 && (rows.last() == tracks.count()-diff)) ||
207             (diff < 0 && (rows.first() == -diff - 1))) {
208                 return;
209         }
210         if (diff > 0) {
211                 for (int i = rows.count()-1; i>=0; i--) {
212                         tracks.swap(rows[i], rows[i]+diff);
213                         rows[i] += diff;
214                 }
215         } else {
216                 for (int i = 0; i < rows.count(); i++) {
217                         tracks.swap(rows[i], rows[i]+diff);
218                         rows[i] += diff;
219                 }
220         }
221         _playlist.setTracks(tracks);
222         updateView();
223         foreach (int i, rows) {
224                 ui->playlistView->selectRow(i);
225         }
226         ui->playlistView->scrollTo(_model->index(rows[rows.count()/2], 0), QAbstractItemView::PositionAtCenter);
227 }
228
229 void PlaylistSortForm::landscapeMode() {
230         ui->topWidget->hide();
231         ui->bottomWidget->hide();
232         ui->bhorWidget->hide();
233
234         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_0);
235         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_1);
236         ui->topWidget->layout()->removeWidget(ui->sortAlphAscButton);
237         ui->topWidget->layout()->removeWidget(ui->sortAlphDescButton);
238         ui->topWidget->layout()->removeWidget(ui->artistsButton);
239
240         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_0);
241         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_1);
242         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_2);
243         ui->bottomWidget->layout()->removeWidget(ui->doneButton);
244         ui->bottomWidget->layout()->removeWidget(ui->moveDownButton);
245         ui->bottomWidget->layout()->removeWidget(ui->moveTopButton);
246         ui->bottomWidget->layout()->removeWidget(ui->shuffleButton);
247
248         ui->bhorWidget->layout()->removeWidget(ui->doneButton);
249         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_0);
250         ui->bhorWidget->layout()->removeWidget(ui->moveTopButton);
251         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_1);
252         ui->bhorWidget->layout()->removeWidget(ui->sortAlphAscButton);
253         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_2);
254         ui->bhorWidget->layout()->removeWidget(ui->artistsButton);
255         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_3);
256         ui->bhorWidget->layout()->removeWidget(ui->sortAlphDescButton);
257         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_4);
258         ui->bhorWidget->layout()->removeWidget(ui->moveDownButton);
259         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_5);
260         ui->bhorWidget->layout()->removeWidget(ui->shuffleButton);
261
262         ui->bhorWidget->layout()->addWidget(ui->doneButton);
263         ui->bhorWidget->layout()->addItem(ui->chorizontalSpacer_0);
264         ui->bhorWidget->layout()->addWidget(ui->sortAlphAscButton);
265         ui->bhorWidget->layout()->addItem(ui->chorizontalSpacer_1);
266         ui->bhorWidget->layout()->addWidget(ui->moveTopButton);
267         ui->bhorWidget->layout()->addItem(ui->chorizontalSpacer_2);
268         ui->bhorWidget->layout()->addWidget(ui->artistsButton);
269         ui->bhorWidget->layout()->addItem(ui->chorizontalSpacer_3);
270         ui->bhorWidget->layout()->addWidget(ui->moveDownButton);
271         ui->bhorWidget->layout()->addItem(ui->chorizontalSpacer_4);
272         ui->bhorWidget->layout()->addWidget(ui->sortAlphDescButton);
273         ui->bhorWidget->layout()->addItem(ui->chorizontalSpacer_5);
274         ui->bhorWidget->layout()->addWidget(ui->shuffleButton);
275
276         ui->bhorWidget->show();
277 }
278
279 void PlaylistSortForm::portraitMode() {
280         ui->topWidget->hide();
281         ui->bottomWidget->hide();
282         ui->bhorWidget->hide();
283
284         ui->bhorWidget->layout()->removeWidget(ui->doneButton);
285         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_0);
286         ui->bhorWidget->layout()->removeWidget(ui->moveTopButton);
287         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_1);
288         ui->bhorWidget->layout()->removeWidget(ui->sortAlphAscButton);
289         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_2);
290         ui->bhorWidget->layout()->removeWidget(ui->artistsButton);
291         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_3);
292         ui->bhorWidget->layout()->removeWidget(ui->sortAlphDescButton);
293         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_4);
294         ui->bhorWidget->layout()->removeWidget(ui->moveDownButton);
295         ui->bhorWidget->layout()->removeItem(ui->chorizontalSpacer_5);
296         ui->bhorWidget->layout()->removeWidget(ui->shuffleButton);
297
298         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_0);
299         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_1);
300         ui->topWidget->layout()->removeWidget(ui->sortAlphAscButton);
301         ui->topWidget->layout()->removeWidget(ui->sortAlphDescButton);
302         ui->topWidget->layout()->removeWidget(ui->artistsButton);
303
304         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_0);
305         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_1);
306         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_2);
307         ui->bottomWidget->layout()->removeWidget(ui->doneButton);
308         ui->bottomWidget->layout()->removeWidget(ui->moveDownButton);
309         ui->bottomWidget->layout()->removeWidget(ui->moveTopButton);
310         ui->bottomWidget->layout()->removeWidget(ui->shuffleButton);
311
312         ui->topWidget->layout()->addWidget(ui->sortAlphAscButton);
313         ui->topWidget->layout()->addItem(ui->thorizontalSpacer_0);
314         ui->topWidget->layout()->addWidget(ui->artistsButton);
315         ui->topWidget->layout()->addItem(ui->thorizontalSpacer_1);
316         ui->topWidget->layout()->addWidget(ui->sortAlphDescButton);
317
318         ui->bottomWidget->layout()->addWidget(ui->doneButton);
319         ui->bottomWidget->layout()->addItem(ui->bhorizontalSpacer_0);
320         ui->bottomWidget->layout()->addWidget(ui->moveDownButton);
321         ui->bottomWidget->layout()->addItem(ui->bhorizontalSpacer_1);
322         ui->bottomWidget->layout()->addWidget(ui->moveTopButton);
323         ui->bottomWidget->layout()->addItem(ui->bhorizontalSpacer_2);
324         ui->bottomWidget->layout()->addWidget(ui->shuffleButton);
325
326         ui->topWidget->show();
327         ui->bottomWidget->show();
328 }
329
330 void PlaylistSortForm::updateTranslations() {
331         ui->retranslateUi(this);
332 }
333
334 void PlaylistSortForm::updateGradiend() {
335         Config config;
336         if (config.getValue("ui/gradient").toString() == "yes") {
337                 ui->bottomWidget->setStyleSheet(_bottom_gradient);
338                 ui->topWidget->setStyleSheet(_top_gradient);
339         } else {
340                 ui->topWidget->setStyleSheet("");
341                 ui->bottomWidget->setStyleSheet("");
342         }
343 }
344
345 void PlaylistSortForm::updateIcons() {
346         Config config;
347         QString icons_theme = config.getValue("ui/iconstheme").toString();
348         ui->doneButton->setIcon(QIcon(":/icons/"+icons_theme+"/use.png"));
349         ui->moveDownButton->setIcon(QIcon(":/icons/"+icons_theme+"/arrow_bottom.png"));
350         ui->moveTopButton->setIcon(QIcon(":/icons/"+icons_theme+"/arrow_top.png"));
351         ui->shuffleButton->setIcon(QIcon(":/icons/"+icons_theme+"/random_on.png"));
352         ui->sortAlphAscButton->setIcon(QIcon(":/icons/"+icons_theme+"/sort_alpha_asc.png"));
353         ui->sortAlphDescButton->setIcon(QIcon(":/icons/"+icons_theme+"/sort_alpha_desc.png"));
354         ui->artistsButton->setIcon(QIcon(":/icons/"+icons_theme+"/artists.png"));
355 }