{
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
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
{
MouseArea
{
- anchors.fill: row
- onPressed:
- {
- entry.pressed();
- }
+ anchors.fill: parent
+ onClicked: entry.clicked();
}
}
CONFIG += sailfishapp
SOURCES += source/browsedirectoryitem.cpp \
+ source/directorymodel.cpp \
source/discovery.cpp \
source/discoveryitem.cpp \
source/remote.cpp \
source/xinemacontrolitem.cpp
HEADERS += source/browsedirectoryitem.h \
+ source/directorymodel.h \
source/discovery.h \
source/discoveryitem.h \
source/streamcontrolitem.h \
#include "xinemacontrol.h"
#include "xinemacontrolitem.h"
-#include <QDebug>
-
BrowseDirectoryItem::BrowseDirectoryItem():
control(0)
{ }
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();
}
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);
}
#define BROWSEDIRECTORYITEM_H_
#include <QQuickItem>
+#include "directorymodel.h"
class XinemaControlItem;
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();
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();
--- /dev/null
+#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<entries.size() && entries[i]<entry); ++i) ;
+
+ beginInsertRows(QModelIndex(), i, i);
+ entries.insert(i, entry);
+ endInsertRows();
+}
+
+QHash<int, QByteArray> DirectoryModel::roleNames() const
+{
+ QHash<int, QByteArray> 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<other.type;
+ return name<other.name;
+}
--- /dev/null
+#ifndef DIRECTORYMODEL_H_
+#define DIRECTORYMODEL_H_
+
+#include <QAbstractListModel>
+#include <QList>
+
+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<Entry> entries;
+
+public:
+ void clear();
+ void add_entry(const QString &, EntryType);
+
+ virtual QHash<int, QByteArray> roleNames() const;
+ virtual int rowCount(const QModelIndex &) const;
+ virtual QVariant data(const QModelIndex &, int) const;
+};
+
+#endif
#include <QQuickView>
#include <sailfishapp.h>
#include "browsedirectoryitem.h"
+#include "directorymodel.h"
#include "discoveryitem.h"
#include "streamcontrolitem.h"
#include "xinemacontrolitem.h"
int main(int argc, char **argv)
{
QGuiApplication *app = SailfishApp::application(argc, argv);
+ qmlRegisterUncreatableType<DirectoryModel>("fi.mikkosoft.xinema", 0, 1, "DirectoryModel", "DirectoryModel is available through BrowseDirectory");
qmlRegisterType<BrowseDirectoryItem>("fi.mikkosoft.xinema", 0, 1, "BrowseDirectory");
qmlRegisterType<DiscoveryItem>("fi.mikkosoft.xinema", 0, 1, "Discovery");
qmlRegisterType<StreamControlItem>("fi.mikkosoft.xinema", 0, 1, "StreamControl");