/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
//![code]
#include "qdeclarativefolderlistmodel.h"
#include <QDirModel>
#include <QDebug>
#include <qdeclarativecontext.h>
#ifndef QT_NO_DIRMODEL
QT_BEGIN_NAMESPACE
class QDeclarativeFolderListModelPrivate
{
public:
QDeclarativeFolderListModelPrivate()
: sortField(QDeclarativeFolderListModel::Name), sortReversed(false), count(0) {
nameFilters << QLatin1String("*");
}
void updateSorting() {
QDir::SortFlags flags = 0;
switch(sortField) {
case QDeclarativeFolderListModel::Unsorted:
flags |= QDir::Unsorted;
break;
case QDeclarativeFolderListModel::Name:
flags |= QDir::Name;
break;
case QDeclarativeFolderListModel::Time:
flags |= QDir::Time;
break;
case QDeclarativeFolderListModel::Size:
flags |= QDir::Size;
break;
case QDeclarativeFolderListModel::Type:
flags |= QDir::Type;
break;
}
if (sortReversed)
flags |= QDir::Reversed;
model.setSorting(flags);
}
QDirModel model;
QUrl folder;
QStringList nameFilters;
QModelIndex folderIndex;
QDeclarativeFolderListModel::SortField sortField;
bool sortReversed;
int count;
};
/*!
\qmlclass FolderListModel QDeclarativeFolderListModel
\brief The FolderListModel provides a model of the contents of a folder in a filesystem.
FolderListModel provides access to the local filesystem. The \e folder property
specifies the folder to list.
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.
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.}
\bold{import Qt.labs.folderlistmodel 1.0}
The roles available are:
\list
\o fileName
\o filePath
\endlist
Additionally a file entry can be differentiated from a folder entry
via the \l isFolder() method.
*/
QDeclarativeFolderListModel::QDeclarativeFolderListModel(QObject *parent)
: QAbstractListModel(parent)
{
QHash<int, QByteArray> roles;
roles[FileNameRole] = "fileName";
roles[FilePathRole] = "filePath";
setRoleNames(roles);
d = new QDeclarativeFolderListModelPrivate;
d->model.setFilter(QDir::AllDirs | QDir::Files | QDir::Drives | QDir::NoDotAndDotDot);
connect(&d->model, SIGNAL(rowsInserted(const QModelIndex&,int,int))
, this, SLOT(inserted(const QModelIndex&,int,int)));
connect(&d->model, SIGNAL(rowsRemoved(const QModelIndex&,int,int))
, this, SLOT(removed(const QModelIndex&,int,int)));
connect(&d->model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))
, this, SLOT(dataChanged(const QModelIndex&,const QModelIndex&)));
connect(&d->model, SIGNAL(modelReset()), this, SLOT(refresh()));
connect(&d->model, SIGNAL(layoutChanged()), this, SLOT(refresh()));
}
QDeclarativeFolderListModel::~QDeclarativeFolderListModel()
{
delete d;
}
QVariant QDeclarativeFolderListModel::data(const QModelIndex &index, int role) const
{
QVariant rv;
QModelIndex modelIndex = d->model.index(index.row(), 0, d->folderIndex);
if (modelIndex.isValid()) {
if (role == FileNameRole)
rv = d->model.data(modelIndex, QDirModel::FileNameRole).toString();
else if (role == FilePathRole)
rv = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString());
}
return rv;
}
int QDeclarativeFolderListModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return d->count;
}
/*!
\qmlproperty string FolderListModel::folder
The \a folder property holds the folder the model is currently providing.
It is a URL, but must be a file: or qrc: URL (or relative to such a URL).
*/
QUrl QDeclarativeFolderListModel::folder() const
{
return d->folder;
}
void QDeclarativeFolderListModel::setFolder(const QUrl &folder)
{
if (folder == d->folder)
return;
QModelIndex index = d->model.index(folder.toLocalFile());
if ((index.isValid() && d->model.isDir(index)) || folder.toLocalFile().isEmpty()) {
d->folder = folder;
QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
emit folderChanged();
}
}
QUrl QDeclarativeFolderListModel::parentFolder() const
{
QString localFile = d->folder.toLocalFile();
if (!localFile.isEmpty()) {
QDir dir(localFile);
#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WIN)
if (dir.isRoot())
dir.setPath("");
else
#endif
dir.cdUp();
localFile = dir.path();
} else {
int pos = d->folder.path().lastIndexOf(QLatin1Char('/'));
if (pos == -1)
return QUrl();
localFile = d->folder.path().left(pos);
}
return QUrl::fromLocalFile(localFile);
}
/*!
\qmlproperty list<string> FolderListModel::nameFilters
The \a nameFilters property contains a list of filename filters.
The filters may include the ? and * wildcards.
The example below filters on PNG and JPEG files:
\code
FolderListModel {
nameFilters: [ "*.png", "*.jpg" ]
}
\endcode
*/
QStringList QDeclarativeFolderListModel::nameFilters() const
{
return d->nameFilters;
}
void QDeclarativeFolderListModel::setNameFilters(const QStringList &filters)
{
d->nameFilters = filters;
d->model.setNameFilters(d->nameFilters);
}
void QDeclarativeFolderListModel::classBegin()
{
}
void QDeclarativeFolderListModel::componentComplete()
{
if (!d->folder.isValid() || !QDir().exists(d->folder.toLocalFile()))
setFolder(QUrl(QLatin1String("file://")+QDir::currentPath()));
if (!d->folderIndex.isValid())
QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
}
QDeclarativeFolderListModel::SortField QDeclarativeFolderListModel::sortField() const
{
return d->sortField;
}
void QDeclarativeFolderListModel::setSortField(SortField field)
{
if (field != d->sortField) {
d->sortField = field;
d->updateSorting();
}
}
bool QDeclarativeFolderListModel::sortReversed() const
{
return d->sortReversed;
}
void QDeclarativeFolderListModel::setSortReversed(bool rev)
{
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 QDeclarativeFolderListModel::isFolder(int index) const
{
if (index != -1) {
QModelIndex idx = d->model.index(index, 0, d->folderIndex);
if (idx.isValid())
return d->model.isDir(idx);
}
return false;
}
void QDeclarativeFolderListModel::refresh()
{
d->folderIndex = QModelIndex();
if (d->count) {
emit beginRemoveRows(QModelIndex(), 0, d->count);
d->count = 0;
emit endRemoveRows();
}
d->folderIndex = d->model.index(d->folder.toLocalFile());
int newcount = d->model.rowCount(d->folderIndex);
if (newcount) {
emit beginInsertRows(QModelIndex(), 0, newcount-1);
d->count = newcount;
emit endInsertRows();
}
}
void QDeclarativeFolderListModel::inserted(const QModelIndex &index, int start, int end)
{
if (index == d->folderIndex) {
emit beginInsertRows(QModelIndex(), start, end);
d->count = d->model.rowCount(d->folderIndex);
emit endInsertRows();
}
}
void QDeclarativeFolderListModel::removed(const QModelIndex &index, int start, int end)
{
if (index == d->folderIndex) {
emit beginRemoveRows(QModelIndex(), start, end);
d->count = d->model.rowCount(d->folderIndex);
emit endRemoveRows();
}
}
void QDeclarativeFolderListModel::dataChanged(const QModelIndex &start, const QModelIndex &end)
{
if (start.parent() == d->folderIndex)
emit dataChanged(index(start.row(),0), index(end.row(),0));
}
/*!
\qmlproperty bool FolderListModel::showDirs
If true (the default), directories are included in the model.
Note that the nameFilters are ignored for directories.
*/
bool QDeclarativeFolderListModel::showDirs() const
{
return d->model.filter() & QDir::AllDirs;
}
void QDeclarativeFolderListModel::setShowDirs(bool on)
{
if (!(d->model.filter() & QDir::AllDirs) == !on)
return;
if (on)
d->model.setFilter(d->model.filter() | QDir::AllDirs | QDir::Drives);
else
d->model.setFilter(d->model.filter() & ~(QDir::AllDirs | QDir::Drives));
}
/*!
\qmlproperty bool FolderListModel::showDotAndDotDot
If true, the "." and ".." directories are included in the model.
The default is false.
*/
bool QDeclarativeFolderListModel::showDotAndDotDot() const
{
return !(d->model.filter() & QDir::NoDotAndDotDot);
}
void QDeclarativeFolderListModel::setShowDotAndDotDot(bool on)
{
if (!(d->model.filter() & QDir::NoDotAndDotDot) == on)
return;
if (on)
d->model.setFilter(d->model.filter() & ~QDir::NoDotAndDotDot);
else
d->model.setFilter(d->model.filter() | QDir::NoDotAndDotDot);
}
/*!
\qmlproperty bool FolderListModel::showOnlyReadable
If true, only readable files and directories are shown.
The default is false.
*/
bool QDeclarativeFolderListModel::showOnlyReadable() const
{
return d->model.filter() & QDir::Readable;
}
void QDeclarativeFolderListModel::setShowOnlyReadable(bool on)
{
if (!(d->model.filter() & QDir::Readable) == !on)
return;
if (on)
d->model.setFilter(d->model.filter() | QDir::Readable);
else
d->model.setFilter(d->model.filter() & ~QDir::Readable);
}
//![code]
QT_END_NAMESPACE
#endif // QT_NO_DIRMODEL