aboutsummaryrefslogtreecommitdiffstats
path: root/src/imports/folderlistmodel
diff options
context:
space:
mode:
Diffstat (limited to 'src/imports/folderlistmodel')
-rw-r--r--src/imports/folderlistmodel/fileinfothread.cpp280
-rw-r--r--src/imports/folderlistmodel/fileinfothread_p.h107
-rw-r--r--src/imports/folderlistmodel/fileproperty_p.h94
-rw-r--r--src/imports/folderlistmodel/folderlistmodel.json1
-rw-r--r--src/imports/folderlistmodel/folderlistmodel.pro9
-rw-r--r--src/imports/folderlistmodel/plugin.cpp7
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp494
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.h60
8 files changed, 856 insertions, 196 deletions
diff --git a/src/imports/folderlistmodel/fileinfothread.cpp b/src/imports/folderlistmodel/fileinfothread.cpp
new file mode 100644
index 0000000000..3c4d60bb89
--- /dev/null
+++ b/src/imports/folderlistmodel/fileinfothread.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "fileinfothread_p.h"
+#include <qdiriterator.h>
+
+#include <QDebug>
+
+
+FileInfoThread::FileInfoThread(QObject *parent)
+ : QThread(parent),
+ abort(false),
+ watcher(0),
+ sortFlags(QDir::Name),
+ needUpdate(true),
+ folderUpdate(false),
+ sortUpdate(false),
+ showDirs(true),
+ showDirsFirst(false),
+ showDotDot(false),
+ showOnlyReadable(false)
+{
+ watcher = new QFileSystemWatcher(this);
+ connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString)));
+ connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFile(QString)));
+ start(LowPriority);
+}
+
+FileInfoThread::~FileInfoThread()
+{
+ QMutexLocker locker(&mutex);
+ abort = true;
+ condition.wakeOne();
+ locker.unlock();
+ wait();
+}
+
+void FileInfoThread::clear()
+{
+ QMutexLocker locker(&mutex);
+ watcher->removePaths(watcher->files());
+ watcher->removePaths(watcher->directories());
+}
+
+void FileInfoThread::removePath(const QString &path)
+{
+ QMutexLocker locker(&mutex);
+ watcher->removePath(path);
+ currentPath.clear();
+}
+
+void FileInfoThread::setPath(const QString &path)
+{
+ Q_ASSERT(!path.isEmpty());
+
+ QMutexLocker locker(&mutex);
+ watcher->addPath(path);
+ currentPath = path;
+ needUpdate = true;
+ condition.wakeAll();
+}
+
+void FileInfoThread::setRootPath(const QString &path)
+{
+ Q_ASSERT(!path.isEmpty());
+
+ QMutexLocker locker(&mutex);
+ rootPath = path;
+}
+
+void FileInfoThread::dirChanged(const QString &directoryPath)
+{
+ Q_UNUSED(directoryPath);
+ QMutexLocker locker(&mutex);
+ folderUpdate = true;
+ condition.wakeAll();
+}
+
+void FileInfoThread::setSortFlags(QDir::SortFlags flags)
+{
+ QMutexLocker locker(&mutex);
+ sortFlags = flags;
+ sortUpdate = true;
+ condition.wakeAll();
+}
+
+void FileInfoThread::setNameFilters(const QStringList & filters)
+{
+ QMutexLocker locker(&mutex);
+ nameFilters = filters;
+ folderUpdate = true;
+ condition.wakeAll();
+}
+
+void FileInfoThread::setShowDirs(bool showFolders)
+{
+ QMutexLocker locker(&mutex);
+ showDirs = showFolders;
+ folderUpdate = true;
+ condition.wakeAll();
+}
+
+void FileInfoThread::setShowDirsFirst(bool showDirsFirst)
+{
+ QMutexLocker locker(&mutex);
+ showDirsFirst = showDirsFirst;
+ folderUpdate = true;
+ condition.wakeAll();
+}
+
+void FileInfoThread::setShowDotDot(bool on)
+{
+ QMutexLocker locker(&mutex);
+ showDotDot = on;
+ folderUpdate = true;
+ condition.wakeAll();
+}
+
+void FileInfoThread::setShowOnlyReadable(bool on)
+{
+ QMutexLocker locker(&mutex);
+ showOnlyReadable = on;
+ folderUpdate = true;
+ condition.wakeAll();
+}
+
+void FileInfoThread::updateFile(const QString &path)
+{
+ Q_UNUSED(path);
+ QMutexLocker locker(&mutex);
+ folderUpdate = true;
+ condition.wakeAll();
+}
+
+void FileInfoThread::run()
+{
+ forever {
+ bool updateFiles = false;
+ QMutexLocker locker(&mutex);
+ if (abort) {
+ return;
+ }
+ if (currentPath.isEmpty() || !needUpdate)
+ condition.wait(&mutex);
+
+ if (abort) {
+ return;
+ }
+
+ if (!currentPath.isEmpty()) {
+ updateFiles = true;
+ }
+ if (updateFiles)
+ getFileInfos(currentPath);
+ locker.unlock();
+ }
+}
+
+
+void FileInfoThread::getFileInfos(const QString &path)
+{
+ QDir::Filters filter;
+ filter = QDir::Files | QDir::NoDot | QDir::CaseSensitive;
+ if (showDirs)
+ filter = filter | QDir::AllDirs | QDir::Drives;
+ if ((path == rootPath) || !showDotDot)
+ filter = filter | QDir::NoDotDot;
+ if (showOnlyReadable)
+ filter = filter | QDir::Readable;
+ if (showDirsFirst)
+ sortFlags = sortFlags | QDir::DirsFirst;
+
+ QDir currentDir(path, QString(), sortFlags);
+ QFileInfoList fileInfoList;
+ QList<FileProperty> filePropertyList;
+
+ fileInfoList = currentDir.entryInfoList(nameFilters, filter, sortFlags);
+
+ if (!fileInfoList.isEmpty()) {
+ foreach (QFileInfo info, fileInfoList) {
+ //qDebug() << "Adding file : " << info.fileName() << "to list ";
+ filePropertyList << FileProperty(info);
+ }
+ if (folderUpdate) {
+ int fromIndex = 0;
+ int toIndex = currentFileList.size()-1;
+ findChangeRange(filePropertyList, fromIndex, toIndex);
+ folderUpdate = false;
+ currentFileList = filePropertyList;
+ //qDebug() << "emit directoryUpdated : " << fromIndex << " " << toIndex;
+ emit directoryUpdated(path, filePropertyList, fromIndex, toIndex);
+ } else {
+ currentFileList = filePropertyList;
+ if (sortUpdate) {
+ emit sortFinished(filePropertyList);
+ sortUpdate = false;
+ } else
+ emit directoryChanged(path, filePropertyList);
+ }
+ } else {
+ // The directory is empty
+ if (folderUpdate) {
+ int fromIndex = 0;
+ int toIndex = currentFileList.size()-1;
+ folderUpdate = false;
+ currentFileList.clear();
+ emit directoryUpdated(path, filePropertyList, fromIndex, toIndex);
+ } else {
+ currentFileList.clear();
+ emit directoryChanged(path, filePropertyList);
+ }
+ }
+ needUpdate = false;
+}
+
+void FileInfoThread::findChangeRange(const QList<FileProperty> &list, int &fromIndex, int &toIndex)
+{
+ if (currentFileList.size() == 0) {
+ fromIndex = 0;
+ toIndex = list.size();
+ return;
+ }
+
+ int i;
+ int listSize = list.size() < currentFileList.size() ? list.size() : currentFileList.size();
+ bool changeFound = false;
+
+ for (i=0; i < listSize; i++) {
+ if (list.at(i) != currentFileList.at(i)) {
+ changeFound = true;
+ break;
+ }
+ }
+
+ if (changeFound)
+ fromIndex = i;
+ else
+ fromIndex = i-1;
+
+ // For now I let the rest of the list be updated..
+ toIndex = list.size() > currentFileList.size() ? list.size() - 1 : currentFileList.size() - 1;
+}
diff --git a/src/imports/folderlistmodel/fileinfothread_p.h b/src/imports/folderlistmodel/fileinfothread_p.h
new file mode 100644
index 0000000000..a5be6e6fcc
--- /dev/null
+++ b/src/imports/folderlistmodel/fileinfothread_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILEINFOTHREAD_P_H
+#define FILEINFOTHREAD_P_H
+
+#include <QThread>
+#include <QMutex>
+#include <QWaitCondition>
+#include <QFileSystemWatcher>
+#include <QFileInfo>
+#include <QDir>
+
+#include "fileproperty_p.h"
+
+class FileInfoThread : public QThread
+{
+ Q_OBJECT
+
+Q_SIGNALS:
+ void directoryChanged(const QString &directory, const QList<FileProperty> &list) const;
+ void directoryUpdated(const QString &directory, const QList<FileProperty> &list, int fromIndex, int toIndex) const;
+ void sortFinished(const QList<FileProperty> &list) const;
+
+public:
+ FileInfoThread(QObject *parent = 0);
+ ~FileInfoThread();
+
+ void clear();
+ void removePath(const QString &path);
+ void setPath(const QString &path);
+ void setRootPath(const QString &path);
+ void setSortFlags(QDir::SortFlags flags);
+ void setNameFilters(const QStringList & nameFilters);
+ void setShowDirs(bool showFolders);
+ void setShowDirsFirst(bool showDirsFirst);
+ void setShowDotDot(bool on);
+ void setShowOnlyReadable(bool on);
+
+public Q_SLOTS:
+ void dirChanged(const QString &directoryPath);
+ void updateFile(const QString &path);
+
+protected:
+ void run();
+ void getFileInfos(const QString &path);
+ void findChangeRange(const QList<FileProperty> &list, int &fromIndex, int &toIndex);
+
+private:
+ QMutex mutex;
+ QWaitCondition condition;
+ volatile bool abort;
+
+ QFileSystemWatcher *watcher;
+ QList<FileProperty> currentFileList;
+ QDir::SortFlags sortFlags;
+ QString currentPath;
+ QString rootPath;
+ QStringList nameFilters;
+ bool needUpdate;
+ bool folderUpdate;
+ bool sortUpdate;
+ bool showDirs;
+ bool showDirsFirst;
+ bool showDotDot;
+ bool showOnlyReadable;
+};
+
+#endif // FILEINFOTHREAD_P_H
diff --git a/src/imports/folderlistmodel/fileproperty_p.h b/src/imports/folderlistmodel/fileproperty_p.h
new file mode 100644
index 0000000000..690581a9a3
--- /dev/null
+++ b/src/imports/folderlistmodel/fileproperty_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILEPROPERTY_P_H
+#define FILEPROPERTY_P_H
+
+#include <QFileInfo>
+#include <QDateTime>
+
+class FileProperty
+{
+public:
+ FileProperty(const QFileInfo &info)
+ {
+ mFileName = info.fileName();
+ mFilePath = info.filePath();
+ mBaseName = info.baseName();
+ mSize = info.size();
+ mSuffix = info.completeSuffix();
+ mIsDir = info.isDir();
+ mIsFile = info.isFile();
+ mLastModified = info.lastModified();
+ mLastRead = info.lastRead();
+ }
+ ~FileProperty()
+ {}
+
+ inline QString fileName() const { return mFileName; }
+ inline QString filePath() const { return mFilePath; }
+ inline QString baseName() const { return mBaseName; }
+ inline qint64 size() const { return mSize; }
+ inline QString suffix() const { return mSuffix; }
+ inline bool isDir() const { return mIsDir; }
+ inline bool isFile() const { return mIsFile; }
+ inline QDateTime lastModified() const { return mLastModified; }
+ inline QDateTime lastRead() const { return mLastRead; }
+
+ inline bool operator !=(const FileProperty &fileInfo) const {
+ return !operator==(fileInfo);
+ }
+ bool operator ==(const FileProperty &property) const {
+ return ((mFileName == property.mFileName) && (isDir() == property.isDir()));
+ }
+
+private:
+ QString mFileName;
+ QString mFilePath;
+ QString mBaseName;
+ QString mSuffix;
+ qint64 mSize;
+ bool mIsDir;
+ bool mIsFile;
+ QDateTime mLastModified;
+ QDateTime mLastRead;
+};
+#endif // FILEPROPERTY_P_H
diff --git a/src/imports/folderlistmodel/folderlistmodel.json b/src/imports/folderlistmodel/folderlistmodel.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/src/imports/folderlistmodel/folderlistmodel.json
@@ -0,0 +1 @@
+{}
diff --git a/src/imports/folderlistmodel/folderlistmodel.pro b/src/imports/folderlistmodel/folderlistmodel.pro
index b4cfcea495..592d8375c8 100644
--- a/src/imports/folderlistmodel/folderlistmodel.pro
+++ b/src/imports/folderlistmodel/folderlistmodel.pro
@@ -2,10 +2,13 @@ TARGET = qmlfolderlistmodelplugin
TARGETPATH = Qt/labs/folderlistmodel
include(../qimportbase.pri)
-QT += widgets qml
+QT += qml
-SOURCES += qquickfolderlistmodel.cpp plugin.cpp
-HEADERS += qquickfolderlistmodel.h
+SOURCES += qquickfolderlistmodel.cpp plugin.cpp \
+ fileinfothread.cpp
+HEADERS += qquickfolderlistmodel.h \
+ fileproperty_p.h \
+ fileinfothread_p.h
DESTDIR = $$QT.qml.imports/$$TARGETPATH
target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp
index 78fc230fdc..bc904512a8 100644
--- a/src/imports/folderlistmodel/plugin.cpp
+++ b/src/imports/folderlistmodel/plugin.cpp
@@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE
class QmlFolderListModelPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "folderlistmodel.json")
+
public:
virtual void registerTypes(const char *uri)
{
@@ -64,8 +66,3 @@ public:
QT_END_NAMESPACE
#include "plugin.moc"
-
-//![plugin export decl]
-Q_EXPORT_PLUGIN2(qmlfolderlistmodelplugin, QT_PREPEND_NAMESPACE(QmlFolderListModelPlugin));
-//![plugin export decl]
-
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index 5621622cca..d68d7af6d4 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -41,25 +41,71 @@
//![code]
#include "qquickfolderlistmodel.h"
-#include <QDirModel>
+#include "fileinfothread_p.h"
+#include "fileproperty_p.h"
#include <QDebug>
#include <qqmlcontext.h>
-#ifndef QT_NO_DIRMODEL
-
QT_BEGIN_NAMESPACE
class QQuickFolderListModelPrivate
{
+ Q_DECLARE_PUBLIC(QQuickFolderListModel)
+
public:
- QQuickFolderListModelPrivate()
- : sortField(QQuickFolderListModel::Name), sortReversed(false), count(0), showDirs(true), showDots(false), showOnlyReadable(false), insideRefresh(false) {
+ QQuickFolderListModelPrivate(QQuickFolderListModel *q)
+ : q_ptr(q),
+ sortField(QQuickFolderListModel::Name), sortReversed(false), showDirs(true), showDirsFirst(false), showDots(false), showOnlyReadable(false)
+ {
nameFilters << QLatin1String("*");
}
- void updateSorting() {
- QDir::SortFlags flags = 0;
- switch(sortField) {
+
+ QQuickFolderListModel *q_ptr;
+ QUrl currentDir;
+ QUrl rootDir;
+ FileInfoThread fileInfoThread;
+ QList<FileProperty> data;
+ QHash<int, QByteArray> roleNames;
+ QQuickFolderListModel::SortField sortField;
+ QStringList nameFilters;
+ bool sortReversed;
+ bool showDirs;
+ bool showDirsFirst;
+ bool showDots;
+ bool showOnlyReadable;
+
+ ~QQuickFolderListModelPrivate() {}
+ void init();
+ void updateSorting();
+
+ // private slots
+ void _q_directoryChanged(const QString &directory, const QList<FileProperty> &list);
+ void _q_directoryUpdated(const QString &directory, const QList<FileProperty> &list, int fromIndex, int toIndex);
+ void _q_sortFinished(const QList<FileProperty> &list);
+};
+
+
+void QQuickFolderListModelPrivate::init()
+{
+ Q_Q(QQuickFolderListModel);
+ qRegisterMetaType<QList<FileProperty> >("QList<FileProperty>");
+ q->connect(&fileInfoThread, SIGNAL(directoryChanged(QString, QList<FileProperty>)),
+ q, SLOT(_q_directoryChanged(QString, QList<FileProperty>)));
+ q->connect(&fileInfoThread, SIGNAL(directoryUpdated(QString, QList<FileProperty>, int, int)),
+ q, SLOT(_q_directoryUpdated(QString, QList<FileProperty>, int, int)));
+ q->connect(&fileInfoThread, SIGNAL(sortFinished(QList<FileProperty>)),
+ q, SLOT(_q_sortFinished(QList<FileProperty>)));
+}
+
+
+void QQuickFolderListModelPrivate::updateSorting()
+{
+ Q_Q(QQuickFolderListModel);
+
+ QDir::SortFlags flags = 0;
+
+ switch (sortField) {
case QQuickFolderListModel::Unsorted:
flags |= QDir::Unsorted;
break;
@@ -75,26 +121,80 @@ public:
case QQuickFolderListModel::Type:
flags |= QDir::Type;
break;
- }
+ default:
+ break;
+ }
+
+ emit q->layoutAboutToBeChanged();
+
+ if (sortReversed)
+ flags |= QDir::Reversed;
+
+ fileInfoThread.setSortFlags(flags);
+}
+
+void QQuickFolderListModelPrivate::_q_directoryChanged(const QString &directory, const QList<FileProperty> &list)
+{
+ Q_Q(QQuickFolderListModel);
+ Q_UNUSED(directory);
+
+ data = list;
+ q->endResetModel();
+ emit q->rowCountChanged();
+ emit q->folderChanged();
+}
- if (sortReversed)
- flags |= QDir::Reversed;
- model.setSorting(flags);
+void QQuickFolderListModelPrivate::_q_directoryUpdated(const QString &directory, const QList<FileProperty> &list, int fromIndex, int toIndex)
+{
+ Q_Q(QQuickFolderListModel);
+ Q_UNUSED(directory);
+
+ QModelIndex parent;
+ if (data.size() > list.size()) {
+ //File(s) removed. Since I do not know how many
+ //or where I need to update the whole list from the first item.
+ data = list;
+ q->beginRemoveRows(parent, fromIndex, toIndex);
+ q->endRemoveRows();
+ q->beginInsertRows(parent, fromIndex, list.size()-1);
+ q->endInsertRows();
+ emit q->rowCountChanged();
+ } else if (data.size() < list.size()) {
+ //qDebug() << "File added. FromIndex: " << fromIndex << " toIndex: " << toIndex << " list size: " << list.size();
+ //File(s) added. Calculate how many and insert
+ //from the first changed one.
+ toIndex = fromIndex + (list.size() - data.size()-1);
+ q->beginInsertRows(parent, fromIndex, toIndex);
+ q->endInsertRows();
+ data = list;
+ emit q->rowCountChanged();
+ QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0);
+ QModelIndex modelIndexTo = q->createIndex(toIndex, 0);
+ emit q->dataChanged(modelIndexFrom, modelIndexTo);
+ } else {
+ //qDebug() << "File has been updated";
+ QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0);
+ QModelIndex modelIndexTo = q->createIndex(toIndex, 0);
+ data = list;
+ emit q->dataChanged(modelIndexFrom, modelIndexTo);
}
+}
+
+void QQuickFolderListModelPrivate::_q_sortFinished(const QList<FileProperty> &list)
+{
+ Q_Q(QQuickFolderListModel);
+
+ QModelIndex parent;
+ q->beginRemoveRows(parent, 0, data.size()-1);
+ data.clear();
+ q->endRemoveRows();
+
+ q->beginInsertRows(parent, 0, list.size()-1);
+ data = list;
+ q->endInsertRows();
+}
- QDirModel model;
- QUrl folder;
- QStringList nameFilters;
- QModelIndex folderIndex;
- QQuickFolderListModel::SortField sortField;
- bool sortReversed;
- int count;
- bool showDirs;
- bool showDots;
- bool showOnlyReadable;
- bool insideRefresh;
-};
/*!
\qmlclass FolderListModel QQuickFolderListModel
@@ -115,8 +215,14 @@ public:
Components access names and paths via the following roles:
\list
- \o fileName
- \o filePath
+ \o \c fileName
+ \o \c filePath
+ \o \c fileBaseName
+ \o \c fileSuffix
+ \o \c fileSize
+ \o \c fileModified
+ \o \c fileAccessed
+ \o \c fileIsDir
\endlist
Additionally a file entry can be differentiated from a folder entry via the
@@ -157,39 +263,62 @@ public:
*/
QQuickFolderListModel::QQuickFolderListModel(QObject *parent)
- : QAbstractListModel(parent)
+ : QAbstractListModel(parent), d_ptr(new QQuickFolderListModelPrivate(this))
{
- QHash<int, QByteArray> roles;
- roles[FileNameRole] = "fileName";
- roles[FilePathRole] = "filePath";
- setRoleNames(roles);
-
- d = new QQuickFolderListModelPrivate;
- d->model.setFilter(QDir::AllDirs | QDir::Files | QDir::Drives | QDir::NoDotAndDotDot);
- connect(&d->model, SIGNAL(rowsInserted(const QModelIndex&,int,int))
- , this, SLOT(inserted(const QModelIndex&,int,int)));
- connect(&d->model, SIGNAL(rowsRemoved(const QModelIndex&,int,int))
- , this, SLOT(removed(const QModelIndex&,int,int)));
- connect(&d->model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))
- , this, SLOT(handleDataChanged(const QModelIndex&,const QModelIndex&)));
- connect(&d->model, SIGNAL(modelReset()), this, SLOT(refresh()));
- connect(&d->model, SIGNAL(layoutChanged()), this, SLOT(refresh()));
+ Q_D(QQuickFolderListModel);
+ d->roleNames[FileNameRole] = "fileName";
+ d->roleNames[FilePathRole] = "filePath";
+ d->roleNames[FileBaseNameRole] = "fileBaseName";
+ d->roleNames[FileSuffixRole] = "fileSuffix";
+ d->roleNames[FileSizeRole] = "fileSize";
+ d->roleNames[FileLastModifiedRole] = "fileModified";
+ d->roleNames[FileLastReadRole] = "fileAccessed";
+ d->roleNames[FileIsDirRole] = "fileIsDir";
+ setRoleNames(d->roleNames);
+
+ d->init();
}
QQuickFolderListModel::~QQuickFolderListModel()
{
- delete d;
}
QVariant QQuickFolderListModel::data(const QModelIndex &index, int role) const
{
+ Q_D(const QQuickFolderListModel);
QVariant rv;
- QModelIndex modelIndex = d->model.index(index.row(), 0, d->folderIndex);
- if (modelIndex.isValid()) {
- if (role == FileNameRole)
- rv = d->model.data(modelIndex, QDirModel::FileNameRole).toString();
- else if (role == FilePathRole)
- rv = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString());
+
+ if (index.row() >= d->data.size())
+ return rv;
+
+ switch (role)
+ {
+ case FileNameRole:
+ rv = d->data.at(index.row()).fileName();
+ break;
+ case FilePathRole:
+ rv = d->data.at(index.row()).filePath();
+ break;
+ case FileBaseNameRole:
+ rv = d->data.at(index.row()).baseName();
+ break;
+ case FileSuffixRole:
+ rv = d->data.at(index.row()).suffix();
+ break;
+ case FileSizeRole:
+ rv = d->data.at(index.row()).size();
+ break;
+ case FileLastModifiedRole:
+ rv = d->data.at(index.row()).lastModified().date().toString(Qt::ISODate) + " " + d->data.at(index.row()).lastModified().time().toString();
+ break;
+ case FileLastReadRole:
+ rv = d->data.at(index.row()).lastRead().date().toString(Qt::ISODate) + " " + d->data.at(index.row()).lastRead().time().toString();
+ break;
+ case FileIsDirRole:
+ rv = d->data.at(index.row()).isDir();
+ break;
+ default:
+ break;
}
return rv;
}
@@ -202,8 +331,14 @@ QVariant QQuickFolderListModel::data(const QModelIndex &index, int role) const
*/
int QQuickFolderListModel::rowCount(const QModelIndex &parent) const
{
+ Q_D(const QQuickFolderListModel);
Q_UNUSED(parent);
- return d->count;
+ return d->data.size();
+}
+
+QModelIndex QQuickFolderListModel::index(int row, int , const QModelIndex &) const
+{
+ return createIndex(row, 0);
}
/*!
@@ -219,46 +354,70 @@ int QQuickFolderListModel::rowCount(const QModelIndex &parent) const
*/
QUrl QQuickFolderListModel::folder() const
{
- return d->folder;
+ Q_D(const QQuickFolderListModel);
+ return d->currentDir;
}
void QQuickFolderListModel::setFolder(const QUrl &folder)
{
- if (folder == d->folder)
+ Q_D(QQuickFolderListModel);
+
+ if (folder == d->currentDir)
return;
- QModelIndex index = d->model.index(folder.toLocalFile()); // This can modify the filtering rules.
- if ((index.isValid() && d->model.isDir(index)) || folder.toLocalFile().isEmpty()) {
- d->folder = folder;
- QMetaObject::invokeMethod(this, "resetFiltering", Qt::QueuedConnection); // resetFiltering will invoke refresh().
- emit folderChanged();
+ QString resolvedPath = QDir::cleanPath(folder.path());
+
+ beginResetModel();
+
+ //Remove the old path for the file system watcher
+ if (!d->currentDir.isEmpty())
+ d->fileInfoThread.removePath(d->currentDir.path());
+
+ d->currentDir = folder;
+
+ QFileInfo info(resolvedPath);
+ if (!info.exists() || !info.isDir()) {
+ d->data.clear();
+ endResetModel();
+ emit rowCountChanged();
+ return;
}
+
+ d->fileInfoThread.setPath(resolvedPath);
+}
+
+
+/*!
+ \qmlproperty string QQuickFolderListModel::rootFolder
+
+ When the rootFolder is set, then this folder will
+ be threated as the root in the file system, so that
+ you can only travers sub folders from this rootFolder.
+*/
+QUrl QQuickFolderListModel::rootFolder() const
+{
+ Q_D(const QQuickFolderListModel);
+ return d->rootDir;
}
-void QQuickFolderListModel::resetFiltering()
+void QQuickFolderListModel::setRootFolder(const QUrl &path)
{
- // ensure that we reset the filtering rules, because the QDirModel::index()
- // function isn't quite as const as it claims to be.
- QDir::Filters filt = d->model.filter();
+ Q_D(QQuickFolderListModel);
- if (d->showDirs)
- filt |= (QDir::AllDirs | QDir::Drives);
- else
- filt &= ~(QDir::AllDirs | QDir::Drives);
+ if (path.isEmpty())
+ return;
- if (d->showDots)
- filt &= ~QDir::NoDotAndDotDot;
- else
- filt |= QDir::NoDotAndDotDot;
+ QString resolvedPath = QDir::cleanPath(path.path());
- if (d->showOnlyReadable)
- filt |= QDir::Readable;
- else
- filt &= ~QDir::Readable;
+ QFileInfo info(resolvedPath);
+ if (!info.exists() || !info.isDir())
+ return;
- d->model.setFilter(filt); // this causes a refresh().
+ d->fileInfoThread.setRootPath(resolvedPath);
+ d->rootDir = path;
}
+
/*!
\qmlproperty url FolderListModel::parentFolder
@@ -266,7 +425,9 @@ void QQuickFolderListModel::resetFiltering()
*/
QUrl QQuickFolderListModel::parentFolder() const
{
- QString localFile = d->folder.toLocalFile();
+ Q_D(const QQuickFolderListModel);
+
+ QString localFile = d->currentDir.toLocalFile();
if (!localFile.isEmpty()) {
QDir dir(localFile);
#if defined(Q_OS_WIN)
@@ -277,10 +438,10 @@ QUrl QQuickFolderListModel::parentFolder() const
dir.cdUp();
localFile = dir.path();
} else {
- int pos = d->folder.path().lastIndexOf(QLatin1Char('/'));
+ int pos = d->currentDir.path().lastIndexOf(QLatin1Char('/'));
if (pos == -1)
return QUrl();
- localFile = d->folder.path().left(pos);
+ localFile = d->currentDir.path().left(pos);
}
return QUrl::fromLocalFile(localFile);
}
@@ -303,13 +464,15 @@ QUrl QQuickFolderListModel::parentFolder() const
*/
QStringList QQuickFolderListModel::nameFilters() const
{
+ Q_D(const QQuickFolderListModel);
return d->nameFilters;
}
void QQuickFolderListModel::setNameFilters(const QStringList &filters)
{
+ Q_D(QQuickFolderListModel);
+ d->fileInfoThread.setNameFilters(filters);
d->nameFilters = filters;
- d->model.setNameFilters(d->nameFilters);
}
void QQuickFolderListModel::classBegin()
@@ -318,11 +481,10 @@ void QQuickFolderListModel::classBegin()
void QQuickFolderListModel::componentComplete()
{
- if (!d->folder.isValid() || d->folder.toLocalFile().isEmpty() || !QDir().exists(d->folder.toLocalFile()))
- setFolder(QUrl(QLatin1String("file://")+QDir::currentPath()));
+ Q_D(QQuickFolderListModel);
- if (!d->folderIndex.isValid())
- QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
+ if (!d->currentDir.isValid() || d->currentDir.toLocalFile().isEmpty() || !QDir().exists(d->currentDir.toLocalFile()))
+ setFolder(QUrl(QLatin1String("file://")+QDir::currentPath()));
}
/*!
@@ -331,9 +493,9 @@ void QQuickFolderListModel::componentComplete()
The \a sortField property contains field to use for sorting. sortField
may be one of:
\list
- \o Unsorted - no sorting is applied. The order is system default.
+ \o Unsorted - no sorting is applied.
\o Name - sort by filename
- \o Time - sort by time modified
+ \o LastModified - sort by time modified
\o Size - sort by file size
\o Type - sort by file type (extension)
\endlist
@@ -342,17 +504,25 @@ void QQuickFolderListModel::componentComplete()
*/
QQuickFolderListModel::SortField QQuickFolderListModel::sortField() const
{
+ Q_D(const QQuickFolderListModel);
return d->sortField;
}
void QQuickFolderListModel::setSortField(SortField field)
{
+ Q_D(QQuickFolderListModel);
if (field != d->sortField) {
d->sortField = field;
d->updateSorting();
}
}
+int QQuickFolderListModel::roleFromString(const QString &roleName) const
+{
+ Q_D(const QQuickFolderListModel);
+ return d->roleNames.key(roleName.toLatin1(), -1);
+}
+
/*!
\qmlproperty bool FolderListModel::sortReversed
@@ -362,11 +532,14 @@ void QQuickFolderListModel::setSortField(SortField field)
*/
bool QQuickFolderListModel::sortReversed() const
{
+ Q_D(const QQuickFolderListModel);
return d->sortReversed;
}
void QQuickFolderListModel::setSortReversed(bool rev)
{
+ Q_D(QQuickFolderListModel);
+
if (rev != d->sortReversed) {
d->sortReversed = rev;
d->updateSorting();
@@ -382,91 +555,66 @@ void QQuickFolderListModel::setSortReversed(bool rev)
bool QQuickFolderListModel::isFolder(int index) const
{
if (index != -1) {
- QModelIndex idx = d->model.index(index, 0, d->folderIndex);
- if (idx.isValid())
- return d->model.isDir(idx);
+ QModelIndex idx = createIndex(index, 0);
+ if (idx.isValid()) {
+ QVariant var = data(idx, FileIsDirRole);
+ if (var.isValid())
+ return var.toBool();
+ }
}
return false;
}
-void QQuickFolderListModel::refresh()
-{
- if (d->insideRefresh)
- return;
- d->insideRefresh = true;
+/*!
+ \qmlproperty bool FolderListModel::showDirs
- d->folderIndex = QModelIndex();
- if (d->count) {
- emit beginRemoveRows(QModelIndex(), 0, d->count-1);
- d->count = 0;
- emit endRemoveRows();
- }
+ If true, directories are included in the model; otherwise only files
+ are included.
- d->folderIndex = d->model.index(d->folder.toLocalFile());
- int newcount = d->model.rowCount(d->folderIndex);
- if (newcount) {
- emit beginInsertRows(QModelIndex(), 0, newcount-1);
- d->count = newcount;
- emit endInsertRows();
- }
+ By default, this property is true.
- d->insideRefresh = false; // finished refreshing.
-}
+ Note that the nameFilters are not applied to directories.
-void QQuickFolderListModel::inserted(const QModelIndex &index, int start, int end)
+ \sa showDotAndDotDot
+*/
+bool QQuickFolderListModel::showDirs() const
{
- if (index == d->folderIndex) {
- emit beginInsertRows(QModelIndex(), start, end);
- d->count = d->model.rowCount(d->folderIndex);
- emit endInsertRows();
- }
+ Q_D(const QQuickFolderListModel);
+ return d->showDirs;
}
-void QQuickFolderListModel::removed(const QModelIndex &index, int start, int end)
+void QQuickFolderListModel::setShowDirs(bool on)
{
- if (index == d->folderIndex) {
- emit beginRemoveRows(QModelIndex(), start, end);
- d->count = d->model.rowCount(d->folderIndex);
- emit endRemoveRows();
- }
-}
+ Q_D(QQuickFolderListModel);
-void QQuickFolderListModel::handleDataChanged(const QModelIndex &start, const QModelIndex &end)
-{
- if (start.parent() == d->folderIndex)
- emit dataChanged(index(start.row(),0), index(end.row(),0));
+ d->fileInfoThread.setShowDirs(on);
+ d->showDirs = on;
}
/*!
- \qmlproperty bool FolderListModel::showDirs
+ \qmlproperty bool FolderListModel::showDirsFirst
- If true, directories are included in the model; otherwise only files
- are included.
+ If true, if directories are included in the model they will
+ always be shown first, then the files.
- By default, this property is true.
-
- Note that the nameFilters are not applied to directories.
+ By default, this property is false.
- \sa showDotAndDotDot
*/
-bool QQuickFolderListModel::showDirs() const
+bool QQuickFolderListModel::showDirsFirst() const
{
- return d->model.filter() & QDir::AllDirs;
+ Q_D(const QQuickFolderListModel);
+ return d->showDirsFirst;
}
-void QQuickFolderListModel::setShowDirs(bool on)
+void QQuickFolderListModel::setShowDirsFirst(bool on)
{
- if (!(d->model.filter() & QDir::AllDirs) == !on)
- return;
- if (on) {
- d->showDirs = true;
- d->model.setFilter(d->model.filter() | QDir::AllDirs | QDir::Drives);
- } else {
- d->showDirs = false;
- d->model.setFilter(d->model.filter() & ~(QDir::AllDirs | QDir::Drives));
- }
+ Q_D(QQuickFolderListModel);
+
+ d->fileInfoThread.setShowDirsFirst(on);
+ d->showDirsFirst = on;
}
+
/*!
\qmlproperty bool FolderListModel::showDotAndDotDot
@@ -479,19 +627,16 @@ void QQuickFolderListModel::setShowDirs(bool on)
*/
bool QQuickFolderListModel::showDotAndDotDot() const
{
- return !(d->model.filter() & QDir::NoDotAndDotDot);
+ Q_D(const QQuickFolderListModel);
+ return d->showDots;
}
void QQuickFolderListModel::setShowDotAndDotDot(bool on)
{
- if (!(d->model.filter() & QDir::NoDotAndDotDot) == on)
- return;
- if (on) {
- d->showDots = true;
- d->model.setFilter(d->model.filter() & ~QDir::NoDotAndDotDot);
- } else {
- d->showDots = false;
- d->model.setFilter(d->model.filter() | QDir::NoDotAndDotDot);
+ Q_D(QQuickFolderListModel);
+
+ if (on != d->showDots) {
+ d->fileInfoThread.setShowDotDot(on);
}
}
@@ -507,23 +652,46 @@ void QQuickFolderListModel::setShowDotAndDotDot(bool on)
*/
bool QQuickFolderListModel::showOnlyReadable() const
{
- return d->model.filter() & QDir::Readable;
+ Q_D(const QQuickFolderListModel);
+ return d->showOnlyReadable;
}
void QQuickFolderListModel::setShowOnlyReadable(bool on)
{
- if (!(d->model.filter() & QDir::Readable) == !on)
- return;
- if (on) {
- d->showOnlyReadable = true;
- d->model.setFilter(d->model.filter() | QDir::Readable);
- } else {
- d->showOnlyReadable = false;
- d->model.setFilter(d->model.filter() & ~QDir::Readable);
+ Q_D(QQuickFolderListModel);
+
+ if (on != d->showOnlyReadable) {
+ d->fileInfoThread.setShowOnlyReadable(on);
}
}
+/*!
+ \qmlmethod QVariant QQuickFolderListModel::get(int idx, const QString &property) const
+
+ Get the folder property for the given index. The following properties
+ are available.
+
+ \list
+ \o \c fileName
+ \o \c filePath
+ \o \c fileBaseName
+ \o \c fileSuffix
+ \o \c fileSize
+ \o \c fileModified
+ \o \c fileAccessed
+ \o \c fileIsDir
+ \endlist
+*/
+QVariant QQuickFolderListModel::get(int idx, const QString &property) const
+{
+ int role = roleFromString(property);
+ if (role >= 0 && idx >= 0)
+ return data(index(idx, 0), role);
+ else
+ return QVariant();
+}
+
+#include "moc_qquickfolderlistmodel.cpp"
+
//![code]
QT_END_NAMESPACE
-
-#endif // QT_NO_DIRMODEL
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h
index 10af7c8075..830a30b146 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.h
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h
@@ -47,8 +47,6 @@
#include <QUrl>
#include <QAbstractListModel>
-#ifndef QT_NO_DIRMODEL
-
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -68,14 +66,16 @@ class QQuickFolderListModel : public QAbstractListModel, public QQmlParserStatus
//![class props]
Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged)
+ Q_PROPERTY(QUrl rootFolder READ rootFolder WRITE setRootFolder)
Q_PROPERTY(QUrl parentFolder READ parentFolder NOTIFY folderChanged)
Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters)
Q_PROPERTY(SortField sortField READ sortField WRITE setSortField)
Q_PROPERTY(bool sortReversed READ sortReversed WRITE setSortReversed)
Q_PROPERTY(bool showDirs READ showDirs WRITE setShowDirs)
+ Q_PROPERTY(bool showDirsFirst READ showDirsFirst WRITE setShowDirsFirst)
Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot)
Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable)
- Q_PROPERTY(int count READ count)
+ Q_PROPERTY(int count READ count NOTIFY rowCountChanged)
//![class props]
//![abslistmodel]
@@ -83,10 +83,20 @@ public:
QQuickFolderListModel(QObject *parent = 0);
~QQuickFolderListModel();
- enum Roles { FileNameRole = Qt::UserRole+1, FilePathRole = Qt::UserRole+2 };
-
- int rowCount(const QModelIndex &parent) const;
- QVariant data(const QModelIndex &index, int role) const;
+ enum Roles {
+ FileNameRole = Qt::UserRole + 1,
+ FilePathRole = Qt::UserRole + 2,
+ FileBaseNameRole = Qt::UserRole + 3,
+ FileSuffixRole = Qt::UserRole + 4,
+ FileSizeRole = Qt::UserRole + 5,
+ FileLastModifiedRole = Qt::UserRole + 6,
+ FileLastReadRole = Qt::UserRole +7,
+ FileIsDirRole = Qt::UserRole + 8
+ };
+
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
//![abslistmodel]
//![count]
@@ -96,6 +106,8 @@ public:
//![prop funcs]
QUrl folder() const;
void setFolder(const QUrl &folder);
+ QUrl rootFolder() const;
+ void setRootFolder(const QUrl &path);
QUrl parentFolder() const;
@@ -111,49 +123,47 @@ public:
void setSortReversed(bool rev);
bool showDirs() const;
- void setShowDirs(bool);
+ void setShowDirs(bool showDirs);
+ bool showDirsFirst() const;
+ void setShowDirsFirst(bool showDirsFirst);
bool showDotAndDotDot() const;
- void setShowDotAndDotDot(bool);
+ void setShowDotAndDotDot(bool on);
bool showOnlyReadable() const;
- void setShowOnlyReadable(bool);
+ void setShowOnlyReadable(bool on);
//![prop funcs]
-//![isfolder]
Q_INVOKABLE bool isFolder(int index) const;
-//![isfolder]
+ Q_INVOKABLE QVariant get(int idx, const QString &property) const;
//![parserstatus]
virtual void classBegin();
virtual void componentComplete();
//![parserstatus]
+ int roleFromString(const QString &roleName) const;
+
//![notifier]
Q_SIGNALS:
void folderChanged();
+ void rowCountChanged() const;
//![notifier]
//![class end]
-private Q_SLOTS:
- void refresh();
- void resetFiltering();
- void inserted(const QModelIndex &index, int start, int end);
- void removed(const QModelIndex &index, int start, int end);
- void handleDataChanged(const QModelIndex &start, const QModelIndex &end);
+
private:
Q_DISABLE_COPY(QQuickFolderListModel)
- QQuickFolderListModelPrivate *d;
+ Q_DECLARE_PRIVATE(QQuickFolderListModel)
+ QScopedPointer<QQuickFolderListModelPrivate> d_ptr;
+
+ Q_PRIVATE_SLOT(d_func(), void _q_directoryChanged(const QString &directory, const QList<FileProperty> &list))
+ Q_PRIVATE_SLOT(d_func(), void _q_directoryUpdated(const QString &directory, const QList<FileProperty> &list, int fromIndex, int toIndex))
+ Q_PRIVATE_SLOT(d_func(), void _q_sortFinished(const QList<FileProperty> &list))
};
//![class end]
QT_END_NAMESPACE
-//![qml decl]
-QML_DECLARE_TYPE(QQuickFolderListModel)
-//![qml decl]
-
QT_END_HEADER
-#endif // QT_NO_DIRMODEL
-
#endif // QQUICKFOLDERLISTMODEL_H