From 2c4dde7be7cc32b027812204b152c9f514d2e6aa Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 16 Oct 2015 23:52:18 +0300 Subject: [PATCH] Overhaul BrowsePage to look and feel better --- remote/qml/pages/BrowsePage.qml | 110 +++++++++++--------------- remote/qml/pages/DirectoryEntry.qml | 18 +++-- remote/remote.pro | 2 + remote/source/browsedirectoryitem.cpp | 26 +++--- remote/source/browsedirectoryitem.h | 10 +-- remote/source/directorymodel.cpp | 57 +++++++++++++ remote/source/directorymodel.h | 41 ++++++++++ remote/source/remote.cpp | 2 + 8 files changed, 174 insertions(+), 92 deletions(-) create mode 100644 remote/source/directorymodel.cpp create mode 100644 remote/source/directorymodel.h diff --git a/remote/qml/pages/BrowsePage.qml b/remote/qml/pages/BrowsePage.qml index f853880..cfd518b 100644 --- a/remote/qml/pages/BrowsePage.qml +++ b/remote/qml/pages/BrowsePage.qml @@ -6,83 +6,65 @@ Page { id: page - SilicaFlickable + function navigate(dir) + { + var newDir = browseDirectory.directory; + if(newDir!="/") + newDir += "/"; + newDir += dir; + browseDirectory.directory = newDir; + } + + function navigateUp() + { + var newDir = browseDirectory.directory; + var slash = newDir.lastIndexOf("/"); + if(slash>0) + newDir = newDir.substring(0, slash); + else + newDir = "/"; + browseDirectory.directory = newDir; + } + + SilicaListView { anchors.fill: parent - contentHeight: column.height - Column + header: PageHeader { - id: column + title: qsTr("Browse files") + } + model: browseDirectory.model + + delegate: DirectoryEntry + { width: parent.width - spacing: Theme.paddingLarge - PageHeader + icon: { - title: qsTr("Browse files") + if(type==DirectoryModel.ParentDir) + return "image://theme/icon-m-back"; + else if(type==DirectoryModel.SubDir) + return "image://theme/icon-m-folder"; + else + return ""; } - // This really should be SilicaListView, but I can't figure out an - // easy way to turn the string lists into a suitable ListModel - Column - { - width: parent.width - spacing: Theme.paddingSmall - - DirectoryEntry - { - visible: browseDirectory.directory!="/" - icon: "image://theme/icon-m-back" - text: ".." - onPressed: - { - var newDir = browseDirectory.directory; - var slash = newDir.lastIndexOf("/"); - if(slash>0) - newDir = newDir.substring(0, slash); - else - newDir = "/"; - browseDirectory.directory = newDir; - } - } - - Repeater - { - model: browseDirectory.subdirectories - - DirectoryEntry - { - icon: "image://theme/icon-m-folder" - text: modelData + text: name - onPressed: - { - var newDir = browseDirectory.directory; - if(newDir!="/") - newDir += "/"; - newDir += modelData; - browseDirectory.directory = newDir; - } - } - } - - Repeater - { - model: browseDirectory.files - DirectoryEntry - { - text: modelData - - onPressed: - { - xinemaControl.play_file(browseDirectory.directory+"/"+modelData); - pageStack.replace("PlaybackPage.qml"); - } - } - } + onClicked: + { + if(type==DirectoryModel.File) + xinemaControl.play_file(browseDirectory.directory+"/"+name); + else if(type==DirectoryModel.ParentDir) + page.navigateUp(); + else if(type==DirectoryModel.SubDir) + page.navigate(name); } } + + VerticalScrollDecorator { } } BrowseDirectory diff --git a/remote/qml/pages/DirectoryEntry.qml b/remote/qml/pages/DirectoryEntry.qml index f8e0862..2c97456 100644 --- a/remote/qml/pages/DirectoryEntry.qml +++ b/remote/qml/pages/DirectoryEntry.qml @@ -9,14 +9,19 @@ Item property alias text: label.text property int iconSize: Theme.iconSizeMedium height: row.height - width: row.width - signal pressed() + signal clicked() Row { id: row - spacing: Theme.paddingSmall + spacing: Theme.paddingMedium + anchors + { + left: parent.left + right: parent.right + margins: Theme.horizontalPageMargin + } Image { @@ -36,10 +41,7 @@ Item MouseArea { - anchors.fill: row - onPressed: - { - entry.pressed(); - } + anchors.fill: parent + onClicked: entry.clicked(); } } diff --git a/remote/remote.pro b/remote/remote.pro index 55e4e03..5797e55 100644 --- a/remote/remote.pro +++ b/remote/remote.pro @@ -4,6 +4,7 @@ TARGET = harbour-xinema-remote CONFIG += sailfishapp SOURCES += source/browsedirectoryitem.cpp \ + source/directorymodel.cpp \ source/discovery.cpp \ source/discoveryitem.cpp \ source/remote.cpp \ @@ -12,6 +13,7 @@ SOURCES += source/browsedirectoryitem.cpp \ source/xinemacontrolitem.cpp HEADERS += source/browsedirectoryitem.h \ + source/directorymodel.h \ source/discovery.h \ source/discoveryitem.h \ source/streamcontrolitem.h \ diff --git a/remote/source/browsedirectoryitem.cpp b/remote/source/browsedirectoryitem.cpp index 99328bb..5a1a636 100644 --- a/remote/source/browsedirectoryitem.cpp +++ b/remote/source/browsedirectoryitem.cpp @@ -2,8 +2,6 @@ #include "xinemacontrol.h" #include "xinemacontrolitem.h" -#include - BrowseDirectoryItem::BrowseDirectoryItem(): control(0) { } @@ -14,10 +12,13 @@ void BrowseDirectoryItem::set_control(XinemaControlItem *c) disconnect(&control->get_control(), 0, this, 0); control = c; - XinemaControl &xc = control->get_control(); - connect(&xc, &XinemaControl::directory_started, this, &BrowseDirectoryItem::directory_started); - connect(&xc, &XinemaControl::file_added, this, &BrowseDirectoryItem::file_added); - connect(&xc, &XinemaControl::subdirectory_added, this, &BrowseDirectoryItem::subdirectory_added); + if(control) + { + XinemaControl &xc = control->get_control(); + connect(&xc, &XinemaControl::directory_started, this, &BrowseDirectoryItem::directory_started); + connect(&xc, &XinemaControl::file_added, this, &BrowseDirectoryItem::file_added); + connect(&xc, &XinemaControl::subdirectory_added, this, &BrowseDirectoryItem::subdirectory_added); + } emit control_changed(); } @@ -41,20 +42,17 @@ void BrowseDirectoryItem::directory_started(const QString &dir) emit directory_changed(); } - subdirectories.clear(); - files.clear(); - emit subdirectories_changed(); - emit files_changed(); + model.clear(); + if(directory!="/") + model.add_entry("..", DirectoryModel::ParentDir); } void BrowseDirectoryItem::file_added(const QString &name) { - files.push_back(name); - emit files_changed(); + model.add_entry(name, DirectoryModel::File); } void BrowseDirectoryItem::subdirectory_added(const QString &name) { - subdirectories.push_back(name); - emit subdirectories_changed(); + model.add_entry(name, DirectoryModel::SubDir); } diff --git a/remote/source/browsedirectoryitem.h b/remote/source/browsedirectoryitem.h index 84f8a6c..6eb94d0 100644 --- a/remote/source/browsedirectoryitem.h +++ b/remote/source/browsedirectoryitem.h @@ -2,6 +2,7 @@ #define BROWSEDIRECTORYITEM_H_ #include +#include "directorymodel.h" class XinemaControlItem; @@ -11,14 +12,12 @@ class BrowseDirectoryItem: public QQuickItem Q_PROPERTY(XinemaControlItem *control READ get_control WRITE set_control NOTIFY control_changed) Q_PROPERTY(QString directory READ get_directory WRITE set_directory NOTIFY directory_changed) - Q_PROPERTY(QStringList subdirectories READ get_subdirectories NOTIFY subdirectories_changed) - Q_PROPERTY(QStringList files READ get_files NOTIFY files_changed) + Q_PROPERTY(DirectoryModel *model READ get_model CONSTANT) private: XinemaControlItem *control; QString directory; - QStringList subdirectories; - QStringList files; + DirectoryModel model; public: BrowseDirectoryItem(); @@ -29,8 +28,7 @@ public: void set_directory(const QString &); const QString &get_directory() const { return directory; } - const QStringList &get_subdirectories() const { return subdirectories; } - const QStringList &get_files() const { return files; } + DirectoryModel *get_model() { return &model; } signals: void control_changed(); diff --git a/remote/source/directorymodel.cpp b/remote/source/directorymodel.cpp new file mode 100644 index 0000000..10bf05e --- /dev/null +++ b/remote/source/directorymodel.cpp @@ -0,0 +1,57 @@ +#include "directorymodel.h" + +void DirectoryModel::clear() +{ + beginResetModel(); + entries.clear(); + endResetModel(); +} + +void DirectoryModel::add_entry(const QString &name, EntryType type) +{ + Entry entry; + entry.name = name; + entry.type = type; + + int i; + for(i=0; (i DirectoryModel::roleNames() const +{ + QHash names; + names[0] = "name"; + names[1] = "type"; + return names; +} + +int DirectoryModel::rowCount(const QModelIndex &) const +{ + return entries.size(); +} + +QVariant DirectoryModel::data(const QModelIndex &index, int role) const +{ + int i = index.row(); + if(i>entries.size()) + return QVariant(); + + if(role==0) + return entries[i].name; + else if(role==1) + return entries[i].type; + else + return QVariant(); +} + + +bool DirectoryModel::Entry::operator<(const Entry &other) const +{ + if(type!=other.type) + return type +#include + +class DirectoryModel: public QAbstractListModel +{ + Q_OBJECT + + Q_ENUMS(EntryType) + +public: + enum EntryType + { + ParentDir, + SubDir, + File + }; + +private: + struct Entry + { + QString name; + EntryType type; + + bool operator<(const Entry &) const; + }; + + QList entries; + +public: + void clear(); + void add_entry(const QString &, EntryType); + + virtual QHash roleNames() const; + virtual int rowCount(const QModelIndex &) const; + virtual QVariant data(const QModelIndex &, int) const; +}; + +#endif diff --git a/remote/source/remote.cpp b/remote/source/remote.cpp index 48ef228..5dac99c 100644 --- a/remote/source/remote.cpp +++ b/remote/source/remote.cpp @@ -2,6 +2,7 @@ #include #include #include "browsedirectoryitem.h" +#include "directorymodel.h" #include "discoveryitem.h" #include "streamcontrolitem.h" #include "xinemacontrolitem.h" @@ -9,6 +10,7 @@ int main(int argc, char **argv) { QGuiApplication *app = SailfishApp::application(argc, argv); + qmlRegisterUncreatableType("fi.mikkosoft.xinema", 0, 1, "DirectoryModel", "DirectoryModel is available through BrowseDirectory"); qmlRegisterType("fi.mikkosoft.xinema", 0, 1, "BrowseDirectory"); qmlRegisterType("fi.mikkosoft.xinema", 0, 1, "Discovery"); qmlRegisterType("fi.mikkosoft.xinema", 0, 1, "StreamControl"); -- 2.45.2