#include "qdeclarativefolderlistmodel.h"
#include <QDirModel>
#include <QDebug>
#include <qdeclarativecontext.h>
#ifndef QT_NO_DIRMODEL
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;
};
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(handleDataChanged(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;
}
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);
}
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() || d->folder.toLocalFile().isEmpty() || !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();
}
}
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-1);
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::handleDataChanged(const QModelIndex &start, const QModelIndex &end)
{
if (start.parent() == d->folderIndex)
emit dataChanged(index(start.row(),0), index(end.row(),0));
}
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));
}
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);
}
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);
}
#endif // QT_NO_DIRMODEL