Version bump
[someplayer] / src / directoryview.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 "directoryview.h"
21 #include "ui_directoryview.h"
22 #include <QDir>
23 #include <QFileInfo>
24 #include "someplayer.h"
25 #include <QDebug>
26 #include <QRegExp>
27 #include "config.h"
28
29 using namespace SomePlayer::Storage;
30 using namespace SomePlayer::DataObjects;
31
32 DirectoryView::DirectoryView(QWidget *parent) :
33                 QWidget(parent),
34                 ui(new Ui::DirectoryView)
35 {
36         ui->setupUi(this);
37         Config config;
38         _icons_theme = config.getValue("ui/iconstheme").toString();
39         REGISTERED_FILE_EXTENSIONS << "mp3" << "flac" << "wma" << "aac" << "ogg" << "asf" << "ape" << "wav" << "m4a";
40         setWindowFlags(windowFlags() | Qt::Window);
41         setAttribute(Qt::WA_Maemo5StackedWindow);
42         _model = new QStandardItemModel(0, 2, this);
43         ui->dirView->setModel(_model);
44         ui->dirView->setColumnHidden(2, true);
45         _current_dir = QDir::homePath();
46         _tagresolver = new TagResolver(this);
47         _mediascanner = new MediaScanner(this);
48
49         ui->addButton->setEnabled(false);
50         ui->addButton->setIcon(QIcon());
51         ui->useButton->setEnabled(false);
52         ui->useButton->setIcon(QIcon());
53
54         ui->progressBar->hide();
55
56         _home();
57         connect(ui->backButton, SIGNAL(clicked()), this, SLOT(_back()));
58         connect(ui->dirView, SIGNAL(clicked(QModelIndex)), this, SLOT(_process_click(QModelIndex)));
59         connect(ui->dirView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(_process_dblclick(QModelIndex)));
60         connect(ui->dirView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this,
61                 SLOT(_process_selection(QItemSelection,QItemSelection)));
62         connect(ui->homeButton, SIGNAL(clicked()), this, SLOT(_home()));
63         connect(ui->selectToggleButton, SIGNAL(clicked()), this, SLOT(_toggle_selection()));
64         connect(ui->addButton, SIGNAL(clicked()), this, SLOT(_add()));
65         connect(ui->useButton, SIGNAL(clicked()), this, SLOT(_use()));
66         connect(_tagresolver, SIGNAL(decoded(Track)), this, SLOT(_add_track(Track)));
67         connect(_tagresolver, SIGNAL(done()), this, SLOT(_done()));
68         connect(ui->playerButton, SIGNAL(clicked()), this, SLOT(hide()));
69         _top_gradient = ui->topWidget->styleSheet();
70         _bottom_gradient = ui->bottomWidget->styleSheet();
71 }
72
73 DirectoryView::~DirectoryView()
74 {
75         delete ui;
76 }
77
78 void DirectoryView::readDir(QString path, QString pathToScroll) {
79         QDir dir(path);
80         _current_dir = dir.absoluteFilePath(path);
81         _directories.clear();
82         _files.clear();
83         QList<QString> dirnames;
84         QList<QString> filenames;
85         QFileInfoList items = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden);
86         foreach (QFileInfo info, items) {
87                 if (info.isDir()) {
88                         if (info.fileName().startsWith(".")) {
89                                 if (info.fileName() == ".sounds") {
90                                         _directories << info.absoluteFilePath();
91                                         dirnames << tr("Audioclips");
92                                 }
93                         } else {
94                                 _directories << info.absoluteFilePath();
95                                 dirnames << info.fileName();
96                         }
97                 } else {
98                         if (REGISTERED_FILE_EXTENSIONS.contains(info.suffix().toLower())) {
99                                 _files << info.absoluteFilePath();
100                                 filenames << info.fileName();
101                         }
102                 }
103         }
104         _model->setRowCount(dirnames.count() + filenames.count());
105         int i = 0;
106         foreach (QString str, dirnames) {
107                 _model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), ""));
108                 _model->setItem(i, 1, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/folder.png"), str));
109                 i++;
110         }
111         foreach (QString str, filenames) {
112                 _model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), ""));
113                 _model->setItem(i, 1, new QStandardItem(str));
114                 i++;
115         }
116         ui->dirView->setColumnWidth(0, 70);
117         ui->addButton->setEnabled(false);
118         ui->addButton->setIcon(QIcon());
119         ui->useButton->setEnabled(false);
120         ui->useButton->setIcon(QIcon());
121         if (pathToScroll.isEmpty()) {
122                 ui->dirView->scrollToTop();
123                 return;
124         }
125         int row = _directories.indexOf(pathToScroll);
126         if (row >= 0 && row < _model->rowCount()) {
127                 QModelIndex id = _model->index(row, 1);
128                 ui->dirView->scrollTo(id, QAbstractItemView::PositionAtCenter);
129         }
130 }
131
132 void DirectoryView::_back() {
133         QDir current(_current_dir);
134         current.cdUp();
135         QString dir_to_center = "";
136         if (_nav_history.size() > 0) {
137                 dir_to_center = _nav_history.pop();
138         }
139         readDir(current.path(), dir_to_center);
140 }
141
142 void DirectoryView::_process_click(QModelIndex index) {
143         if (index.column() == 0) {
144         } else {
145                 if (index.row() < _directories.count()) {
146                         _current_dir = _directories.at(index.row());
147                         readDir(_current_dir);
148                         _nav_history.push(_current_dir);
149                         return;
150                 }
151         }
152 }
153
154 void DirectoryView::_process_dblclick(QModelIndex index) {
155         if (index.column() == 0) {
156         } else {
157                 if (index.row() >= _directories.count()) {
158                         QString filename = _files.at(index.row() - _directories.count());
159                         Track track = _tagresolver->decodeOne(filename);
160                         emit addAndPlay(track);
161                         return;
162                 }
163         }
164 }
165
166 void DirectoryView::_process_selection(QItemSelection selected, QItemSelection deselected) {
167         foreach (QModelIndex id, selected.indexes()) {
168                 if (id.column() == 0) {
169                         _model->item(id.row())->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png"));
170                 }
171                 ui->dirView->selectionModel()->select(id, QItemSelectionModel::Select);
172         }
173         foreach (QModelIndex id, deselected.indexes()) {
174                 if (id.column() == 0) {
175                         _model->item(id.row())->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"));
176                 }
177                 ui->dirView->selectionModel()->select(id, QItemSelectionModel::Deselect);
178         }
179         if (ui->dirView->selectionModel()->selectedRows().count() > 0) {
180                 ui->addButton->setEnabled(true);
181                 ui->addButton->setIcon(QIcon(":/icons/"+_icons_theme+"/add.png"));
182                 ui->useButton->setEnabled(true);
183                 ui->useButton->setIcon(QIcon(":/icons/"+_icons_theme+"/use.png"));
184         } else {
185                 ui->addButton->setEnabled(false);
186                 ui->addButton->setIcon(QIcon());
187                 ui->useButton->setEnabled(false);
188                 ui->useButton->setIcon(QIcon());
189         }
190 }
191
192 void DirectoryView::_home() {
193         _current_dir = QDir::homePath();
194         homeScreen();
195         _nav_history.clear();
196 }
197
198 void DirectoryView::_toggle_selection() {
199         if (ui->dirView->selectionModel()->selectedRows().count() == _model->rowCount()) {
200                 ui->dirView->clearSelection();
201                 ui->selectToggleButton->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png"));
202         } else {
203                 ui->dirView->selectAll();
204                 ui->selectToggleButton->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"));
205         }
206 }
207
208 void DirectoryView::_add() {
209         QModelIndexList selected = ui->dirView->selectionModel()->selectedRows(1);
210         QStringList files;
211         QStringList directories;
212         foreach (QModelIndex index, selected) {
213                 if (index.row() >= _directories.count()) {
214                         files << _files.at(index.row() - _directories.count());
215                 } else {
216                         directories << _directories.at(index.row());
217                 }
218         }
219         foreach (QString dir, directories) {
220                 files.append(_mediascanner->singleScan(dir));
221         }
222         _tracks.clear();
223         ui->progressBar->setMinimum(0);
224         ui->progressBar->setMaximum(files.count());
225         ui->progressBar->show();
226         _tagresolver->decode(files);
227         ui->dirView->clearSelection();
228 }
229
230 void DirectoryView::_add_track(Track track) {
231         _tracks.append(track);
232         ui->progressBar->setValue(ui->progressBar->value()+1);
233 }
234
235 void DirectoryView::_done() {
236         emit addTracks(_tracks);
237         ui->progressBar->hide();
238         _tracks.clear();
239 }
240
241 void DirectoryView::updateIcons() {
242         Config config;
243         _icons_theme = config.getValue("ui/iconstheme").toString();
244         if (!ui->addButton->icon().isNull())
245                 ui->addButton->setIcon(QIcon(":/icons/"+_icons_theme+"/add.png"));
246         if (!ui->useButton->icon().isNull())
247                 ui->useButton->setIcon(QIcon(":/icons/"+_icons_theme+"/add.png"));
248         ui->homeButton->setIcon(QIcon(":/icons/"+_icons_theme+"/home.png"));
249         ui->backButton->setIcon(QIcon(":/icons/"+_icons_theme+"/back.png"));
250         if (ui->dirView->selectionModel()->selectedRows().count() == _model->rowCount()) {
251                 ui->selectToggleButton->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"));
252         } else {
253                 ui->selectToggleButton->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png"));
254         }
255         ui->playerButton->setIcon(QIcon(":/icons/"+_icons_theme+"/player.png"));
256         _home();
257 }
258
259 void DirectoryView::checkGradient() {
260         Config config;
261         if (config.getValue("ui/gradient").toString() == "yes") {
262                 ui->bottomWidget->setStyleSheet(_bottom_gradient);
263                 ui->topWidget->setStyleSheet(_top_gradient);
264         } else {
265                 ui->topWidget->setStyleSheet("");
266                 ui->bottomWidget->setStyleSheet("");
267         }
268 }
269
270 void DirectoryView::lanscapeMode() {
271         ui->topWidget->hide();
272         ui->bottomWidget->hide();
273         ui->lverticalLayout->removeItem(ui->lverticalSpacer_0);
274         ui->lverticalLayout->removeItem(ui->lverticalSpacer_1);
275         ui->lverticalLayout->addWidget(ui->backButton);
276         ui->lverticalLayout->addItem(ui->lverticalSpacer_0);
277         ui->lverticalLayout->addWidget(ui->homeButton);
278         ui->lverticalLayout->addItem(ui->lverticalSpacer_1);
279         ui->lverticalLayout->addWidget(ui->playerButton);
280         ui->rverticalLayout->removeItem(ui->rverticalSpacer_0);
281         ui->rverticalLayout->removeItem(ui->rverticalSpacer_1);
282         ui->rverticalLayout->addWidget(ui->addButton);
283         ui->rverticalLayout->addItem(ui->rverticalSpacer_0);
284         ui->rverticalLayout->addWidget(ui->useButton);
285         ui->rverticalLayout->addItem(ui->rverticalSpacer_1);
286         ui->rverticalLayout->addWidget(ui->selectToggleButton);
287         ui->lverticalWidget->show();
288         ui->rverticalWidget->show();
289 }
290
291 void DirectoryView::portraitMode() {
292         ui->lverticalWidget->hide();
293         ui->rverticalWidget->hide();
294         ui->lverticalLayout->removeItem(ui->lverticalSpacer_0);
295         ui->lverticalLayout->removeItem(ui->lverticalSpacer_1);
296         ui->rverticalLayout->removeItem(ui->rverticalSpacer_0);
297         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_0);
298         ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_1);
299         ui->topWidget->layout()->addWidget(ui->backButton);
300         ui->topWidget->layout()->addItem(ui->thorizontalSpacer_0);
301         ui->topWidget->layout()->addWidget(ui->homeButton);
302         ui->topWidget->layout()->addItem(ui->thorizontalSpacer_1);
303         ui->topWidget->layout()->addWidget(ui->addButton);
304         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_0);
305         ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer_1);
306         ui->bottomWidget->layout()->addWidget(ui->playerButton);
307         ui->bottomWidget->layout()->addItem(ui->bhorizontalSpacer_0);
308         ui->bottomWidget->layout()->addWidget(ui->useButton);
309         ui->bottomWidget->layout()->addItem(ui->bhorizontalSpacer_1);
310         ui->bottomWidget->layout()->addWidget(ui->selectToggleButton);
311         ui->topWidget->show();
312         ui->bottomWidget->show();
313 }
314
315 void DirectoryView::updateTranslations() {
316         ui->retranslateUi(this);
317         homeScreen();
318 }
319
320 void DirectoryView::homeScreen() {
321         _directories.clear();
322         _files.clear();
323         _model->clear();
324         _model->setRowCount(2);
325         _model->setColumnCount(2);
326         _model->setItem(0, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), ""));
327         _model->setItem(0, 1, new QStandardItem(tr("Internal memory")));
328         _model->setItem(1, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), ""));
329         _model->setItem(1, 1, new QStandardItem(tr("Memory card")));
330         _directories << QDir::homePath()+"/MyDocs/";
331         _directories << "/media/mmc1/";
332         ui->dirView->setColumnWidth(0, 70);
333         ui->addButton->setEnabled(false);
334         ui->addButton->setIcon(QIcon());
335         ui->useButton->setEnabled(false);
336         ui->useButton->setIcon(QIcon());
337 }
338
339 void DirectoryView::_use() {
340         emit clearCurrent();
341         _add();
342 }