From 6d75a8b2ab5c0addae2c5baad06687e8f4fc088d Mon Sep 17 00:00:00 2001 From: Nikolay Tischenko Date: Sun, 31 Oct 2010 03:02:52 +0600 Subject: [PATCH] Implemented directory browser Now user can add any media files to current playlist directly --- resources/black/home.png | Bin 0 -> 5965 bytes resources/resources.qrc | 2 + resources/white/home.png | Bin 0 -> 5888 bytes someplayer.pro | 9 +- src/directoryview.cpp | 269 ++++++++++++++++++++++++++++++ src/directoryview.h | 82 ++++++++++ src/mainwindow.cpp | 23 +++ src/mainwindow.h | 4 + src/mediascanner.cpp | 9 +- src/mediascanner.h | 3 +- src/playerform.cpp | 8 +- src/playerform.h | 1 + src/tagresolver.cpp | 28 ++++ src/tagresolver.h | 1 + src/ui/directoryview.ui | 406 ++++++++++++++++++++++++++++++++++++++++++++++ src/ui/libraryform.ui | 26 ++- 16 files changed, 851 insertions(+), 20 deletions(-) create mode 100644 resources/black/home.png create mode 100644 resources/white/home.png create mode 100644 src/directoryview.cpp create mode 100644 src/directoryview.h create mode 100644 src/ui/directoryview.ui diff --git a/resources/black/home.png b/resources/black/home.png new file mode 100644 index 0000000000000000000000000000000000000000..2c5816e8f9f0b0eadc7f8011438d4917cb0ac8b8 GIT binary patch literal 5965 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 Mnc16GnCy@I2mNGs)&Kwi literal 0 HcmV?d00001 diff --git a/resources/resources.qrc b/resources/resources.qrc index 229926f..6774c0d 100644 --- a/resources/resources.qrc +++ b/resources/resources.qrc @@ -69,5 +69,7 @@ black/arrow_r.png black/directory.png white/directory.png + black/home.png + white/home.png diff --git a/resources/white/home.png b/resources/white/home.png new file mode 100644 index 0000000000000000000000000000000000000000..c857c9cfa7b24a8b55ef2300f3767d61fb31c93d GIT binary patch literal 5888 zcmcIo2{@GP`hTVDTSb!ejV(*eW}n77W8WDWt;Wo2Ow7{E$o3_YNQkG)q%#W#2GH!n*`Q~*3xOOSNH(FUn45`VLorYQI>;r#Lg_&a z4kpx8g&!9K{m*-hP=WDHxPhiBmOMZh(b)}#W3oY*J{%24>ynX%dN2b$xSj#p5UsBR zLnD#K2&55052=eX#-Pv`lrikbpNg3n49lkYV?6LSKj5H|sY(Es%fcWKAt52~5Is1P zO+}zgOiU0+Gy;v*g)DSAVGJ%QRF}a~<%O7wfd@HcHjTxlF&QvkOp+fnm}{z{0?osI z1ZM>>xlB#~leGZB;QUYx(hspPjX=SXh{cZfEG}6e(uKFo1z!k@%qPd;QV@$R`0jl5 zehNY%FSxRT*+G0)3K;ZZGQFq&pwOS z2EjNx|7UYL{ipC8uJvw6*&n;~TT&cC7z;#rfE;Epn+#g-h8C#G2VKw@gC}u892XR4jwIbECOo z5RF$!FhL{+720223Y3h&L0lCxzEHH?AXEqGbS8rXv*dEwG{0beF>+xtba~G~Hkn2W zg1InZc#uuoP2xfh94vxYtAc1hF!`f-P%PqSN?2$}=A9TOdl5xXaM#Zi%`Ah!P!fXz zvSE%i4pd%t{|;o{jSsRoDi4M7cP(9nG|%ft!Ton)5CUi%81&)>fG`>vs>c3oCLIPH zvPFj%dIrwTa$p>g3y1xV;yfOo;;)o=G&#Y3JE0@Ih@usV`imGm20sU%-%7KE1OM~< z+-N=$AAB(o5131X*0Kn8p6UOg%+GoHw+1{3e#c=xET6;Qm{_Q?%-swaFAj+c5{VmCkMNq8@Fdtn^!}Gg}3s_6t;TlZ+ijqGSP!@S|3j0Sg;}sPxn8J%RH} z0pDh_-vHpI3;1g6ef+Y+ol9-fQSTS{T*vf zfM>b@(%#$O4!BkdRJF>87Xcy?0Mb1^Rts1f0r)nms)hpl&j7ME$w8}~m=0}~ zDr{{vJX#{PL-*}np;;9_zk!*dwmg;v0KDWzw$JDwiq}MK6pEtHTvQ)h8n9jbeDLHU z{~~FNo51;zZtn>ePaEqC$I808h6V?pIn-KhAvJmLnW5I~sPdi;`WlJ-KKbdzomXnn z=xx!qOTWCRdGOIGYi-+c(fxkUUnkmrFBPBtuJlNy*50p-s4Y9-zGBx=eCpu|be76N ztK(XA>K(I`SN%Fuf@b{&z_p!b0uf2NIorsBpB*)1h}^1IlK?PY&a8f{DIypZ5c9Gv zWcGvkwC#CyAj;qV_$~n0j#q;dnu^UEL;wJPK3e;lrQ*lx)jCx|Ypa(%uNMFAYq;M^ zt+vKW#!8G5wU+IxmA}tQ^FYfrC2e2CV+$qyD))c`$t)>&jn^$HQl_cfvcmclzqUuo*`7^O!l&kHQt~jIyyB{y>uHu+vV2AQZAi%url*UcjOHAUn z+T2ds*a)EaeLqlPi#icqxE~F#Iqt zK)O584A+3Hdb3(suQmt?ufJz?-B?F7ncRF`C0`=1e$BN_`GVyKKatz6hb&zYZCxd5 zxHQBHMp|cSM|2{(JhRJztyR-s-Yse*D!AXhMnfez$MMGc+snV!uJ%Kt;)r%Ss!vxW zu0+U0#N%p>)K(nCp*6~mEwR6TiO{j4!={7bp*o^-B~9OMjcW4!Zc1R0u*nG>*oMZ~ z!Sumd~8Xfw0^lakEvy zg%Xde?r}LQ^@CGQT4Gk&J7yJJJo#u%fPBCt?dluu?d82E*SVxT^zLXLv3-;BM(|^Z zgyaFan1*<&rb60k;nh@ykkwaDJ6%?IbV#9rfHXqAJ3V|x`V7;Hs9mD{r(9B#*hzrX0bBM4V=FX#5z#Xyc{lIdDbv@u@to+;q2ho{FB-D;sm-a;Z5? zg88LLpXq}_KKGpNx#BLlpTE9iprRfoPF5%m)lm+V%sUVqZBV=ZdP~=zyS2+tPb-xl zGR?hm!33x0pyyreF>%7*TzKI0t}kb~E~3Ml*(no|34O93v|ec`UePR#7Su*%_YYxf|g3Dfj%*`I7Bh(g5@YC=5{t*fzh2D_M8 zB}7BdU+%bV_bhN(q?4qSm-~~-+Oe5WY>wDSAEwoB9Z(yf*VF4W*9)yzUhnAq)_E+| z!@2CT*5!>(8=V?j9<*F+d3wem%@oy%9!?uh>rCq}_1zr0S*IkY^c8tQ>UUe%iI|Wq8M@^t9r% zn$et|t7C>^w6VD7=N{;v)5`GC<2=0AhKR?nH=Ne7DIjo8xBa*xe zIKFFJWHe;U~FdM)c^`ZNGc04euDs3!ncD={U*b&>0+p9WDnGK(92ePBo z1*n1tqb;MiESdTe{-^TYqvn_%@N-eusO91FWtMW5iTeun4OJH?2Qw<=#JZEh_XCTMdH1|?bek&?;nRPU^zA^pqM6*m zghJUK`4qXm&orNh4k^Ylo9>=@e&WWJyxKBKn}3J@$m>4cj4e{9a#LQXNHHY4x^GDK zZ@Mx1>9chYBBe#Mr#z+vSC)Afd#eJ>zTeui(VTFJ@R9J1U^v#%dy~}ph0#8y7*X+A z|NWDmEftf~X7}&(cnNqpKk1f4A-VL;9>f)+fwif^eVKJ+kjnGIhM| zaQeygJ(2LQ&wYC?mP8DbTl;rPGe6vx;lAv!o;@_Yv0`KE*6~~1@uHrgmEO0!Q?Fun z(BE?3VrP;cxi*xaEl({h+ZtFl7G8NX!hdo^F~g{}_hV()U#n)HKFKgK?X8>$XHM2l ze(GP<8_Cv~Zf!2_3egxVsBo>=@zG+`vJ2N6_r!e5%=2d-p6}gR6>@%}{kiR=P;5-w zOwy-BY232JGl|UyBoDmHFg7zWd1cO?9{HY)YooNS&yb(FIMZAxzX}og<;lCw*7now z7gEMklJC<0%$j~%^-kexPkl}Ox;ytn^-$YCZkigc4tXA;^dYlf+I8?x*j~-qfUnm- zc|OdZN>)fto?R+3w@6OKrr+>L)y6=l#9S=}_*H#bb^|^nq+wta6r(&6yUWS0OMUF%1+tKZ%eU_8KdF3){N&dacLk^}@b$AcuuW5sN z_Uc}Bj#__QIziV`zZc-BbrLb25yJkgs_+ITau_CZ*;0mu=(d#6j40cCr*SHt>HR^V ze=<*Pqng+8XX441hNkXZCl}AwdkJ9M0*?nNX*Q|R!ZN65#bNTLtj=ILK=*im;@XQ# zu5IlsI7^mJSaz+K@rT`=B}i2%F99O(z7|;9fU?_6LS@?>K^bnBHa_aP?4gORfcIX( zw3f^E718JKyEBgl`1$p1ghRe3iJct&CJX+xC6yqPNI81rR{vm>MGPsKu>8z(R&=;gsd#R zA{CXIo7;OA2b|X0aXNB`WC1~ywxgrM z{X(ov;!F9Ow8D2sV*0Hrw<9`MHVv`W#M1+39`_%4-TEm3LBAjY6NH+#D2W#;6I4YX k|GBZBJ!N*2J@JDe08_9*B)rJdhjI?Ew|2o7TKVq#C%_#*ssI20 literal 0 HcmV?d00001 diff --git a/someplayer.pro b/someplayer.pro index f46e990..2a1ae52 100644 --- a/someplayer.pro +++ b/someplayer.pro @@ -123,7 +123,8 @@ SOURCES += src/main.cpp\ src/settingsdialog.cpp \ src/dbusadaptor.cpp \ src/toolswidget.cpp \ - src/managelibraryform.cpp + src/managelibraryform.cpp \ + src/directoryview.cpp HEADERS += src/mainwindow.h \ src/player/player.h \ @@ -225,7 +226,8 @@ HEADERS += src/mainwindow.h \ src/abstractitemrenderer.h \ src/dbusadaptor.h \ src/toolswidget.h \ - src/managelibraryform.h + src/managelibraryform.h \ + src/directoryview.h FORMS += src/ui/mainwindow.ui \ src/ui/playerform.ui \ @@ -238,7 +240,8 @@ FORMS += src/ui/mainwindow.ui \ src/ui/saveplaylistdialog.ui \ src/ui/settingsdialog.ui \ src/ui/toolswidget.ui \ - src/ui/managelibraryform.ui + src/ui/managelibraryform.ui \ + src/ui/directoryview.ui CONFIG += mobility MOBILITY = diff --git a/src/directoryview.cpp b/src/directoryview.cpp new file mode 100644 index 0000000..60e0839 --- /dev/null +++ b/src/directoryview.cpp @@ -0,0 +1,269 @@ +/* + * SomePlayer - An alternate music player for Maemo 5 + * Copyright (C) 2010 Nikolay (somebody) Tischenko + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "directoryview.h" +#include "ui_directoryview.h" +#include +#include +#include "someplayer.h" +#include +#include +#include "config.h" + +using namespace SomePlayer::Storage; +using namespace SomePlayer::DataObjects; + +DirectoryView::DirectoryView(QWidget *parent) : + QWidget(parent), + ui(new Ui::DirectoryView) +{ + ui->setupUi(this); + Config config; + _icons_theme = config.getValue("ui/iconstheme").toString(); + REGISTERED_FILE_EXTENSIONS << "mp3" << "flac" << "wma" << "aac" << "ogg"; + setWindowFlags(windowFlags() | Qt::Window); + setAttribute(Qt::WA_Maemo5StackedWindow); + _model = new QStandardItemModel(0, 2, this); + ui->dirView->setModel(_model); + ui->dirView->setColumnHidden(2, true); + _current_dir = QDir::homePath(); + _tagresolver = new TagResolver(this); + _mediascanner = new MediaScanner(this); + + ui->addButton->setEnabled(false); + ui->addButton->setIcon(QIcon()); + + ui->progressBar->hide(); + + readDir(_current_dir); + connect(ui->backButton, SIGNAL(clicked()), this, SLOT(_back())); + connect(ui->dirView, SIGNAL(clicked(QModelIndex)), this, SLOT(_process_click(QModelIndex))); + connect(ui->dirView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(_process_dblclick(QModelIndex))); + connect(ui->dirView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, + SLOT(_process_selection(QItemSelection,QItemSelection))); + connect(ui->homeButton, SIGNAL(clicked()), this, SLOT(_home())); + connect(ui->selectToggleButton, SIGNAL(clicked()), this, SLOT(_toggle_selection())); + connect(ui->addButton, SIGNAL(clicked()), this, SLOT(_add())); + connect(_tagresolver, SIGNAL(decoded(Track)), this, SLOT(_add_track(Track))); + connect(_tagresolver, SIGNAL(done()), this, SLOT(_done())); + _top_gradient = ui->topWidget->styleSheet(); + _bottom_gradient = ui->bottomWidget->styleSheet(); +} + +DirectoryView::~DirectoryView() +{ + delete ui; +} + +void DirectoryView::readDir(QString path) { + QDir dir(path); + _current_dir = dir.absoluteFilePath(path); + _directories.clear(); + _files.clear(); + QList dirnames; + QList filenames; + QFileInfoList items = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); + foreach (QFileInfo info, items) { + if (info.isDir()) { + _directories << info.absoluteFilePath(); + dirnames << info.fileName(); + } else { + if (REGISTERED_FILE_EXTENSIONS.contains(info.suffix().toLower())) { + _files << info.absoluteFilePath(); + filenames << info.fileName(); + } + } + } + _model->setRowCount(dirnames.count() + filenames.count()); + int i = 0; + foreach (QString str, dirnames) { + _model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), "")); + _model->setItem(i, 1, new QStandardItem(str+"/")); + i++; + } + foreach (QString str, filenames) { + _model->setItem(i, 0, new QStandardItem(QIcon(":/icons/"+_icons_theme+"/deselect_all.png"), "")); + _model->setItem(i, 1, new QStandardItem(str)); + i++; + } + ui->dirView->setColumnWidth(0, 70); + ui->addButton->setEnabled(false); + ui->addButton->setIcon(QIcon()); +} + +void DirectoryView::_back() { + readDir(_current_dir+"/.."); +} + +void DirectoryView::_process_click(QModelIndex index) { + if (index.column() == 0) { + } else { + QString data = index.data().toString(); + if (data.endsWith("/")) { + _current_dir = _directories.at(index.row()); + readDir(_current_dir); + return; + } + } +} + +void DirectoryView::_process_dblclick(QModelIndex index) { + if (index.column() == 0) { + } else { + QString data = index.data().toString(); + if (!data.endsWith("/")) { + QString filename = _files.at(index.row() - _directories.count()); + Track track = _tagresolver->decodeOne(filename); + emit addAndPlay(track); + return; + } + } +} + +void DirectoryView::_process_selection(QItemSelection selected, QItemSelection deselected) { + foreach (QModelIndex id, selected.indexes()) { + if (id.column() == 0) { + _model->item(id.row())->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png")); + } + ui->dirView->selectionModel()->select(id, QItemSelectionModel::Select); + } + foreach (QModelIndex id, deselected.indexes()) { + if (id.column() == 0) { + _model->item(id.row())->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png")); + } + ui->dirView->selectionModel()->select(id, QItemSelectionModel::Deselect); + } + if (ui->dirView->selectionModel()->selectedRows().count() > 0) { + ui->addButton->setEnabled(true); + ui->addButton->setIcon(QIcon(":/icons/"+_icons_theme+"/add.png")); + } else { + ui->addButton->setEnabled(false); + ui->addButton->setIcon(QIcon()); + } +} + +void DirectoryView::_home() { + _current_dir = QDir::homePath(); + readDir(_current_dir); +} + +void DirectoryView::_toggle_selection() { + if (ui->dirView->selectionModel()->selectedRows().count() == _model->rowCount()) { + ui->dirView->clearSelection(); + ui->selectToggleButton->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png")); + } else { + ui->dirView->selectAll(); + ui->selectToggleButton->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png")); + } +} + +void DirectoryView::_add() { + QModelIndexList selected = ui->dirView->selectionModel()->selectedRows(1); + QStringList files; + QStringList directories; + foreach (QModelIndex index, selected) { + if (!index.data().toString().endsWith("/")) { + files << _files.at(index.row() - _directories.count()); + } else { + directories << _directories.at(index.row()); + } + } + foreach (QString dir, directories) { + files.append(_mediascanner->singleScan(dir)); + } + _tracks.clear(); + ui->progressBar->setMinimum(0); + ui->progressBar->setMaximum(files.count()); + ui->progressBar->show(); + _tagresolver->decode(files); + ui->dirView->clearSelection(); +} + +void DirectoryView::_add_track(Track track) { + _tracks.append(track); + ui->progressBar->setValue(ui->progressBar->value()+1); +} + +void DirectoryView::_done() { + emit addTracks(_tracks); + ui->progressBar->hide(); + _tracks.clear(); +} + +void DirectoryView::updateIcons() { + Config config; + _icons_theme = config.getValue("ui/iconstheme").toString(); + if (!ui->addButton->icon().isNull()) + ui->addButton->setIcon(QIcon(":/icons/"+_icons_theme+"/add.png")); + ui->homeButton->setIcon(QIcon(":/icons/"+_icons_theme+"/home.png")); + ui->backButton->setIcon(QIcon(":/icons/"+_icons_theme+"/back.png")); + if (ui->dirView->selectionModel()->selectedRows().count() == _model->rowCount()) { + ui->selectToggleButton->setIcon(QIcon(":/icons/"+_icons_theme+"/deselect_all.png")); + } else { + ui->selectToggleButton->setIcon(QIcon(":/icons/"+_icons_theme+"/select_all.png")); + } + ui->playerButton->setIcon(QIcon(":/icons/"+_icons_theme+"/player.png")); + readDir(_current_dir); +} + +void DirectoryView::updateGradient() { + Config config; + if (config.getValue("ui/gradient").toString() == "yes") { + ui->bottomWidget->setStyleSheet(_bottom_gradient); + ui->topWidget->setStyleSheet(_top_gradient); + } else { + ui->topWidget->setStyleSheet(""); + ui->bottomWidget->setStyleSheet(""); + } +} + +void DirectoryView::lanscapeMode() { + ui->topWidget->hide(); + ui->bottomWidget->hide(); + ui->lverticalLayout->removeItem(ui->lverticalSpacer_0); + ui->lverticalLayout->removeItem(ui->lverticalSpacer_1); + ui->lverticalLayout->addWidget(ui->backButton); + ui->lverticalLayout->addItem(ui->lverticalSpacer_0); + ui->lverticalLayout->addWidget(ui->homeButton); + ui->lverticalLayout->addItem(ui->lverticalSpacer_1); + ui->lverticalLayout->addWidget(ui->playerButton); + ui->rverticalLayout->removeItem(ui->rverticalSpacer); + ui->rverticalLayout->addWidget(ui->addButton); + ui->rverticalLayout->addItem(ui->rverticalSpacer); + ui->rverticalLayout->addWidget(ui->selectToggleButton); +} + +void DirectoryView::portraitMode() { + ui->lverticalLayout->removeItem(ui->lverticalSpacer_0); + ui->lverticalLayout->removeItem(ui->lverticalSpacer_1); + ui->rverticalLayout->removeItem(ui->rverticalSpacer); + ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_0); + ui->topWidget->layout()->removeItem(ui->thorizontalSpacer_1); + ui->topWidget->layout()->addWidget(ui->backButton); + ui->topWidget->layout()->addItem(ui->thorizontalSpacer_0); + ui->topWidget->layout()->addWidget(ui->homeButton); + ui->topWidget->layout()->addItem(ui->thorizontalSpacer_1); + ui->topWidget->layout()->addWidget(ui->addButton); + ui->bottomWidget->layout()->removeItem(ui->bhorizontalSpacer); + ui->bottomWidget->layout()->addWidget(ui->playerButton); + ui->bottomWidget->layout()->addItem(ui->bhorizontalSpacer); + ui->bottomWidget->layout()->addWidget(ui->selectToggleButton); + ui->topWidget->show(); + ui->bottomWidget->show(); +} diff --git a/src/directoryview.h b/src/directoryview.h new file mode 100644 index 0000000..db180ef --- /dev/null +++ b/src/directoryview.h @@ -0,0 +1,82 @@ +/* + * SomePlayer - An alternate music player for Maemo 5 + * Copyright (C) 2010 Nikolay (somebody) Tischenko + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef DIRECTORYVIEW_H +#define DIRECTORYVIEW_H + +#include +#include +#include +#include +#include "tagresolver.h" +#include "mediascanner.h" + +namespace Ui { + class DirectoryView; +} + +using SomePlayer::DataObjects::TagResolver; +using SomePlayer::Storage::MediaScanner; +using SomePlayer::DataObjects::Track; + +class DirectoryView : public QWidget +{ + Q_OBJECT + +public: + explicit DirectoryView(QWidget *parent = 0); + ~DirectoryView(); + void updateIcons(); + void updateGradient(); + void lanscapeMode(); + void portraitMode(); + +signals: + void addAndPlay(Track); + void addTracks(QList); + +private: + Ui::DirectoryView *ui; + QStandardItemModel *_model; + QList REGISTERED_FILE_EXTENSIONS; + void readDir(QString path); + QList _directories; + QList _files; + QString _icons_theme; + QString _current_dir; + TagResolver *_tagresolver; + MediaScanner *_mediascanner; + QList _tracks; + QString _bottom_gradient; + QString _top_gradient; + +private slots: + void _back(); + void _home(); + void _toggle_selection(); + void _add(); + void _add_track(Track); + void _done(); + void _process_click(QModelIndex); + void _process_dblclick(QModelIndex); + void _process_selection(QItemSelection, QItemSelection); + +}; + +#endif // DIRECTORYVIEW_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 67b1399..9f3dd12 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -50,6 +50,8 @@ MainWindow::MainWindow(QWidget *parent) : _player_form = new PlayerForm(_library, this); ui->centralWidget->layout()->addWidget(_player_form); _library_form = new LibraryForm(_library, this); + _directory_form = new DirectoryView(this); + _directory_form->hide(); _timer = new QTimer(this); _equalizer_dialog = new EqualizerDialog(this); _manage_library_form = new ManageLibraryForm(_library, this); @@ -70,6 +72,9 @@ MainWindow::MainWindow(QWidget *parent) : connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(_orientation_changed())); connect(_player_form, SIGNAL(fullscreen(bool)), this, SLOT(_fullscreen(bool))); connect(_library_form, SIGNAL(addAndPlay(Track)), _player_form, SLOT(play(Track))); + connect(_directory_form, SIGNAL(addAndPlay(Track)), _player_form, SLOT(play(Track))); + connect(_player_form, SIGNAL(dirView()), _directory_form, SLOT(show())); + connect(_directory_form, SIGNAL(addTracks(QList)), this, SLOT(_add_tracks(QList))); _player_form->reload(true); QString mode = config.getValue("ui/orientation").toString(); if (mode == "landscape") { @@ -77,22 +82,27 @@ MainWindow::MainWindow(QWidget *parent) : _player_form->landscapeMode(); _library_form->landscapeMode(); _equalizer_dialog->landscapeMode(); + _directory_form->lanscapeMode(); } else if (mode == "portrait") { setAttribute(Qt::WA_Maemo5PortraitOrientation); _player_form->portraitMode(); _library_form->portraitMode(); _equalizer_dialog->portraitMode(); + _directory_form->portraitMode(); } else if (mode == "auto") { // initialization in landscape _player_form->landscapeMode(); _library_form->landscapeMode(); _equalizer_dialog->landscapeMode(); + _directory_form->lanscapeMode(); setAttribute(Qt::WA_Maemo5AutoOrientation); } _library_form->updateIcons(); _player_form->updateIcons(); _manage_library_form->updateIcons(); + _directory_form->updateIcons(); _player_form->checkGradient(); _library_form->checkGradient(); + _directory_form->updateGradient(); setWindowTitle("SomePlayer"); } @@ -249,6 +259,8 @@ void MainWindow::settings() { _manage_library_form->updateIcons(); _player_form->checkGradient(); _library_form->checkGradient(); + _directory_form->updateIcons(); + _directory_form->updateGradient(); } void MainWindow::_orientation_changed() { @@ -257,10 +269,12 @@ void MainWindow::_orientation_changed() { _player_form->landscapeMode(); _library_form->landscapeMode(); _equalizer_dialog->landscapeMode(); + _directory_form->lanscapeMode(); } else { _player_form->portraitMode(); _library_form->portraitMode(); _equalizer_dialog->portraitMode(); + _directory_form->portraitMode(); } } @@ -268,3 +282,12 @@ void MainWindow::_fullscreen(bool f) { if (f) showFullScreen(); else showNormal(); } + +void MainWindow::_add_tracks(QList tracks) { + Playlist cur = _library->getCurrentPlaylist(); + foreach (Track track, tracks) { + cur.addTrack(track); + } + _library->saveCurrentPlaylist(cur); + _player_form->reload(true); +} diff --git a/src/mainwindow.h b/src/mainwindow.h index 0212d06..fbfc860 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -27,6 +27,7 @@ #include "busywidget.h" #include "equalizerdialog.h" #include "managelibraryform.h" +#include "directoryview.h" #include "library.h" #include @@ -35,6 +36,7 @@ namespace Ui { } using SomePlayer::DataObjects::Library; +using SomePlayer::DataObjects::Track; class MainWindow : public QMainWindow { @@ -66,10 +68,12 @@ private slots: void _equalizer_value_changed(int, int); void _orientation_changed(); void _fullscreen(bool); + void _add_tracks(QList); private: PlayerForm *_player_form; LibraryForm *_library_form; BusyWidget *_busy_widget; + DirectoryView *_directory_form; Library *_library; QTimer *_timer; EqualizerDialog *_equalizer_dialog; diff --git a/src/mediascanner.cpp b/src/mediascanner.cpp index f6a32c1..0fc2d37 100644 --- a/src/mediascanner.cpp +++ b/src/mediascanner.cpp @@ -35,11 +35,17 @@ void MediaScanner::run() { return; _foundMedia.clear(); _scan_directory(_dir); + _foundMedia = _scan_directory(_dir); emit scanFinish(_foundMedia); _stopped = true; } -void MediaScanner::_scan_directory(QDir dir) { +QStringList MediaScanner::singleScan(QString path) { + _dir = path; + return _scan_directory(_dir); +} + +QStringList MediaScanner::_scan_directory(QDir dir) { QFileInfoList items = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); foreach (QFileInfo info, items) { if (info.isDir()) { @@ -53,6 +59,7 @@ void MediaScanner::_scan_directory(QDir dir) { } } } + return _foundMedia; } void MediaScanner::stop() { diff --git a/src/mediascanner.h b/src/mediascanner.h index 8a33e2c..151bf3d 100644 --- a/src/mediascanner.h +++ b/src/mediascanner.h @@ -36,6 +36,7 @@ namespace SomePlayer { public: explicit MediaScanner(QObject *parent = 0); void run(); + QStringList singleScan(QString); signals: void scanFinish(QStringList); @@ -49,7 +50,7 @@ namespace SomePlayer { QStringList REGISTERED_FILE_EXTENSIONS; QStringList _foundMedia; - void _scan_directory(QDir); + QStringList _scan_directory(QDir); }; }; diff --git a/src/playerform.cpp b/src/playerform.cpp index f01eb99..83b0ee1 100644 --- a/src/playerform.cpp +++ b/src/playerform.cpp @@ -394,7 +394,7 @@ void PlayerForm::stop() { } void PlayerForm::_dirview() { - + emit dirView(); } void PlayerForm::landscapeMode() { @@ -556,5 +556,11 @@ void PlayerForm::play(Track track) { if (id >= 0) { _player->setTrackId(id); _player->play(); + } else { + _current_playlist.addTrack(track); + _lib->saveCurrentPlaylist(_current_playlist); + reload(true); + _player->setTrackId(_current_playlist.tracks().count()-1); + _player->play(); } } diff --git a/src/playerform.h b/src/playerform.h index 21ab858..cbfa802 100644 --- a/src/playerform.h +++ b/src/playerform.h @@ -60,6 +60,7 @@ signals: void fullscreen(bool); void clearPlaylist(); void refreshLibrary(); + void dirView(); public slots: void reload(bool); diff --git a/src/tagresolver.cpp b/src/tagresolver.cpp index 7ec6231..efa81c3 100644 --- a/src/tagresolver.cpp +++ b/src/tagresolver.cpp @@ -74,3 +74,31 @@ void TagResolver::updateTags(Track track) { file_ref.save(); } } + +Track TagResolver::decodeOne(QString filename) { + TagLib::FileRef file_ref(QFile::encodeName(filename).data()); + if (!file_ref.isNull()) { + TagLib::Tag *tag = file_ref.tag(); + if (NULL != tag) { + TagLib::AudioProperties *properties = file_ref.audioProperties(); + if (NULL != properties) { + TrackMetadata meta(QString::fromStdWString(tag->title().toWString()), + QString::fromStdWString(tag->artist().toWString()), + QString::fromStdWString(tag->album().toWString()), + properties->length()); + meta.setYear(tag->year()); + Track track(meta, filename); + return track; + } + } + } else { // workaround + TrackMetadata meta; + meta.setLength(0); + QFileInfo fi(filename); + meta.setArtist(fi.suffix().toUpper()); + meta.setTitle(fi.baseName()); + Track track(meta, filename); + return track; + } + return Track(); +} diff --git a/src/tagresolver.h b/src/tagresolver.h index 972ff41..074d5b4 100644 --- a/src/tagresolver.h +++ b/src/tagresolver.h @@ -38,6 +38,7 @@ namespace SomePlayer { public slots: void decode (QStringList files); void updateTags(Track); + Track decodeOne (QString filepath); signals: void decoded(Track); diff --git a/src/ui/directoryview.ui b/src/ui/directoryview.ui new file mode 100644 index 0000000..0485509 --- /dev/null +++ b/src/ui/directoryview.ui @@ -0,0 +1,406 @@ + + + DirectoryView + + + + 0 + 0 + 800 + 480 + + + + Directories + + + + 0 + + + 0 + + + + + 0 + + + + + + 0 + 0 + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + :/icons/white/back.png:/icons/white/back.png + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 70 + 70 + + + + + + + + :/icons/white/home.png:/icons/white/home.png + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + :/icons/white/player.png:/icons/white/player.png + + + true + + + + + + + + + 0 + + + + + background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(38, 38, 38, 255), stop:1 rgba(92, 92, 92, 255)) + + + + 0 + + + 0 + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 324 + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 327 + 0 + + + + + + + + + + + Qt::CustomContextMenu + + + QFrame::Sunken + + + Qt::ScrollBarAlwaysOff + + + false + + + QAbstractItemView::NoEditTriggers + + + false + + + false + + + false + + + QAbstractItemView::NoDragDrop + + + QAbstractItemView::MultiSelection + + + QAbstractItemView::SelectRows + + + + 50 + 50 + + + + false + + + false + + + false + + + true + + + false + + + 70 + + + 70 + + + + + + + 24 + + + + + + + background:qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 rgba(38, 38, 38, 255), stop:1 rgba(92, 92, 92, 255)) + + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 651 + 0 + + + + + + + + + + + + + 0 + + + + + + 0 + 0 + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + :/icons/white/add.png:/icons/white/add.png + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + + :/icons/white/select_all.png:/icons/white/select_all.png + + + true + + + + + + + + + + + + + playerButton + clicked() + DirectoryView + hide() + + + 35 + 443 + + + 399 + 239 + + + + + diff --git a/src/ui/libraryform.ui b/src/ui/libraryform.ui index 918c94b..ac90790 100644 --- a/src/ui/libraryform.ui +++ b/src/ui/libraryform.ui @@ -11,7 +11,7 @@ - SomePlayer Library + Library @@ -137,7 +137,7 @@ - + :/icons/white/back.png:/icons/white/back.png @@ -182,7 +182,7 @@ - + :/icons/white/add.png:/icons/white/add.png @@ -221,7 +221,7 @@ - + :/icons/white/delete.png:/icons/white/delete.png @@ -266,7 +266,7 @@ - + :/icons/white/use.png:/icons/white/use.png @@ -311,7 +311,7 @@ - + :/icons/white/player.png:/icons/white/player.png @@ -416,7 +416,7 @@ - + :/icons/white/more.png:/icons/white/more.png @@ -461,7 +461,7 @@ - + :/icons/white/select_all.png:/icons/white/select_all.png @@ -506,7 +506,7 @@ - + :/icons/white/artists.png:/icons/white/artists.png @@ -545,7 +545,7 @@ - + :/icons/white/playlists.png:/icons/white/playlists.png @@ -590,7 +590,7 @@ - + :/icons/white/dynamic.png:/icons/white/dynamic.png @@ -658,8 +658,6 @@ - - - + -- 1.7.9.5