From eb5bb9e7f547a7e222b5dbb848774639ab11f243 Mon Sep 17 00:00:00 2001 From: Maximilian Goldstein Date: Wed, 20 Jan 2021 17:23:23 +0100 Subject: Qt.labs.folderlistmodel: Make plugin optional This moves the folderlistmodel types into a new library and is meant to make them availabe to the QML compiler at some point in the future. Task-number: QTBUG-90487 Change-Id: Iee84a4804a241aa1dee5f896a02ccc9f0ecc0d8d Reviewed-by: Fabian Kosmale --- src/imports/folderlistmodel/CMakeLists.txt | 7 +- src/imports/folderlistmodel/fileinfothread.cpp | 369 -------- src/imports/folderlistmodel/fileinfothread_p.h | 133 --- src/imports/folderlistmodel/fileproperty_p.h | 103 --- src/imports/folderlistmodel/plugin.cpp | 5 +- .../folderlistmodel/qquickfolderlistmodel.cpp | 927 --------------------- .../folderlistmodel/qquickfolderlistmodel.h | 189 ----- src/labs/CMakeLists.txt | 3 + src/labs/folderlistmodel/CMakeLists.txt | 24 + src/labs/folderlistmodel/fileinfothread.cpp | 369 ++++++++ src/labs/folderlistmodel/fileinfothread_p.h | 133 +++ src/labs/folderlistmodel/fileproperty_p.h | 103 +++ src/labs/folderlistmodel/qquickfolderlistmodel.cpp | 927 +++++++++++++++++++++ src/labs/folderlistmodel/qquickfolderlistmodel.h | 191 +++++ .../qquickfolderlistmodelglobal_p.h | 73 ++ 15 files changed, 1827 insertions(+), 1729 deletions(-) delete mode 100644 src/imports/folderlistmodel/fileinfothread.cpp delete mode 100644 src/imports/folderlistmodel/fileinfothread_p.h delete mode 100644 src/imports/folderlistmodel/fileproperty_p.h delete mode 100644 src/imports/folderlistmodel/qquickfolderlistmodel.cpp delete mode 100644 src/imports/folderlistmodel/qquickfolderlistmodel.h create mode 100644 src/labs/folderlistmodel/CMakeLists.txt create mode 100644 src/labs/folderlistmodel/fileinfothread.cpp create mode 100644 src/labs/folderlistmodel/fileinfothread_p.h create mode 100644 src/labs/folderlistmodel/fileproperty_p.h create mode 100644 src/labs/folderlistmodel/qquickfolderlistmodel.cpp create mode 100644 src/labs/folderlistmodel/qquickfolderlistmodel.h create mode 100644 src/labs/folderlistmodel/qquickfolderlistmodelglobal_p.h (limited to 'src') diff --git a/src/imports/folderlistmodel/CMakeLists.txt b/src/imports/folderlistmodel/CMakeLists.txt index f1e543ad9f..85a43061f4 100644 --- a/src/imports/folderlistmodel/CMakeLists.txt +++ b/src/imports/folderlistmodel/CMakeLists.txt @@ -9,16 +9,13 @@ qt_internal_add_qml_module(qmlfolderlistmodelplugin VERSION "${CMAKE_PROJECT_VERSION}" CLASSNAME QmlFolderListModelPlugin SKIP_TYPE_REGISTRATION - GENERATE_QMLTYPES - INSTALL_QMLTYPES + PLUGIN_OPTIONAL SOURCES - fileinfothread.cpp fileinfothread_p.h - fileproperty_p.h plugin.cpp - qquickfolderlistmodel.cpp qquickfolderlistmodel.h PUBLIC_LIBRARIES Qt::CorePrivate Qt::QmlPrivate + Qt::LabsFolderListModelPrivate ) #### Keys ignored in scope 1:.:.:folderlistmodel.pro:: diff --git a/src/imports/folderlistmodel/fileinfothread.cpp b/src/imports/folderlistmodel/fileinfothread.cpp deleted file mode 100644 index a93edd3b1b..0000000000 --- a/src/imports/folderlistmodel/fileinfothread.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "fileinfothread_p.h" -#include -#include -#include - -#include - - -FileInfoThread::FileInfoThread(QObject *parent) - : QThread(parent), - abort(false), - scanPending(false), -#if QT_CONFIG(filesystemwatcher) - watcher(nullptr), -#endif - sortFlags(QDir::Name), - needUpdate(true), - folderUpdate(false), - sortUpdate(false), - showFiles(true), - showDirs(true), - showDirsFirst(false), - showDotAndDotDot(false), - showHidden(false), - showOnlyReadable(false), - caseSensitive(true) -{ -#if QT_CONFIG(filesystemwatcher) - watcher = new QFileSystemWatcher(this); - connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString))); - connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFile(QString))); -#endif // filesystemwatcher -} - -FileInfoThread::~FileInfoThread() -{ - QMutexLocker locker(&mutex); - abort = true; - condition.wakeOne(); - locker.unlock(); - wait(); -} - -void FileInfoThread::clear() -{ - QMutexLocker locker(&mutex); -#if QT_CONFIG(filesystemwatcher) - watcher->removePaths(watcher->files()); - watcher->removePaths(watcher->directories()); -#endif -} - -void FileInfoThread::removePath(const QString &path) -{ - QMutexLocker locker(&mutex); -#if QT_CONFIG(filesystemwatcher) - if (!path.startsWith(QLatin1Char(':'))) - watcher->removePath(path); -#else - Q_UNUSED(path); -#endif - currentPath.clear(); -} - -void FileInfoThread::setPath(const QString &path) -{ - Q_ASSERT(!path.isEmpty()); - - QMutexLocker locker(&mutex); -#if QT_CONFIG(filesystemwatcher) - if (!path.startsWith(QLatin1Char(':'))) - watcher->addPath(path); -#endif - currentPath = path; - needUpdate = true; - initiateScan(); -} - -void FileInfoThread::setRootPath(const QString &path) -{ - Q_ASSERT(!path.isEmpty()); - - QMutexLocker locker(&mutex); - rootPath = path; -} - -#if QT_CONFIG(filesystemwatcher) -void FileInfoThread::dirChanged(const QString &directoryPath) -{ - Q_UNUSED(directoryPath); - QMutexLocker locker(&mutex); - folderUpdate = true; - initiateScan(); -} -#endif - -void FileInfoThread::setSortFlags(QDir::SortFlags flags) -{ - QMutexLocker locker(&mutex); - sortFlags = flags; - sortUpdate = true; - needUpdate = true; - initiateScan(); -} - -void FileInfoThread::setNameFilters(const QStringList & filters) -{ - QMutexLocker locker(&mutex); - nameFilters = filters; - folderUpdate = true; - initiateScan(); -} - -void FileInfoThread::setShowFiles(bool show) -{ - QMutexLocker locker(&mutex); - showFiles = show; - folderUpdate = true; - initiateScan(); -} - -void FileInfoThread::setShowDirs(bool showFolders) -{ - QMutexLocker locker(&mutex); - showDirs = showFolders; - folderUpdate = true; - initiateScan(); -} - -void FileInfoThread::setShowDirsFirst(bool show) -{ - QMutexLocker locker(&mutex); - showDirsFirst = show; - folderUpdate = true; - initiateScan(); -} - -void FileInfoThread::setShowDotAndDotDot(bool on) -{ - QMutexLocker locker(&mutex); - showDotAndDotDot = on; - folderUpdate = true; - needUpdate = true; - initiateScan(); -} - -void FileInfoThread::setShowHidden(bool on) -{ - QMutexLocker locker(&mutex); - showHidden = on; - folderUpdate = true; - needUpdate = true; - initiateScan(); -} - -void FileInfoThread::setShowOnlyReadable(bool on) -{ - QMutexLocker locker(&mutex); - showOnlyReadable = on; - folderUpdate = true; - initiateScan(); -} - -void FileInfoThread::setCaseSensitive(bool on) -{ - QMutexLocker locker(&mutex); - caseSensitive = on; - folderUpdate = true; - initiateScan(); -} - -#if QT_CONFIG(filesystemwatcher) -void FileInfoThread::updateFile(const QString &path) -{ - Q_UNUSED(path); - QMutexLocker locker(&mutex); - folderUpdate = true; - initiateScan(); -} -#endif - -void FileInfoThread::run() -{ - forever { - bool updateFiles = false; - QMutexLocker locker(&mutex); - if (abort) { - return; - } - if (currentPath.isEmpty() || !needUpdate) { - emit statusChanged(currentPath.isEmpty() ? QQuickFolderListModel::Null : QQuickFolderListModel::Ready); - condition.wait(&mutex); - } - - if (abort) { - return; - } - - if (!currentPath.isEmpty()) { - updateFiles = true; - emit statusChanged(QQuickFolderListModel::Loading); - } - if (updateFiles) - getFileInfos(currentPath); - locker.unlock(); - } -} - -void FileInfoThread::runOnce() -{ - if (scanPending) - return; - scanPending = true; - QPointer guardedThis(this); - - auto getFileInfosAsync = [guardedThis](){ - if (!guardedThis) - return; - guardedThis->scanPending = false; - if (guardedThis->currentPath.isEmpty()) { - emit guardedThis->statusChanged(QQuickFolderListModel::Null); - return; - } - emit guardedThis->statusChanged(QQuickFolderListModel::Loading); - guardedThis->getFileInfos(guardedThis->currentPath); - emit guardedThis->statusChanged(QQuickFolderListModel::Ready); - }; - - QTimer::singleShot(0, getFileInfosAsync); -} - -void FileInfoThread::initiateScan() -{ -#if QT_CONFIG(thread) - condition.wakeAll(); -#else - runOnce(); -#endif -} - -void FileInfoThread::getFileInfos(const QString &path) -{ - QDir::Filters filter; - if (caseSensitive) - filter = QDir::CaseSensitive; - if (showFiles) - filter = filter | QDir::Files; - if (showDirs) - filter = filter | QDir::AllDirs | QDir::Drives; - if (!showDotAndDotDot) - filter = filter | QDir::NoDot | QDir::NoDotDot; - else if (path == rootPath) - filter = filter | QDir::NoDotDot; - if (showHidden) - filter = filter | QDir::Hidden; - if (showOnlyReadable) - filter = filter | QDir::Readable; - if (showDirsFirst) - sortFlags = sortFlags | QDir::DirsFirst; - - QDir currentDir(path, QString(), sortFlags); - QList filePropertyList; - - const QFileInfoList fileInfoList = currentDir.entryInfoList(nameFilters, filter, sortFlags); - - if (!fileInfoList.isEmpty()) { - filePropertyList.reserve(fileInfoList.count()); - for (const 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 &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 deleted file mode 100644 index 923cb29e03..0000000000 --- a/src/imports/folderlistmodel/fileinfothread_p.h +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef FILEINFOTHREAD_P_H -#define FILEINFOTHREAD_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#if QT_CONFIG(filesystemwatcher) -#include -#endif -#include -#include - -#include "fileproperty_p.h" -#include "qquickfolderlistmodel.h" - -class FileInfoThread : public QThread -{ - Q_OBJECT - -Q_SIGNALS: - void directoryChanged(const QString &directory, const QList &list) const; - void directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex) const; - void sortFinished(const QList &list) const; - void statusChanged(QQuickFolderListModel::Status status) 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 setShowFiles(bool show); - void setShowDirs(bool showFolders); - void setShowDirsFirst(bool show); - void setShowDotAndDotDot(bool on); - void setShowHidden(bool on); - void setShowOnlyReadable(bool on); - void setCaseSensitive(bool on); - -public Q_SLOTS: -#if QT_CONFIG(filesystemwatcher) - void dirChanged(const QString &directoryPath); - void updateFile(const QString &path); -#endif - -protected: - void run() override; - void runOnce(); - void initiateScan(); - void getFileInfos(const QString &path); - void findChangeRange(const QList &list, int &fromIndex, int &toIndex); - -private: - QMutex mutex; - QWaitCondition condition; - volatile bool abort; - bool scanPending; - -#if QT_CONFIG(filesystemwatcher) - QFileSystemWatcher *watcher; -#endif - QList currentFileList; - QDir::SortFlags sortFlags; - QString currentPath; - QString rootPath; - QStringList nameFilters; - bool needUpdate; - bool folderUpdate; - bool sortUpdate; - bool showFiles; - bool showDirs; - bool showDirsFirst; - bool showDotAndDotDot; - bool showHidden; - bool showOnlyReadable; - bool caseSensitive; -}; - -#endif // FILEINFOTHREAD_P_H diff --git a/src/imports/folderlistmodel/fileproperty_p.h b/src/imports/folderlistmodel/fileproperty_p.h deleted file mode 100644 index 48be4a3d85..0000000000 --- a/src/imports/folderlistmodel/fileproperty_p.h +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef FILEPROPERTY_P_H -#define FILEPROPERTY_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -class FileProperty -{ -public: - FileProperty(const QFileInfo &info) : - mFileName(info.fileName()), - mFilePath(info.filePath()), - mBaseName(info.baseName()), - mSuffix(info.completeSuffix()), - mSize(info.size()), - 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/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp index 9f8f14093e..eda8ea19d7 100644 --- a/src/imports/folderlistmodel/plugin.cpp +++ b/src/imports/folderlistmodel/plugin.cpp @@ -41,9 +41,8 @@ #include #include -#include "qquickfolderlistmodel.h" - -extern void qml_register_types_Qt_labs_folderlistmodel(); +#include +#include QT_BEGIN_NAMESPACE diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp deleted file mode 100644 index ef21471c0c..0000000000 --- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp +++ /dev/null @@ -1,927 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//![code] -#include "qquickfolderlistmodel.h" -#include "fileinfothread_p.h" -#include "fileproperty_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -class QQuickFolderListModelPrivate -{ - Q_DECLARE_PUBLIC(QQuickFolderListModel) - -public: - QQuickFolderListModelPrivate(QQuickFolderListModel *q) : q_ptr(q) { } - - QQuickFolderListModel *q_ptr; - QUrl currentDir; - QUrl rootDir; - FileInfoThread fileInfoThread; - QList data; - QHash roleNames; - QQuickFolderListModel::SortField sortField = QQuickFolderListModel::Name; - QStringList nameFilters = { QLatin1String("*") }; - QQuickFolderListModel::Status status = QQuickFolderListModel::Null; - bool sortReversed = false; - bool showFiles = true; - bool showDirs = true; - bool showDirsFirst = false; - bool showDotAndDotDot = false; - bool showOnlyReadable = false; - bool showHidden = false; - bool caseSensitive = true; - bool sortCaseSensitive = true; - - ~QQuickFolderListModelPrivate() {} - void init(); - void updateSorting(); - - // private slots - void _q_directoryChanged(const QString &directory, const QList &list); - void _q_directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex); - void _q_sortFinished(const QList &list); - void _q_statusChanged(QQuickFolderListModel::Status s); - - static QString resolvePath(const QUrl &path); -}; - - -void QQuickFolderListModelPrivate::init() -{ - Q_Q(QQuickFolderListModel); - qRegisterMetaType >("QList"); - qRegisterMetaType("QQuickFolderListModel::Status"); - q->connect(&fileInfoThread, SIGNAL(directoryChanged(QString,QList)), - q, SLOT(_q_directoryChanged(QString,QList))); - q->connect(&fileInfoThread, SIGNAL(directoryUpdated(QString,QList,int,int)), - q, SLOT(_q_directoryUpdated(QString,QList,int,int))); - q->connect(&fileInfoThread, SIGNAL(sortFinished(QList)), - q, SLOT(_q_sortFinished(QList))); - q->connect(&fileInfoThread, SIGNAL(statusChanged(QQuickFolderListModel::Status)), - q, SLOT(_q_statusChanged(QQuickFolderListModel::Status))); - q->connect(q, SIGNAL(rowCountChanged()), q, SIGNAL(countChanged())); -} - - -void QQuickFolderListModelPrivate::updateSorting() -{ - Q_Q(QQuickFolderListModel); - - QDir::SortFlags flags; - - switch (sortField) { - case QQuickFolderListModel::Unsorted: - flags |= QDir::Unsorted; - break; - case QQuickFolderListModel::Name: - flags |= QDir::Name; - break; - case QQuickFolderListModel::Time: - flags |= QDir::Time; - break; - case QQuickFolderListModel::Size: - flags |= QDir::Size; - break; - case QQuickFolderListModel::Type: - flags |= QDir::Type; - break; - } - - emit q->layoutAboutToBeChanged(); - - if (sortReversed) - flags |= QDir::Reversed; - if (!sortCaseSensitive) - flags |= QDir::IgnoreCase; - - fileInfoThread.setSortFlags(flags); -} - -void QQuickFolderListModelPrivate::_q_directoryChanged(const QString &directory, const QList &list) -{ - Q_Q(QQuickFolderListModel); - Q_UNUSED(directory); - - data = list; - q->endResetModel(); - emit q->rowCountChanged(); - emit q->folderChanged(); -} - - -void QQuickFolderListModelPrivate::_q_directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex) -{ - Q_Q(QQuickFolderListModel); - Q_UNUSED(directory); - - QModelIndex parent; - if (data.size() == list.size()) { - QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0); - QModelIndex modelIndexTo = q->createIndex(toIndex, 0); - data = list; - emit q->dataChanged(modelIndexFrom, modelIndexTo); - } else { - // File(s) inserted or removed. Since I do not know how many - // or where, I need to update the whole list from the first item. - // This is a little pessimistic, but optimizing it would require - // more information in the signal from FileInfoThread. - if (data.size() > 0) { - q->beginRemoveRows(parent, 0, data.size() - 1); - q->endRemoveRows(); - } - data = list; - if (list.size() > 0) { - if (toIndex > list.size() - 1) - toIndex = list.size() - 1; - q->beginInsertRows(parent, 0, data.size() - 1); - q->endInsertRows(); - } - emit q->rowCountChanged(); - } -} - -void QQuickFolderListModelPrivate::_q_sortFinished(const QList &list) -{ - Q_Q(QQuickFolderListModel); - - QModelIndex parent; - if (data.size() > 0) { - q->beginRemoveRows(parent, 0, data.size()-1); - data.clear(); - q->endRemoveRows(); - } - - q->beginInsertRows(parent, 0, list.size()-1); - data = list; - q->endInsertRows(); -} - -void QQuickFolderListModelPrivate::_q_statusChanged(QQuickFolderListModel::Status s) -{ - Q_Q(QQuickFolderListModel); - - if (status != s) { - status = s; - emit q->statusChanged(); - } -} - -QString QQuickFolderListModelPrivate::resolvePath(const QUrl &path) -{ - QString localPath = QQmlFile::urlToLocalFileOrQrc(path); - QUrl localUrl = QUrl(localPath); - QString fullPath = localUrl.path(); - if (localUrl.scheme().length()) - fullPath = localUrl.scheme() + QLatin1Char(':') + fullPath; - return QDir::cleanPath(fullPath); -} - -/*! - \qmlmodule Qt.labs.folderlistmodel 2.\QtMinorVersion - \title Qt Labs FolderListModel QML Types - \ingroup qmlmodules - \brief The FolderListModel provides a model of the contents of a file system folder. - - To use this module, import the module with the following line: - - \qml - import Qt.labs.folderlistmodel - \endqml -*/ - -/*! - \qmltype FolderListModel - \inqmlmodule Qt.labs.folderlistmodel - \instantiates QQuickFolderListModel - \ingroup qtquick-models - \brief The FolderListModel provides a model of the contents of a file system folder. - - FolderListModel provides access to information about the contents of a folder - in the local file system, exposing a list of files to views and other data components. - - \note This type is made available by importing the \c Qt.labs.folderlistmodel module. - \e{Elements in the Qt.labs module are not guaranteed to remain compatible - in future versions.} - - \qml - import Qt.labs.folderlistmodel - \endqml - - The \l folder property specifies the folder to access. Information about the - files and directories in the folder is supplied via the model's interface. - Components access names and paths via the following roles: - - \list - \li \c fileName - \li \c filePath - \li \c fileURL (since Qt 5.2; deprecated since Qt 5.15) - \li \c fileUrl (since Qt 5.15) - \li \c fileBaseName - \li \c fileSuffix - \li \c fileSize - \li \c fileModified - \li \c fileAccessed - \li \c fileIsDir - \endlist - - Additionally a file entry can be differentiated from a folder entry via the - isFolder() method. - - \section1 Filtering - - Various properties can be set to filter the number of files and directories - exposed by the model. - - The \l nameFilters property can be set to contain a list of wildcard filters - that are applied to names of files and directories, causing only those that - match the filters to be exposed. - - Directories can be included or excluded using the \l showDirs property, - navigation directories can also be excluded by setting the \l showDotAndDotDot - property to false, hidden files can be included or excluded using the - \l showHidden property. - - It is sometimes useful to limit the files and directories exposed to those - that the user can access. The \l showOnlyReadable property can be set to - enable this feature. - - \section1 Example Usage - - The following example shows a FolderListModel being used to provide a list - of QML files in a \l ListView: - - \qml - import QtQuick - import Qt.labs.folderlistmodel - - ListView { - width: 200; height: 400 - - FolderListModel { - id: folderModel - nameFilters: ["*.qml"] - } - - Component { - id: fileDelegate - Text { text: fileName } - } - - model: folderModel - delegate: fileDelegate - } - \endqml - - \section1 Path Separators - - Qt uses "/" as a universal directory separator in the same way that "/" is - used as a path separator in URLs. If you always use "/" as a directory - separator, Qt will translate your paths to conform to the underlying - operating system. - - \sa {QML Data Models} -*/ - -QQuickFolderListModel::QQuickFolderListModel(QObject *parent) - : QAbstractListModel(parent), d_ptr(new QQuickFolderListModelPrivate(this)) -{ - 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"; - d->roleNames[FileUrlRole] = "fileUrl"; - d->roleNames[FileURLRole] = "fileURL"; - d->init(); -} - -QQuickFolderListModel::~QQuickFolderListModel() -{ -} - -QVariant QQuickFolderListModel::data(const QModelIndex &index, int role) const -{ - Q_D(const QQuickFolderListModel); - QVariant rv; - - 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(); - break; - case FileLastReadRole: - rv = d->data.at(index.row()).lastRead(); - break; - case FileIsDirRole: - rv = d->data.at(index.row()).isDir(); - break; - case FileUrlRole: - case FileURLRole: - rv = QUrl::fromLocalFile(d->data.at(index.row()).filePath()); - break; - default: - break; - } - return rv; -} - -QHash QQuickFolderListModel::roleNames() const -{ - Q_D(const QQuickFolderListModel); - return d->roleNames; -} - -/*! - \qmlproperty int FolderListModel::count - - Returns the number of items in the current folder that match the - filter criteria. -*/ -int QQuickFolderListModel::rowCount(const QModelIndex &parent) const -{ - Q_D(const QQuickFolderListModel); - Q_UNUSED(parent); - return d->data.size(); -} - -QModelIndex QQuickFolderListModel::index(int row, int , const QModelIndex &) const -{ - return createIndex(row, 0); -} - -/*! - \qmlproperty url FolderListModel::folder - - The \a folder property holds a URL for the folder that the model - currently provides. - - The value must be a \c file: or \c qrc: URL, or a relative URL. - - The default value is an invalid URL. -*/ -QUrl QQuickFolderListModel::folder() const -{ - Q_D(const QQuickFolderListModel); - return d->currentDir; -} - -void QQuickFolderListModel::setFolder(const QUrl &folder) -{ - Q_D(QQuickFolderListModel); - - if (folder == d->currentDir) - return; - - QString resolvedPath = QQuickFolderListModelPrivate::resolvePath(folder); - - 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(); - if (d->status != QQuickFolderListModel::Null) { - d->status = QQuickFolderListModel::Null; - emit statusChanged(); - } - return; - } - - d->fileInfoThread.setPath(resolvedPath); -} - - -/*! - \qmlproperty url FolderListModel::rootFolder - - When this property is set, the given folder will - be treated as the root in the file system, so that - you can only traverse subfolders within it. -*/ -QUrl QQuickFolderListModel::rootFolder() const -{ - Q_D(const QQuickFolderListModel); - return d->rootDir; -} - -void QQuickFolderListModel::setRootFolder(const QUrl &path) -{ - Q_D(QQuickFolderListModel); - - if (path.isEmpty()) - return; - - QString resolvedPath = QQuickFolderListModelPrivate::resolvePath(path); - - QFileInfo info(resolvedPath); - if (!info.exists() || !info.isDir()) - return; - - d->fileInfoThread.setRootPath(resolvedPath); - d->rootDir = path; -} - - -/*! - \qmlproperty url FolderListModel::parentFolder - - Returns the URL of the parent of the current \l folder. -*/ -QUrl QQuickFolderListModel::parentFolder() const -{ - Q_D(const QQuickFolderListModel); - - QString localFile = d->currentDir.toLocalFile(); - if (!localFile.isEmpty()) { - QDir dir(localFile); - if (dir.isRoot() || !dir.cdUp()) - return QUrl(); - localFile = dir.path(); - } else { - const QString path = d->currentDir.path(); - const int pos = path.lastIndexOf(QLatin1Char('/')); - if (pos <= 0) - return QUrl(); - localFile = path.left(pos); - } - return QUrl::fromLocalFile(localFile); -} - -/*! - \qmlproperty list FolderListModel::nameFilters - - The \a nameFilters property contains a list of file name filters. - The filters may include the ? and * wildcards. - - The example below filters on PNG and JPEG files: - - \qml - FolderListModel { - nameFilters: [ "*.png", "*.jpg" ] - } - \endqml - - \note Directories are not excluded by filters. -*/ -QStringList QQuickFolderListModel::nameFilters() const -{ - Q_D(const QQuickFolderListModel); - return d->nameFilters; -} - -void QQuickFolderListModel::setNameFilters(const QStringList &filters) -{ - Q_D(QQuickFolderListModel); - if (d->nameFilters == filters) - return; - d->fileInfoThread.setNameFilters(filters); - d->nameFilters = filters; -} - -void QQuickFolderListModel::classBegin() -{ -} - -void QQuickFolderListModel::componentComplete() -{ - Q_D(QQuickFolderListModel); - QString localPath = QQmlFile::urlToLocalFileOrQrc(d->currentDir); - if (localPath.isEmpty() || !QDir(localPath).exists()) - setFolder(QUrl::fromLocalFile(QDir::currentPath())); - d->fileInfoThread.start(QThread::LowPriority); -} - -/*! - \qmlproperty enumeration FolderListModel::sortField - - The \a sortField property contains field to use for sorting. sortField - may be one of: - \list - \li Unsorted - no sorting is applied. - \li Name - sort by filename - \li Time - sort by time modified - \li Size - sort by file size - \li Type - sort by file type (extension) - \endlist - - \sa sortReversed -*/ -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 - - If set to true, reverses the sort order. The default is false. - - \sa sortField -*/ -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(); - } -} - -/*! - \qmlmethod bool FolderListModel::isFolder(int index) - - Returns true if the entry \a index is a folder; otherwise - returns false. -*/ -bool QQuickFolderListModel::isFolder(int index) const -{ - if (index != -1) { - QModelIndex idx = createIndex(index, 0); - if (idx.isValid()) { - QVariant var = data(idx, FileIsDirRole); - if (var.isValid()) - return var.toBool(); - } - } - return false; -} - -/*! - \qmlproperty bool FolderListModel::showFiles - \since 5.2 - - If true, files are included in the model; otherwise only directories - are included. - - By default, this property is true. - - \sa showDirs -*/ -bool QQuickFolderListModel::showFiles() const -{ - Q_D(const QQuickFolderListModel); - return d->showFiles; -} - -void QQuickFolderListModel::setShowFiles(bool on) -{ - Q_D(QQuickFolderListModel); - - d->fileInfoThread.setShowFiles(on); - d->showFiles = on; -} - -/*! - \qmlproperty bool FolderListModel::showDirs - - If true, directories are included in the model; otherwise only files - are included. - - By default, this property is true. - - Note that the nameFilters are not applied to directories. - - \sa showDotAndDotDot -*/ -bool QQuickFolderListModel::showDirs() const -{ - Q_D(const QQuickFolderListModel); - return d->showDirs; -} - -void QQuickFolderListModel::setShowDirs(bool on) -{ - Q_D(QQuickFolderListModel); - - d->fileInfoThread.setShowDirs(on); - d->showDirs = on; -} - -/*! - \qmlproperty bool FolderListModel::showDirsFirst - - If true, if directories are included in the model they will - always be shown first, then the files. - - By default, this property is false. - -*/ -bool QQuickFolderListModel::showDirsFirst() const -{ - Q_D(const QQuickFolderListModel); - return d->showDirsFirst; -} - -void QQuickFolderListModel::setShowDirsFirst(bool on) -{ - Q_D(QQuickFolderListModel); - - d->fileInfoThread.setShowDirsFirst(on); - d->showDirsFirst = on; -} - - -/*! - \qmlproperty bool FolderListModel::showDotAndDotDot - - If true, the "." and ".." directories are included in the model; otherwise - they are excluded. - - By default, this property is false. - - \sa showDirs -*/ -bool QQuickFolderListModel::showDotAndDotDot() const -{ - Q_D(const QQuickFolderListModel); - return d->showDotAndDotDot; -} - -void QQuickFolderListModel::setShowDotAndDotDot(bool on) -{ - Q_D(QQuickFolderListModel); - - if (on != d->showDotAndDotDot) { - d->fileInfoThread.setShowDotAndDotDot(on); - d->showDotAndDotDot = on; - } -} - - -/*! - \qmlproperty bool FolderListModel::showHidden - \since 5.2 - - If true, hidden files and directories are included in the model; otherwise - they are excluded. - - By default, this property is false. -*/ -bool QQuickFolderListModel::showHidden() const -{ - Q_D(const QQuickFolderListModel); - return d->showHidden; -} - -void QQuickFolderListModel::setShowHidden(bool on) -{ - Q_D(QQuickFolderListModel); - - if (on != d->showHidden) { - d->fileInfoThread.setShowHidden(on); - d->showHidden = on; - } -} - -/*! - \qmlproperty bool FolderListModel::showOnlyReadable - - If true, only readable files and directories are shown; otherwise all files - and directories are shown. - - By default, this property is false. - - \sa showDirs -*/ -bool QQuickFolderListModel::showOnlyReadable() const -{ - Q_D(const QQuickFolderListModel); - return d->showOnlyReadable; -} - -void QQuickFolderListModel::setShowOnlyReadable(bool on) -{ - Q_D(QQuickFolderListModel); - - if (on != d->showOnlyReadable) { - d->fileInfoThread.setShowOnlyReadable(on); - d->showOnlyReadable = on; - } -} - -/*! - * \qmlproperty bool FolderListModel::caseSensitive - * \since 5.7 - * - * Use case sensitive pattern matching. - * - * By default, this property is true. - * - */ -bool QQuickFolderListModel::caseSensitive() const -{ - Q_D(const QQuickFolderListModel); - return d->caseSensitive; -} - -void QQuickFolderListModel::setCaseSensitive(bool on) -{ - Q_D(QQuickFolderListModel); - - if (on != d->caseSensitive) { - d->fileInfoThread.setCaseSensitive(on); - d->caseSensitive = on; - } -} - -/*! - \qmlproperty enumeration FolderListModel::status - \since 5.11 - - This property holds the status of folder reading. It can be one of: - \list - \li FolderListModel.Null - no \a folder has been set - \li FolderListModel.Ready - the folder has been loaded - \li FolderListModel.Loading - the folder is currently being loaded - \endlist - - Use this status to provide an update or respond to the status change in some way. - For example, you could: - - \list - \li Trigger a state change: - \qml - State { name: 'loaded'; when: folderModel.status == FolderListModel.Ready } - \endqml - - \li Implement an \c onStatusChanged signal handler: - \qml - FolderListModel { - id: folderModel - onStatusChanged: if (folderModel.status == FolderListModel.Ready) console.log('Loaded') - } - \endqml - - \li Bind to the status value: - \qml - Text { text: folderModel.status == FolderListModel.Ready ? 'Loaded' : 'Not loaded' } - \endqml - \endlist -*/ -QQuickFolderListModel::Status QQuickFolderListModel::status() const -{ - Q_D(const QQuickFolderListModel); - return d->status; -} - -/*! - \qmlproperty bool FolderListModel::sortCaseSensitive - \since 5.12 - - If set to \c true, the sort is case sensitive. This property is \c true by default. -*/ - -bool QQuickFolderListModel::sortCaseSensitive() const -{ - Q_D(const QQuickFolderListModel); - return d->sortCaseSensitive; -} - -void QQuickFolderListModel::setSortCaseSensitive(bool on) -{ - Q_D(QQuickFolderListModel); - - if (on != d->sortCaseSensitive) { - d->sortCaseSensitive = on; - d->updateSorting(); - } -} - -/*! - \qmlmethod var FolderListModel::get(int index, string property) - - Returns the folder \a property for the given \a index. The following properties - are available: - - \list - \li \c fileName - \li \c filePath - \li \c fileURL (since Qt 5.2; deprecated since Qt 5.15) - \li \c fileUrl (since Qt 5.15) - \li \c fileBaseName - \li \c fileSuffix - \li \c fileSize - \li \c fileModified - \li \c fileAccessed - \li \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(); -} - -/*! - \qmlmethod int FolderListModel::indexOf(url file) - \since 5.6 - - Returns the index of the given \a file URL if the model contains it, - or -1 if not. -*/ -int QQuickFolderListModel::indexOf(const QUrl &file) const -{ - Q_D(const QQuickFolderListModel); - FileProperty toFind(QFileInfo(file.toLocalFile())); - return d->data.indexOf(toFind); -} - -#include "moc_qquickfolderlistmodel.cpp" - -//![code] -QT_END_NAMESPACE diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h deleted file mode 100644 index e21a8d8f37..0000000000 --- a/src/imports/folderlistmodel/qquickfolderlistmodel.h +++ /dev/null @@ -1,189 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQUICKFOLDERLISTMODEL_H -#define QQUICKFOLDERLISTMODEL_H - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - - -class QQmlContext; -class QModelIndex; - -class QQuickFolderListModelPrivate; - -//![class begin] -class QQuickFolderListModel : public QAbstractListModel, public QQmlParserStatus -{ - Q_OBJECT - Q_INTERFACES(QQmlParserStatus) -//![class begin] - -//![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 showFiles READ showFiles WRITE setShowFiles REVISION(2, 1)) - 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 showHidden READ showHidden WRITE setShowHidden REVISION(2, 1)) - Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable) - Q_PROPERTY(bool caseSensitive READ caseSensitive WRITE setCaseSensitive REVISION(2, 2)) - Q_PROPERTY(int count READ count NOTIFY countChanged) - Q_PROPERTY(Status status READ status NOTIFY statusChanged REVISION(2, 11)) - Q_PROPERTY(bool sortCaseSensitive READ sortCaseSensitive WRITE setSortCaseSensitive REVISION(2, 12)) -//![class props] - - QML_NAMED_ELEMENT(FolderListModel) - QML_ADDED_IN_VERSION(2, 0) -//![abslistmodel] -public: - QQuickFolderListModel(QObject *parent = nullptr); - ~QQuickFolderListModel(); - - 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, - FileUrlRole = Qt::UserRole + 9, - FileURLRole = Qt::UserRole + 10 - }; - - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - QHash roleNames() const override; -//![abslistmodel] - -//![count] - int count() const { return rowCount(QModelIndex()); } -//![count] - -//![prop funcs] - QUrl folder() const; - void setFolder(const QUrl &folder); - QUrl rootFolder() const; - void setRootFolder(const QUrl &path); - - QUrl parentFolder() const; - - QStringList nameFilters() const; - void setNameFilters(const QStringList &filters); - - enum SortField { Unsorted, Name, Time, Size, Type }; - Q_ENUM(SortField) - SortField sortField() const; - void setSortField(SortField field); - - bool sortReversed() const; - void setSortReversed(bool rev); - - bool showFiles() const; - void setShowFiles(bool showFiles); - bool showDirs() const; - void setShowDirs(bool showDirs); - bool showDirsFirst() const; - void setShowDirsFirst(bool showDirsFirst); - bool showDotAndDotDot() const; - void setShowDotAndDotDot(bool on); - bool showHidden() const; - void setShowHidden(bool on); - bool showOnlyReadable() const; - void setShowOnlyReadable(bool on); - bool caseSensitive() const; - void setCaseSensitive(bool on); - - enum Status { Null, Ready, Loading }; - Q_ENUM(Status) - Status status() const; - bool sortCaseSensitive() const; - void setSortCaseSensitive(bool on); -//![prop funcs] - - Q_INVOKABLE bool isFolder(int index) const; - Q_INVOKABLE QVariant get(int idx, const QString &property) const; - Q_INVOKABLE int indexOf(const QUrl &file) const; - -//![parserstatus] - void classBegin() override; - void componentComplete() override; -//![parserstatus] - - int roleFromString(const QString &roleName) const; - -//![notifier] -Q_SIGNALS: - void folderChanged(); - void rowCountChanged() const; - Q_REVISION(2, 1) void countChanged() const; - Q_REVISION(2, 11) void statusChanged(); -//![notifier] - -//![class end] - - -private: - Q_DISABLE_COPY(QQuickFolderListModel) - Q_DECLARE_PRIVATE(QQuickFolderListModel) - QScopedPointer d_ptr; - - Q_PRIVATE_SLOT(d_func(), void _q_directoryChanged(const QString &directory, const QList &list)) - Q_PRIVATE_SLOT(d_func(), void _q_directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex)) - Q_PRIVATE_SLOT(d_func(), void _q_sortFinished(const QList &list)) - Q_PRIVATE_SLOT(d_func(), void _q_statusChanged(QQuickFolderListModel::Status s)) -}; -//![class end] - -QT_END_NAMESPACE - -#endif // QQUICKFOLDERLISTMODEL_H diff --git a/src/labs/CMakeLists.txt b/src/labs/CMakeLists.txt index b1f8c7c142..5dc715db60 100644 --- a/src/labs/CMakeLists.txt +++ b/src/labs/CMakeLists.txt @@ -1 +1,4 @@ add_subdirectory(settings) +if(QT_FEATURE_qml_itemmodel) + add_subdirectory(folderlistmodel) +endif() diff --git a/src/labs/folderlistmodel/CMakeLists.txt b/src/labs/folderlistmodel/CMakeLists.txt new file mode 100644 index 0000000000..bcee01629b --- /dev/null +++ b/src/labs/folderlistmodel/CMakeLists.txt @@ -0,0 +1,24 @@ +qt_internal_add_module(LabsFolderListModel + GENERATE_METATYPES + SOURCES + fileinfothread.cpp fileinfothread_p.h + fileproperty_p.h + qquickfolderlistmodel.cpp qquickfolderlistmodel.h + qquickfolderlistmodelglobal_p.h + DEFINES + QT_BUILD_LABSFOLDERMODEL_LIB + PUBLIC_LIBRARIES + Qt::CorePrivate + Qt::QmlPrivate +) + +set_target_properties(LabsFolderListModel PROPERTIES + QT_QML_MODULE_INSTALL_QMLTYPES TRUE + QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION} + QT_QML_MODULE_URI Qt.labs.folderlistmodel + QT_QMLTYPES_FILENAME plugins.qmltypes + QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/Qt/labs/folderlistmodel" +) + + +qt6_qml_type_registration(LabsFolderListModel) diff --git a/src/labs/folderlistmodel/fileinfothread.cpp b/src/labs/folderlistmodel/fileinfothread.cpp new file mode 100644 index 0000000000..a93edd3b1b --- /dev/null +++ b/src/labs/folderlistmodel/fileinfothread.cpp @@ -0,0 +1,369 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "fileinfothread_p.h" +#include +#include +#include + +#include + + +FileInfoThread::FileInfoThread(QObject *parent) + : QThread(parent), + abort(false), + scanPending(false), +#if QT_CONFIG(filesystemwatcher) + watcher(nullptr), +#endif + sortFlags(QDir::Name), + needUpdate(true), + folderUpdate(false), + sortUpdate(false), + showFiles(true), + showDirs(true), + showDirsFirst(false), + showDotAndDotDot(false), + showHidden(false), + showOnlyReadable(false), + caseSensitive(true) +{ +#if QT_CONFIG(filesystemwatcher) + watcher = new QFileSystemWatcher(this); + connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString))); + connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFile(QString))); +#endif // filesystemwatcher +} + +FileInfoThread::~FileInfoThread() +{ + QMutexLocker locker(&mutex); + abort = true; + condition.wakeOne(); + locker.unlock(); + wait(); +} + +void FileInfoThread::clear() +{ + QMutexLocker locker(&mutex); +#if QT_CONFIG(filesystemwatcher) + watcher->removePaths(watcher->files()); + watcher->removePaths(watcher->directories()); +#endif +} + +void FileInfoThread::removePath(const QString &path) +{ + QMutexLocker locker(&mutex); +#if QT_CONFIG(filesystemwatcher) + if (!path.startsWith(QLatin1Char(':'))) + watcher->removePath(path); +#else + Q_UNUSED(path); +#endif + currentPath.clear(); +} + +void FileInfoThread::setPath(const QString &path) +{ + Q_ASSERT(!path.isEmpty()); + + QMutexLocker locker(&mutex); +#if QT_CONFIG(filesystemwatcher) + if (!path.startsWith(QLatin1Char(':'))) + watcher->addPath(path); +#endif + currentPath = path; + needUpdate = true; + initiateScan(); +} + +void FileInfoThread::setRootPath(const QString &path) +{ + Q_ASSERT(!path.isEmpty()); + + QMutexLocker locker(&mutex); + rootPath = path; +} + +#if QT_CONFIG(filesystemwatcher) +void FileInfoThread::dirChanged(const QString &directoryPath) +{ + Q_UNUSED(directoryPath); + QMutexLocker locker(&mutex); + folderUpdate = true; + initiateScan(); +} +#endif + +void FileInfoThread::setSortFlags(QDir::SortFlags flags) +{ + QMutexLocker locker(&mutex); + sortFlags = flags; + sortUpdate = true; + needUpdate = true; + initiateScan(); +} + +void FileInfoThread::setNameFilters(const QStringList & filters) +{ + QMutexLocker locker(&mutex); + nameFilters = filters; + folderUpdate = true; + initiateScan(); +} + +void FileInfoThread::setShowFiles(bool show) +{ + QMutexLocker locker(&mutex); + showFiles = show; + folderUpdate = true; + initiateScan(); +} + +void FileInfoThread::setShowDirs(bool showFolders) +{ + QMutexLocker locker(&mutex); + showDirs = showFolders; + folderUpdate = true; + initiateScan(); +} + +void FileInfoThread::setShowDirsFirst(bool show) +{ + QMutexLocker locker(&mutex); + showDirsFirst = show; + folderUpdate = true; + initiateScan(); +} + +void FileInfoThread::setShowDotAndDotDot(bool on) +{ + QMutexLocker locker(&mutex); + showDotAndDotDot = on; + folderUpdate = true; + needUpdate = true; + initiateScan(); +} + +void FileInfoThread::setShowHidden(bool on) +{ + QMutexLocker locker(&mutex); + showHidden = on; + folderUpdate = true; + needUpdate = true; + initiateScan(); +} + +void FileInfoThread::setShowOnlyReadable(bool on) +{ + QMutexLocker locker(&mutex); + showOnlyReadable = on; + folderUpdate = true; + initiateScan(); +} + +void FileInfoThread::setCaseSensitive(bool on) +{ + QMutexLocker locker(&mutex); + caseSensitive = on; + folderUpdate = true; + initiateScan(); +} + +#if QT_CONFIG(filesystemwatcher) +void FileInfoThread::updateFile(const QString &path) +{ + Q_UNUSED(path); + QMutexLocker locker(&mutex); + folderUpdate = true; + initiateScan(); +} +#endif + +void FileInfoThread::run() +{ + forever { + bool updateFiles = false; + QMutexLocker locker(&mutex); + if (abort) { + return; + } + if (currentPath.isEmpty() || !needUpdate) { + emit statusChanged(currentPath.isEmpty() ? QQuickFolderListModel::Null : QQuickFolderListModel::Ready); + condition.wait(&mutex); + } + + if (abort) { + return; + } + + if (!currentPath.isEmpty()) { + updateFiles = true; + emit statusChanged(QQuickFolderListModel::Loading); + } + if (updateFiles) + getFileInfos(currentPath); + locker.unlock(); + } +} + +void FileInfoThread::runOnce() +{ + if (scanPending) + return; + scanPending = true; + QPointer guardedThis(this); + + auto getFileInfosAsync = [guardedThis](){ + if (!guardedThis) + return; + guardedThis->scanPending = false; + if (guardedThis->currentPath.isEmpty()) { + emit guardedThis->statusChanged(QQuickFolderListModel::Null); + return; + } + emit guardedThis->statusChanged(QQuickFolderListModel::Loading); + guardedThis->getFileInfos(guardedThis->currentPath); + emit guardedThis->statusChanged(QQuickFolderListModel::Ready); + }; + + QTimer::singleShot(0, getFileInfosAsync); +} + +void FileInfoThread::initiateScan() +{ +#if QT_CONFIG(thread) + condition.wakeAll(); +#else + runOnce(); +#endif +} + +void FileInfoThread::getFileInfos(const QString &path) +{ + QDir::Filters filter; + if (caseSensitive) + filter = QDir::CaseSensitive; + if (showFiles) + filter = filter | QDir::Files; + if (showDirs) + filter = filter | QDir::AllDirs | QDir::Drives; + if (!showDotAndDotDot) + filter = filter | QDir::NoDot | QDir::NoDotDot; + else if (path == rootPath) + filter = filter | QDir::NoDotDot; + if (showHidden) + filter = filter | QDir::Hidden; + if (showOnlyReadable) + filter = filter | QDir::Readable; + if (showDirsFirst) + sortFlags = sortFlags | QDir::DirsFirst; + + QDir currentDir(path, QString(), sortFlags); + QList filePropertyList; + + const QFileInfoList fileInfoList = currentDir.entryInfoList(nameFilters, filter, sortFlags); + + if (!fileInfoList.isEmpty()) { + filePropertyList.reserve(fileInfoList.count()); + for (const 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 &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/labs/folderlistmodel/fileinfothread_p.h b/src/labs/folderlistmodel/fileinfothread_p.h new file mode 100644 index 0000000000..923cb29e03 --- /dev/null +++ b/src/labs/folderlistmodel/fileinfothread_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FILEINFOTHREAD_P_H +#define FILEINFOTHREAD_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#if QT_CONFIG(filesystemwatcher) +#include +#endif +#include +#include + +#include "fileproperty_p.h" +#include "qquickfolderlistmodel.h" + +class FileInfoThread : public QThread +{ + Q_OBJECT + +Q_SIGNALS: + void directoryChanged(const QString &directory, const QList &list) const; + void directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex) const; + void sortFinished(const QList &list) const; + void statusChanged(QQuickFolderListModel::Status status) 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 setShowFiles(bool show); + void setShowDirs(bool showFolders); + void setShowDirsFirst(bool show); + void setShowDotAndDotDot(bool on); + void setShowHidden(bool on); + void setShowOnlyReadable(bool on); + void setCaseSensitive(bool on); + +public Q_SLOTS: +#if QT_CONFIG(filesystemwatcher) + void dirChanged(const QString &directoryPath); + void updateFile(const QString &path); +#endif + +protected: + void run() override; + void runOnce(); + void initiateScan(); + void getFileInfos(const QString &path); + void findChangeRange(const QList &list, int &fromIndex, int &toIndex); + +private: + QMutex mutex; + QWaitCondition condition; + volatile bool abort; + bool scanPending; + +#if QT_CONFIG(filesystemwatcher) + QFileSystemWatcher *watcher; +#endif + QList currentFileList; + QDir::SortFlags sortFlags; + QString currentPath; + QString rootPath; + QStringList nameFilters; + bool needUpdate; + bool folderUpdate; + bool sortUpdate; + bool showFiles; + bool showDirs; + bool showDirsFirst; + bool showDotAndDotDot; + bool showHidden; + bool showOnlyReadable; + bool caseSensitive; +}; + +#endif // FILEINFOTHREAD_P_H diff --git a/src/labs/folderlistmodel/fileproperty_p.h b/src/labs/folderlistmodel/fileproperty_p.h new file mode 100644 index 0000000000..48be4a3d85 --- /dev/null +++ b/src/labs/folderlistmodel/fileproperty_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FILEPROPERTY_P_H +#define FILEPROPERTY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +class FileProperty +{ +public: + FileProperty(const QFileInfo &info) : + mFileName(info.fileName()), + mFilePath(info.filePath()), + mBaseName(info.baseName()), + mSuffix(info.completeSuffix()), + mSize(info.size()), + 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/labs/folderlistmodel/qquickfolderlistmodel.cpp b/src/labs/folderlistmodel/qquickfolderlistmodel.cpp new file mode 100644 index 0000000000..ef21471c0c --- /dev/null +++ b/src/labs/folderlistmodel/qquickfolderlistmodel.cpp @@ -0,0 +1,927 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//![code] +#include "qquickfolderlistmodel.h" +#include "fileinfothread_p.h" +#include "fileproperty_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QQuickFolderListModelPrivate +{ + Q_DECLARE_PUBLIC(QQuickFolderListModel) + +public: + QQuickFolderListModelPrivate(QQuickFolderListModel *q) : q_ptr(q) { } + + QQuickFolderListModel *q_ptr; + QUrl currentDir; + QUrl rootDir; + FileInfoThread fileInfoThread; + QList data; + QHash roleNames; + QQuickFolderListModel::SortField sortField = QQuickFolderListModel::Name; + QStringList nameFilters = { QLatin1String("*") }; + QQuickFolderListModel::Status status = QQuickFolderListModel::Null; + bool sortReversed = false; + bool showFiles = true; + bool showDirs = true; + bool showDirsFirst = false; + bool showDotAndDotDot = false; + bool showOnlyReadable = false; + bool showHidden = false; + bool caseSensitive = true; + bool sortCaseSensitive = true; + + ~QQuickFolderListModelPrivate() {} + void init(); + void updateSorting(); + + // private slots + void _q_directoryChanged(const QString &directory, const QList &list); + void _q_directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex); + void _q_sortFinished(const QList &list); + void _q_statusChanged(QQuickFolderListModel::Status s); + + static QString resolvePath(const QUrl &path); +}; + + +void QQuickFolderListModelPrivate::init() +{ + Q_Q(QQuickFolderListModel); + qRegisterMetaType >("QList"); + qRegisterMetaType("QQuickFolderListModel::Status"); + q->connect(&fileInfoThread, SIGNAL(directoryChanged(QString,QList)), + q, SLOT(_q_directoryChanged(QString,QList))); + q->connect(&fileInfoThread, SIGNAL(directoryUpdated(QString,QList,int,int)), + q, SLOT(_q_directoryUpdated(QString,QList,int,int))); + q->connect(&fileInfoThread, SIGNAL(sortFinished(QList)), + q, SLOT(_q_sortFinished(QList))); + q->connect(&fileInfoThread, SIGNAL(statusChanged(QQuickFolderListModel::Status)), + q, SLOT(_q_statusChanged(QQuickFolderListModel::Status))); + q->connect(q, SIGNAL(rowCountChanged()), q, SIGNAL(countChanged())); +} + + +void QQuickFolderListModelPrivate::updateSorting() +{ + Q_Q(QQuickFolderListModel); + + QDir::SortFlags flags; + + switch (sortField) { + case QQuickFolderListModel::Unsorted: + flags |= QDir::Unsorted; + break; + case QQuickFolderListModel::Name: + flags |= QDir::Name; + break; + case QQuickFolderListModel::Time: + flags |= QDir::Time; + break; + case QQuickFolderListModel::Size: + flags |= QDir::Size; + break; + case QQuickFolderListModel::Type: + flags |= QDir::Type; + break; + } + + emit q->layoutAboutToBeChanged(); + + if (sortReversed) + flags |= QDir::Reversed; + if (!sortCaseSensitive) + flags |= QDir::IgnoreCase; + + fileInfoThread.setSortFlags(flags); +} + +void QQuickFolderListModelPrivate::_q_directoryChanged(const QString &directory, const QList &list) +{ + Q_Q(QQuickFolderListModel); + Q_UNUSED(directory); + + data = list; + q->endResetModel(); + emit q->rowCountChanged(); + emit q->folderChanged(); +} + + +void QQuickFolderListModelPrivate::_q_directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex) +{ + Q_Q(QQuickFolderListModel); + Q_UNUSED(directory); + + QModelIndex parent; + if (data.size() == list.size()) { + QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0); + QModelIndex modelIndexTo = q->createIndex(toIndex, 0); + data = list; + emit q->dataChanged(modelIndexFrom, modelIndexTo); + } else { + // File(s) inserted or removed. Since I do not know how many + // or where, I need to update the whole list from the first item. + // This is a little pessimistic, but optimizing it would require + // more information in the signal from FileInfoThread. + if (data.size() > 0) { + q->beginRemoveRows(parent, 0, data.size() - 1); + q->endRemoveRows(); + } + data = list; + if (list.size() > 0) { + if (toIndex > list.size() - 1) + toIndex = list.size() - 1; + q->beginInsertRows(parent, 0, data.size() - 1); + q->endInsertRows(); + } + emit q->rowCountChanged(); + } +} + +void QQuickFolderListModelPrivate::_q_sortFinished(const QList &list) +{ + Q_Q(QQuickFolderListModel); + + QModelIndex parent; + if (data.size() > 0) { + q->beginRemoveRows(parent, 0, data.size()-1); + data.clear(); + q->endRemoveRows(); + } + + q->beginInsertRows(parent, 0, list.size()-1); + data = list; + q->endInsertRows(); +} + +void QQuickFolderListModelPrivate::_q_statusChanged(QQuickFolderListModel::Status s) +{ + Q_Q(QQuickFolderListModel); + + if (status != s) { + status = s; + emit q->statusChanged(); + } +} + +QString QQuickFolderListModelPrivate::resolvePath(const QUrl &path) +{ + QString localPath = QQmlFile::urlToLocalFileOrQrc(path); + QUrl localUrl = QUrl(localPath); + QString fullPath = localUrl.path(); + if (localUrl.scheme().length()) + fullPath = localUrl.scheme() + QLatin1Char(':') + fullPath; + return QDir::cleanPath(fullPath); +} + +/*! + \qmlmodule Qt.labs.folderlistmodel 2.\QtMinorVersion + \title Qt Labs FolderListModel QML Types + \ingroup qmlmodules + \brief The FolderListModel provides a model of the contents of a file system folder. + + To use this module, import the module with the following line: + + \qml + import Qt.labs.folderlistmodel + \endqml +*/ + +/*! + \qmltype FolderListModel + \inqmlmodule Qt.labs.folderlistmodel + \instantiates QQuickFolderListModel + \ingroup qtquick-models + \brief The FolderListModel provides a model of the contents of a file system folder. + + FolderListModel provides access to information about the contents of a folder + in the local file system, exposing a list of files to views and other data components. + + \note This type is made available by importing the \c Qt.labs.folderlistmodel module. + \e{Elements in the Qt.labs module are not guaranteed to remain compatible + in future versions.} + + \qml + import Qt.labs.folderlistmodel + \endqml + + The \l folder property specifies the folder to access. Information about the + files and directories in the folder is supplied via the model's interface. + Components access names and paths via the following roles: + + \list + \li \c fileName + \li \c filePath + \li \c fileURL (since Qt 5.2; deprecated since Qt 5.15) + \li \c fileUrl (since Qt 5.15) + \li \c fileBaseName + \li \c fileSuffix + \li \c fileSize + \li \c fileModified + \li \c fileAccessed + \li \c fileIsDir + \endlist + + Additionally a file entry can be differentiated from a folder entry via the + isFolder() method. + + \section1 Filtering + + Various properties can be set to filter the number of files and directories + exposed by the model. + + The \l nameFilters property can be set to contain a list of wildcard filters + that are applied to names of files and directories, causing only those that + match the filters to be exposed. + + Directories can be included or excluded using the \l showDirs property, + navigation directories can also be excluded by setting the \l showDotAndDotDot + property to false, hidden files can be included or excluded using the + \l showHidden property. + + It is sometimes useful to limit the files and directories exposed to those + that the user can access. The \l showOnlyReadable property can be set to + enable this feature. + + \section1 Example Usage + + The following example shows a FolderListModel being used to provide a list + of QML files in a \l ListView: + + \qml + import QtQuick + import Qt.labs.folderlistmodel + + ListView { + width: 200; height: 400 + + FolderListModel { + id: folderModel + nameFilters: ["*.qml"] + } + + Component { + id: fileDelegate + Text { text: fileName } + } + + model: folderModel + delegate: fileDelegate + } + \endqml + + \section1 Path Separators + + Qt uses "/" as a universal directory separator in the same way that "/" is + used as a path separator in URLs. If you always use "/" as a directory + separator, Qt will translate your paths to conform to the underlying + operating system. + + \sa {QML Data Models} +*/ + +QQuickFolderListModel::QQuickFolderListModel(QObject *parent) + : QAbstractListModel(parent), d_ptr(new QQuickFolderListModelPrivate(this)) +{ + 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"; + d->roleNames[FileUrlRole] = "fileUrl"; + d->roleNames[FileURLRole] = "fileURL"; + d->init(); +} + +QQuickFolderListModel::~QQuickFolderListModel() +{ +} + +QVariant QQuickFolderListModel::data(const QModelIndex &index, int role) const +{ + Q_D(const QQuickFolderListModel); + QVariant rv; + + 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(); + break; + case FileLastReadRole: + rv = d->data.at(index.row()).lastRead(); + break; + case FileIsDirRole: + rv = d->data.at(index.row()).isDir(); + break; + case FileUrlRole: + case FileURLRole: + rv = QUrl::fromLocalFile(d->data.at(index.row()).filePath()); + break; + default: + break; + } + return rv; +} + +QHash QQuickFolderListModel::roleNames() const +{ + Q_D(const QQuickFolderListModel); + return d->roleNames; +} + +/*! + \qmlproperty int FolderListModel::count + + Returns the number of items in the current folder that match the + filter criteria. +*/ +int QQuickFolderListModel::rowCount(const QModelIndex &parent) const +{ + Q_D(const QQuickFolderListModel); + Q_UNUSED(parent); + return d->data.size(); +} + +QModelIndex QQuickFolderListModel::index(int row, int , const QModelIndex &) const +{ + return createIndex(row, 0); +} + +/*! + \qmlproperty url FolderListModel::folder + + The \a folder property holds a URL for the folder that the model + currently provides. + + The value must be a \c file: or \c qrc: URL, or a relative URL. + + The default value is an invalid URL. +*/ +QUrl QQuickFolderListModel::folder() const +{ + Q_D(const QQuickFolderListModel); + return d->currentDir; +} + +void QQuickFolderListModel::setFolder(const QUrl &folder) +{ + Q_D(QQuickFolderListModel); + + if (folder == d->currentDir) + return; + + QString resolvedPath = QQuickFolderListModelPrivate::resolvePath(folder); + + 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(); + if (d->status != QQuickFolderListModel::Null) { + d->status = QQuickFolderListModel::Null; + emit statusChanged(); + } + return; + } + + d->fileInfoThread.setPath(resolvedPath); +} + + +/*! + \qmlproperty url FolderListModel::rootFolder + + When this property is set, the given folder will + be treated as the root in the file system, so that + you can only traverse subfolders within it. +*/ +QUrl QQuickFolderListModel::rootFolder() const +{ + Q_D(const QQuickFolderListModel); + return d->rootDir; +} + +void QQuickFolderListModel::setRootFolder(const QUrl &path) +{ + Q_D(QQuickFolderListModel); + + if (path.isEmpty()) + return; + + QString resolvedPath = QQuickFolderListModelPrivate::resolvePath(path); + + QFileInfo info(resolvedPath); + if (!info.exists() || !info.isDir()) + return; + + d->fileInfoThread.setRootPath(resolvedPath); + d->rootDir = path; +} + + +/*! + \qmlproperty url FolderListModel::parentFolder + + Returns the URL of the parent of the current \l folder. +*/ +QUrl QQuickFolderListModel::parentFolder() const +{ + Q_D(const QQuickFolderListModel); + + QString localFile = d->currentDir.toLocalFile(); + if (!localFile.isEmpty()) { + QDir dir(localFile); + if (dir.isRoot() || !dir.cdUp()) + return QUrl(); + localFile = dir.path(); + } else { + const QString path = d->currentDir.path(); + const int pos = path.lastIndexOf(QLatin1Char('/')); + if (pos <= 0) + return QUrl(); + localFile = path.left(pos); + } + return QUrl::fromLocalFile(localFile); +} + +/*! + \qmlproperty list FolderListModel::nameFilters + + The \a nameFilters property contains a list of file name filters. + The filters may include the ? and * wildcards. + + The example below filters on PNG and JPEG files: + + \qml + FolderListModel { + nameFilters: [ "*.png", "*.jpg" ] + } + \endqml + + \note Directories are not excluded by filters. +*/ +QStringList QQuickFolderListModel::nameFilters() const +{ + Q_D(const QQuickFolderListModel); + return d->nameFilters; +} + +void QQuickFolderListModel::setNameFilters(const QStringList &filters) +{ + Q_D(QQuickFolderListModel); + if (d->nameFilters == filters) + return; + d->fileInfoThread.setNameFilters(filters); + d->nameFilters = filters; +} + +void QQuickFolderListModel::classBegin() +{ +} + +void QQuickFolderListModel::componentComplete() +{ + Q_D(QQuickFolderListModel); + QString localPath = QQmlFile::urlToLocalFileOrQrc(d->currentDir); + if (localPath.isEmpty() || !QDir(localPath).exists()) + setFolder(QUrl::fromLocalFile(QDir::currentPath())); + d->fileInfoThread.start(QThread::LowPriority); +} + +/*! + \qmlproperty enumeration FolderListModel::sortField + + The \a sortField property contains field to use for sorting. sortField + may be one of: + \list + \li Unsorted - no sorting is applied. + \li Name - sort by filename + \li Time - sort by time modified + \li Size - sort by file size + \li Type - sort by file type (extension) + \endlist + + \sa sortReversed +*/ +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 + + If set to true, reverses the sort order. The default is false. + + \sa sortField +*/ +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(); + } +} + +/*! + \qmlmethod bool FolderListModel::isFolder(int index) + + Returns true if the entry \a index is a folder; otherwise + returns false. +*/ +bool QQuickFolderListModel::isFolder(int index) const +{ + if (index != -1) { + QModelIndex idx = createIndex(index, 0); + if (idx.isValid()) { + QVariant var = data(idx, FileIsDirRole); + if (var.isValid()) + return var.toBool(); + } + } + return false; +} + +/*! + \qmlproperty bool FolderListModel::showFiles + \since 5.2 + + If true, files are included in the model; otherwise only directories + are included. + + By default, this property is true. + + \sa showDirs +*/ +bool QQuickFolderListModel::showFiles() const +{ + Q_D(const QQuickFolderListModel); + return d->showFiles; +} + +void QQuickFolderListModel::setShowFiles(bool on) +{ + Q_D(QQuickFolderListModel); + + d->fileInfoThread.setShowFiles(on); + d->showFiles = on; +} + +/*! + \qmlproperty bool FolderListModel::showDirs + + If true, directories are included in the model; otherwise only files + are included. + + By default, this property is true. + + Note that the nameFilters are not applied to directories. + + \sa showDotAndDotDot +*/ +bool QQuickFolderListModel::showDirs() const +{ + Q_D(const QQuickFolderListModel); + return d->showDirs; +} + +void QQuickFolderListModel::setShowDirs(bool on) +{ + Q_D(QQuickFolderListModel); + + d->fileInfoThread.setShowDirs(on); + d->showDirs = on; +} + +/*! + \qmlproperty bool FolderListModel::showDirsFirst + + If true, if directories are included in the model they will + always be shown first, then the files. + + By default, this property is false. + +*/ +bool QQuickFolderListModel::showDirsFirst() const +{ + Q_D(const QQuickFolderListModel); + return d->showDirsFirst; +} + +void QQuickFolderListModel::setShowDirsFirst(bool on) +{ + Q_D(QQuickFolderListModel); + + d->fileInfoThread.setShowDirsFirst(on); + d->showDirsFirst = on; +} + + +/*! + \qmlproperty bool FolderListModel::showDotAndDotDot + + If true, the "." and ".." directories are included in the model; otherwise + they are excluded. + + By default, this property is false. + + \sa showDirs +*/ +bool QQuickFolderListModel::showDotAndDotDot() const +{ + Q_D(const QQuickFolderListModel); + return d->showDotAndDotDot; +} + +void QQuickFolderListModel::setShowDotAndDotDot(bool on) +{ + Q_D(QQuickFolderListModel); + + if (on != d->showDotAndDotDot) { + d->fileInfoThread.setShowDotAndDotDot(on); + d->showDotAndDotDot = on; + } +} + + +/*! + \qmlproperty bool FolderListModel::showHidden + \since 5.2 + + If true, hidden files and directories are included in the model; otherwise + they are excluded. + + By default, this property is false. +*/ +bool QQuickFolderListModel::showHidden() const +{ + Q_D(const QQuickFolderListModel); + return d->showHidden; +} + +void QQuickFolderListModel::setShowHidden(bool on) +{ + Q_D(QQuickFolderListModel); + + if (on != d->showHidden) { + d->fileInfoThread.setShowHidden(on); + d->showHidden = on; + } +} + +/*! + \qmlproperty bool FolderListModel::showOnlyReadable + + If true, only readable files and directories are shown; otherwise all files + and directories are shown. + + By default, this property is false. + + \sa showDirs +*/ +bool QQuickFolderListModel::showOnlyReadable() const +{ + Q_D(const QQuickFolderListModel); + return d->showOnlyReadable; +} + +void QQuickFolderListModel::setShowOnlyReadable(bool on) +{ + Q_D(QQuickFolderListModel); + + if (on != d->showOnlyReadable) { + d->fileInfoThread.setShowOnlyReadable(on); + d->showOnlyReadable = on; + } +} + +/*! + * \qmlproperty bool FolderListModel::caseSensitive + * \since 5.7 + * + * Use case sensitive pattern matching. + * + * By default, this property is true. + * + */ +bool QQuickFolderListModel::caseSensitive() const +{ + Q_D(const QQuickFolderListModel); + return d->caseSensitive; +} + +void QQuickFolderListModel::setCaseSensitive(bool on) +{ + Q_D(QQuickFolderListModel); + + if (on != d->caseSensitive) { + d->fileInfoThread.setCaseSensitive(on); + d->caseSensitive = on; + } +} + +/*! + \qmlproperty enumeration FolderListModel::status + \since 5.11 + + This property holds the status of folder reading. It can be one of: + \list + \li FolderListModel.Null - no \a folder has been set + \li FolderListModel.Ready - the folder has been loaded + \li FolderListModel.Loading - the folder is currently being loaded + \endlist + + Use this status to provide an update or respond to the status change in some way. + For example, you could: + + \list + \li Trigger a state change: + \qml + State { name: 'loaded'; when: folderModel.status == FolderListModel.Ready } + \endqml + + \li Implement an \c onStatusChanged signal handler: + \qml + FolderListModel { + id: folderModel + onStatusChanged: if (folderModel.status == FolderListModel.Ready) console.log('Loaded') + } + \endqml + + \li Bind to the status value: + \qml + Text { text: folderModel.status == FolderListModel.Ready ? 'Loaded' : 'Not loaded' } + \endqml + \endlist +*/ +QQuickFolderListModel::Status QQuickFolderListModel::status() const +{ + Q_D(const QQuickFolderListModel); + return d->status; +} + +/*! + \qmlproperty bool FolderListModel::sortCaseSensitive + \since 5.12 + + If set to \c true, the sort is case sensitive. This property is \c true by default. +*/ + +bool QQuickFolderListModel::sortCaseSensitive() const +{ + Q_D(const QQuickFolderListModel); + return d->sortCaseSensitive; +} + +void QQuickFolderListModel::setSortCaseSensitive(bool on) +{ + Q_D(QQuickFolderListModel); + + if (on != d->sortCaseSensitive) { + d->sortCaseSensitive = on; + d->updateSorting(); + } +} + +/*! + \qmlmethod var FolderListModel::get(int index, string property) + + Returns the folder \a property for the given \a index. The following properties + are available: + + \list + \li \c fileName + \li \c filePath + \li \c fileURL (since Qt 5.2; deprecated since Qt 5.15) + \li \c fileUrl (since Qt 5.15) + \li \c fileBaseName + \li \c fileSuffix + \li \c fileSize + \li \c fileModified + \li \c fileAccessed + \li \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(); +} + +/*! + \qmlmethod int FolderListModel::indexOf(url file) + \since 5.6 + + Returns the index of the given \a file URL if the model contains it, + or -1 if not. +*/ +int QQuickFolderListModel::indexOf(const QUrl &file) const +{ + Q_D(const QQuickFolderListModel); + FileProperty toFind(QFileInfo(file.toLocalFile())); + return d->data.indexOf(toFind); +} + +#include "moc_qquickfolderlistmodel.cpp" + +//![code] +QT_END_NAMESPACE diff --git a/src/labs/folderlistmodel/qquickfolderlistmodel.h b/src/labs/folderlistmodel/qquickfolderlistmodel.h new file mode 100644 index 0000000000..ba55ad2b92 --- /dev/null +++ b/src/labs/folderlistmodel/qquickfolderlistmodel.h @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKFOLDERLISTMODEL_H +#define QQUICKFOLDERLISTMODEL_H + +#include "qquickfolderlistmodelglobal_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + + +class QQmlContext; +class QModelIndex; + +class QQuickFolderListModelPrivate; + +//![class begin] +class Q_LABSFOLDERMODEL_PRIVATE_EXPORT QQuickFolderListModel : public QAbstractListModel, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) +//![class begin] + +//![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 showFiles READ showFiles WRITE setShowFiles REVISION(2, 1)) + 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 showHidden READ showHidden WRITE setShowHidden REVISION(2, 1)) + Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable) + Q_PROPERTY(bool caseSensitive READ caseSensitive WRITE setCaseSensitive REVISION(2, 2)) + Q_PROPERTY(int count READ count NOTIFY countChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged REVISION(2, 11)) + Q_PROPERTY(bool sortCaseSensitive READ sortCaseSensitive WRITE setSortCaseSensitive REVISION(2, 12)) +//![class props] + + QML_NAMED_ELEMENT(FolderListModel) + QML_ADDED_IN_VERSION(2, 0) +//![abslistmodel] +public: + QQuickFolderListModel(QObject *parent = nullptr); + ~QQuickFolderListModel(); + + 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, + FileUrlRole = Qt::UserRole + 9, + FileURLRole = Qt::UserRole + 10 + }; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const override; +//![abslistmodel] + +//![count] + int count() const { return rowCount(QModelIndex()); } +//![count] + +//![prop funcs] + QUrl folder() const; + void setFolder(const QUrl &folder); + QUrl rootFolder() const; + void setRootFolder(const QUrl &path); + + QUrl parentFolder() const; + + QStringList nameFilters() const; + void setNameFilters(const QStringList &filters); + + enum SortField { Unsorted, Name, Time, Size, Type }; + Q_ENUM(SortField) + SortField sortField() const; + void setSortField(SortField field); + + bool sortReversed() const; + void setSortReversed(bool rev); + + bool showFiles() const; + void setShowFiles(bool showFiles); + bool showDirs() const; + void setShowDirs(bool showDirs); + bool showDirsFirst() const; + void setShowDirsFirst(bool showDirsFirst); + bool showDotAndDotDot() const; + void setShowDotAndDotDot(bool on); + bool showHidden() const; + void setShowHidden(bool on); + bool showOnlyReadable() const; + void setShowOnlyReadable(bool on); + bool caseSensitive() const; + void setCaseSensitive(bool on); + + enum Status { Null, Ready, Loading }; + Q_ENUM(Status) + Status status() const; + bool sortCaseSensitive() const; + void setSortCaseSensitive(bool on); +//![prop funcs] + + Q_INVOKABLE bool isFolder(int index) const; + Q_INVOKABLE QVariant get(int idx, const QString &property) const; + Q_INVOKABLE int indexOf(const QUrl &file) const; + +//![parserstatus] + void classBegin() override; + void componentComplete() override; +//![parserstatus] + + int roleFromString(const QString &roleName) const; + +//![notifier] +Q_SIGNALS: + void folderChanged(); + void rowCountChanged() const; + Q_REVISION(2, 1) void countChanged() const; + Q_REVISION(2, 11) void statusChanged(); +//![notifier] + +//![class end] + + +private: + Q_DISABLE_COPY(QQuickFolderListModel) + Q_DECLARE_PRIVATE(QQuickFolderListModel) + QScopedPointer d_ptr; + + Q_PRIVATE_SLOT(d_func(), void _q_directoryChanged(const QString &directory, const QList &list)) + Q_PRIVATE_SLOT(d_func(), void _q_directoryUpdated(const QString &directory, const QList &list, int fromIndex, int toIndex)) + Q_PRIVATE_SLOT(d_func(), void _q_sortFinished(const QList &list)) + Q_PRIVATE_SLOT(d_func(), void _q_statusChanged(QQuickFolderListModel::Status s)) +}; +//![class end] + +QT_END_NAMESPACE + +#endif // QQUICKFOLDERLISTMODEL_H diff --git a/src/labs/folderlistmodel/qquickfolderlistmodelglobal_p.h b/src/labs/folderlistmodel/qquickfolderlistmodelglobal_p.h new file mode 100644 index 0000000000..c8df4e9ff7 --- /dev/null +++ b/src/labs/folderlistmodel/qquickfolderlistmodelglobal_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTLABSFOLDERLISTMODELGLOBAL_P_H +#define QTLABSFOLDERLISTMODELGLOBAL_P_H + +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +#if !defined(QT_STATIC) +# if defined(QT_BUILD_LABSFOLDERMODEL_LIB) +# define Q_LABSFOLDERMODEL_EXPORT Q_DECL_EXPORT +# else +# define Q_LABSFOLDERMODEL_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_LABSFOLDERMODEL_EXPORT +#endif +#define Q_LABSFOLDERMODEL_PRIVATE_EXPORT Q_LABSFOLDERMODEL_EXPORT + +QT_END_NAMESPACE + +void Q_LABSFOLDERMODEL_PRIVATE_EXPORT qml_register_types_Qt_labs_folderlistmodel(); + +#endif // QTLABSFOLDERLISTMODELGLOBAL_P_H -- cgit v1.2.3