Add support for folders tab

This commit is contained in:
craig.p.drummond@gmail.com
2014-04-16 11:04:33 +00:00
committed by craig.p.drummond@gmail.com
parent 5de31f5d8f
commit e5da87c7de
8 changed files with 104 additions and 28 deletions

View File

@@ -25,11 +25,19 @@
#include "stdactions.h"
#include "itemview.h"
#ifdef ENABLE_UBUNTU
static const int Role_HasChildren = Qt::UserRole+500;
#endif
QVariant ActionModel::data(const QModelIndex &index, int role) const
{
QVariant v;
#ifdef ENABLE_UBUNTU
if (Role_HasChildren==role) {
return rowCount(index)>0;
}
#else
Q_UNUSED(index)
#ifndef ENABLE_UBUNTU // Should touch version return a list of action names?
if (ItemView::Role_Actions==role) {
v.setValue<QList<Action *> >(QList<Action *>() << StdActions::self()->replacePlayQueueAction << StdActions::self()->addToPlayQueueAction);
}
@@ -46,6 +54,7 @@ QHash<int, QByteArray> ActionModel::roleNames() const
roles[ItemView::Role_SubText] = "subText";
roles[ItemView::Role_TitleText] = "titleText";
roles[ItemView::Role_Image] = "image";
roles[Role_HasChildren] = "hasChildren";
return roles;
}
#endif

View File

@@ -186,6 +186,17 @@ QVariant DirViewModel::data(const QModelIndex &index, int role) const
break;
}
#endif
#ifdef ENABLE_UBUNTU
case ItemView::Role_TitleText:
switch (item->type()) {
case DirViewItem::Type_Dir:
return static_cast<DirViewItemDir *>(item)->fullName();
default:
case DirViewItem::Type_File:
return item->data();
}
#endif
case ItemView::Role_MainText:
case Qt::DisplayRole:
return item->data();
case Qt::ToolTipRole:
@@ -427,6 +438,10 @@ void DirViewModel::updateDirView(DirViewItemRoot *newroot, const QDateTime &dbUp
if (!fromFile && (needToSave || updatedListing)) {
toXML();
}
#ifdef ENABLE_UBUNTU
emit updated();
#endif
}
void DirViewModel::updatingMpd()

View File

@@ -67,6 +67,9 @@ public Q_SLOTS:
void updateDirView(DirViewItemRoot *newroot, const QDateTime &dbUpdate=QDateTime(), bool fromFile=false);
void updatingMpd();
Q_SIGNALS:
void updated();
private:
void toXML(const DirViewItem *item, QXmlStreamWriter &writer);
quint32 fromXML(QIODevice *dev, const QDateTime &dt, DirViewItemRoot *root);

View File

@@ -41,12 +41,19 @@ MPDBackend::MPDBackend(QObject *parent) : QObject(parent)
connect(this, SIGNAL(goToNextSong()), MPDConnection::self(), SLOT(goToNext()));
connect(this, SIGNAL(goToPreviousSong()), MPDConnection::self(), SLOT(goToPrevious()));
connect(this, SIGNAL(loadLibrary()), MPDConnection::self(), SLOT(loadLibrary()));
connect(this, SIGNAL(loadFolders()), MPDConnection::self(), SLOT(loadFolders()));
connect(MPDConnection::self(), SIGNAL(stateChanged(bool)), this, SLOT(onConnected(bool)));
// TODO: These need to be confiurable vi QML UI!
AlbumsModel::self()->setEnabled(true);
DirViewModel::self()->setEnabled(true);
PlaylistsModel::self()->setEnabled(true);
playQueueProxyModel.setSourceModel(&playQueueModel);
artistsProxyModel.setSourceModel(MusicLibraryModel::self());
albumsProxyModel.setSourceModel(AlbumsModel::self());
foldersProxyModel.setSourceModel(DirViewModel::self());
playlistsProxyModel.setSourceModel(PlaylistsModel::self());
// connect(MPDConnection::self(), SIGNAL(outputsUpdated(const QList<Output> &)), this, SLOT(outputsUpdated(const QList<Output> &)));
@@ -96,6 +103,7 @@ MPDBackend::MPDBackend(QObject *parent) : QObject(parent)
connect(MusicLibraryModel::self(), SIGNAL(updated()), this, SLOT(artistsUpdated()));
connect(AlbumsModel::self(), SIGNAL(updated()), this, SLOT(albumsUpdated()));
connect(DirViewModel::self(), SIGNAL(updated()), this, SLOT(foldersUpdated()));
connect(PlaylistsModel::self(), SIGNAL(updated()), this, SLOT(playlistsUpdated()));
MPDConnection::self()->start();
@@ -157,20 +165,25 @@ void MPDBackend::setIsRandomOrder(bool random) {
emit setRandomOrder(random);
}
// TODO: Why are the sorts required below? e.g. If we don't call sort, the items are only sorted string-wise. This
// means that 'Various Artists' is not placed at the top, and "The XXX" is not sorted as "XXX"
void MPDBackend::artistsUpdated() {
// TODO: If we don't call sort here, the items are only sorted string-wise. This
// means that 'Various Artists' is not placed at the top, and "The XXX" is not sorted as "XXX"
artistsProxyModel.sort();
emit onArtistsModelChanged();
}
void MPDBackend::albumsUpdated() {
//albumsProxyModel.sort();
albumsProxyModel.sort();
emit onAlbumsModelChanged();
}
void MPDBackend::foldersUpdated() {
foldersProxyModel.sort();
emit onFoldersModelChanged();
}
void MPDBackend::playlistsUpdated() {
//playlistsProxyModel.sort();
playlistsProxyModel.sort();
emit onPlaylistsModelChanged();
}
@@ -183,9 +196,12 @@ void MPDBackend::add(const QString &modelName, const QVariant &rows, bool replac
} else if ("albums"==modelName) {
proxy=&albumsProxyModel;
model=AlbumsModel::self();
} else if ("playlists"==modelName) {
} else if ("playlists"==modelName) {
proxy=&playlistsProxyModel;
model=PlaylistsModel::self();
} else if ("folders"==modelName) {
proxy=&foldersProxyModel;
model=DirViewModel::self();
}
if (model) {
@@ -324,6 +340,9 @@ void MPDBackend::updateStats() //Does nothing right now...
if (!MusicLibraryModel::self()->fromXML()) {
emit loadLibrary();
}
if (DirViewModel::self()->isEnabled() && !DirViewModel::self()->fromXML()) {
emit loadFolders();
}
// albumsPage->goTop();
// libraryPage->refresh();
// folderPage->refresh();

View File

@@ -38,6 +38,8 @@
#include "musiclibraryproxymodel.h"
#include "albumsproxymodel.h"
#include "playlistsproxymodel.h"
#include "dirviewmodel.h"
#include "dirviewproxymodel.h"
class MPDBackend : public QObject
{
@@ -60,6 +62,7 @@ class MPDBackend : public QObject
Q_PROPERTY(QString playQueueStatus READ getPlayQueueStatus NOTIFY onPlayQueueChanged)
Q_PROPERTY(bool artistsFound READ getArtistsFound NOTIFY onArtistsModelChanged)
Q_PROPERTY(bool albumsFound READ getAlbumsFound NOTIFY onAlbumsModelChanged)
Q_PROPERTY(bool foldersFound READ getFoldersFound NOTIFY onFoldersModelChanged)
Q_PROPERTY(bool playlistsFound READ getPlaylistsFound NOTIFY onPlaylistsModelChanged)
public:
@@ -87,6 +90,7 @@ public:
Q_INVOKABLE bool isPlayQueueEmpty() { return playQueueModel.rowCount() == 0; }
Q_INVOKABLE bool getArtistsFound() { return MusicLibraryModel::self()->rowCount()>0; }
Q_INVOKABLE bool getAlbumsFound() { return AlbumsModel::self()->rowCount()>0; }
Q_INVOKABLE bool getFoldersFound() { return DirViewModel::self()->rowCount()>0; }
Q_INVOKABLE bool getPlaylistsFound() { return PlaylistsModel::self()->rowCount()>0; }
Q_INVOKABLE bool getIsRandomOrder() { return MPDStatus::self()->random(); }
Q_INVOKABLE void setIsRandomOrder(bool random);
@@ -94,6 +98,7 @@ public:
PlayQueueProxyModel * getPlayQueueProxyModel() { return &playQueueProxyModel; }
MusicLibraryProxyModel * getArtistsProxyModel() { return &artistsProxyModel; }
AlbumsProxyModel * getAlbumsProxyModel() { return &albumsProxyModel; }
DirViewProxyModel * getFoldersProxyModel() { return &foldersProxyModel; }
PlaylistsProxyModel * getPlaylistsProxyModel() { return &playlistsProxyModel; }
Q_SIGNALS:
@@ -103,6 +108,7 @@ Q_SIGNALS:
void onPlayQueueChanged();
void onArtistsModelChanged();
void onAlbumsModelChanged();
void onFoldersModelChanged();
void onPlaylistsModelChanged();
void onMpdStatusChanged();
@@ -115,6 +121,7 @@ public Q_SLOTS:
void mpdConnectionStateChanged(bool connected);
void artistsUpdated();
void albumsUpdated();
void foldersUpdated();
void playlistsUpdated();
Q_SIGNALS:
@@ -129,6 +136,7 @@ Q_SIGNALS:
void startPlayingSongId(qint32);
void goToNextSong();
void goToPreviousSong();
void loadFolders();
void loadLibrary();
void add(const QStringList &files, bool replace, quint8 priorty); // Songs
void loadPlaylist(const QString &name, bool replace);
@@ -154,6 +162,7 @@ private:
PlayQueueProxyModel playQueueProxyModel;
MusicLibraryProxyModel artistsProxyModel;
AlbumsProxyModel albumsProxyModel;
DirViewProxyModel foldersProxyModel;
PlaylistsProxyModel playlistsProxyModel;
};

View File

@@ -200,6 +200,7 @@ int main(int argc, char *argv[])
view.rootContext()->setContextProperty("backend", &backend);
view.rootContext()->setContextProperty("artistsProxyModel", backend.getArtistsProxyModel());
view.rootContext()->setContextProperty("albumsProxyModel", backend.getAlbumsProxyModel());
view.rootContext()->setContextProperty("foldersProxyModel", backend.getFoldersProxyModel());
view.rootContext()->setContextProperty("playlistsProxyModel", backend.getPlaylistsProxyModel());
view.rootContext()->setContextProperty("playQueueProxyModel", backend.getPlayQueueProxyModel());
view.rootContext()->setContextProperty("currentCover", CurrentCover::self());
@@ -207,8 +208,5 @@ int main(int argc, char *argv[])
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:qml/cantata/main.qml"));
view.show();
AlbumsModel::self()->setEnabled(true);
return app.exec();
}

View File

@@ -38,7 +38,6 @@ Page {
visible: false
property variant rows
property int depth: -1
property string modelName
property alias model: visualDataModel.model
@@ -56,26 +55,23 @@ Page {
}
function onDelegateClicked(index, text) {
if (depth > 1) {
var newRows = []
for (var i = 0; i < rows.length; i++) {
newRows[i] = rows[i]
}
newRows[rows.length] = index
var newRows = []
for (var i = 0; i < rows.length; i++) {
newRows[i] = rows[i]
}
newRows[rows.length] = index
var component = Qt.createComponent("SubListViewPage.qml")
var component = Qt.createComponent("SubListViewPage.qml")
if (component.status == Component.Ready) {
var page = component.createObject(parent, {"model": model, "title": text, "modelName": modelName})
page.init(newRows, depth - 1)
pageStack.push(page)
}
if (component.status == Component.Ready) {
var page = component.createObject(parent, {"model": model, "title": text, "modelName": modelName})
page.init(newRows)
pageStack.push(page)
}
}
function init(rows, depth) {
function init(rows) {
this.rows = rows
this.depth = depth
subListView.model.rootIndex = -1
for (var i = 0; i < this.rows.length; i++) {
subListView.model.rootIndex = subListView.model.modelIndex(this.rows[i])
@@ -155,7 +151,7 @@ Page {
onFirstImageButtonClicked: subListViewPage.add(index, true)
onSecondImageButtonClicked: subListViewPage.add(index, false)
onClicked: subListViewPage.onDelegateClicked(index, model.titleText)
onClicked: model.hasChildren ? subListViewPage.onDelegateClicked(index, model.titleText) : "";
}
}
}

View File

@@ -81,7 +81,7 @@ MainView {
var component = Qt.createComponent("SubListViewPage.qml")
var page = component.createObject(parent, {"model": model, "title": text, "modelName": "artists"})
page.init([index], 2)
page.init([index])
pageStack.push(page)
}
}
@@ -108,7 +108,34 @@ MainView {
var component = Qt.createComponent("SubListViewPage.qml")
var page = component.createObject(parent, {"model": model, "title": text, "modelName": "albums"})
page.init([index], 1)
page.init([index])
pageStack.push(page)
}
}
}
Tab {
id: foldersTab
title: i18n.tr("Folders")
page: ListViewPage {
id: foldersPage
model: foldersProxyModel
emptyViewVisible: !backend.foldersFound
emptyViewText: i18n.tr("No folders found")
function add(index, replace) {
backend.add("folders", index, replace)
pageStack.push(currentlyPlayingPage)
}
function onDelegateClicked(index, text) {
var component = Qt.createComponent("SubListViewPage.qml")
var page = component.createObject(parent, {"model": model, "title": text, "modelName": "folders"})
page.init([index])
pageStack.push(page)
}
}
@@ -135,7 +162,7 @@ MainView {
var component = Qt.createComponent("SubListViewPage.qml")
var page = component.createObject(parent, {"model": model, "title": text, "modelName": "playlists"})
page.init([index], 1)
page.init([index])
pageStack.push(page)
}
}