1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the item views module of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include "qdirmodel.h"
36
#include <qdatetime.h>
38
#include <qapplication.h>
39
#include <private/qabstractitemmodel_p.h>
43
\class QFileIconProvider
45
\brief The QFileIconProvider class provides file icon for the QDirModel class.
49
\enum QFileIconProvider::IconType
60
\enum QDirModel::Roles
66
class QFileIconProviderPrivate
68
Q_DECLARE_PUBLIC(QFileIconProvider)
70
QFileIconProviderPrivate();
86
QFileIconProvider *q_ptr;
89
QFileIconProviderPrivate::QFileIconProviderPrivate()
91
QStyle *style = QApplication::style();
93
file = QIcon(style->standardPixmap(QStyle::SP_FileIcon));
94
fileLink = QIcon(style->standardPixmap(QStyle::SP_FileLinkIcon));
96
directory = QIcon(style->standardPixmap(QStyle::SP_DirClosedIcon));
97
directory.addPixmap(style->standardPixmap(QStyle::SP_DirOpenIcon), QIcon::Normal, QIcon::On);
98
directoryLink = QIcon(style->standardPixmap(QStyle::SP_DirLinkIcon));
100
harddisk = QIcon(style->standardPixmap(QStyle::SP_DriveHDIcon));
101
floppy = QIcon(style->standardPixmap(QStyle::SP_DriveFDIcon));
102
cdrom = QIcon(style->standardPixmap(QStyle::SP_DriveCDIcon));
103
generic = ram = harddisk; // FIXME
104
network = QIcon(style->standardPixmap(QStyle::SP_DriveNetIcon));
105
computer = QIcon(style->standardPixmap(QStyle::SP_ComputerIcon));
106
desktop = QIcon(style->standardPixmap(QStyle::SP_DesktopIcon));
107
trashcan = QIcon(style->standardPixmap(QStyle::SP_TrashIcon));
111
Constructs a file icon provider.
114
QFileIconProvider::QFileIconProvider()
115
: d_ptr(new QFileIconProviderPrivate)
120
Destroys the file icon provider.
124
QFileIconProvider::~QFileIconProvider()
130
Returns an icon set for the given \a type.
133
QIcon QFileIconProvider::icon(IconType type) const
137
return d_ptr->computer;
139
return d_ptr->desktop;
141
return d_ptr->trashcan;
143
return d_ptr->network;
145
return d_ptr->generic;
147
return d_ptr->directory;
157
Returns an icon for the file described by \a info.
160
QIcon QFileIconProvider::icon(const QFileInfo &info) const
166
uint type = DRIVE_UNKNOWN;
167
QT_WA({ type = GetDriveTypeW((wchar_t *)info.absoluteFilePath().utf16()); },
168
{ type = GetDriveTypeA(info.absoluteFilePath().toLocal8Bit()); });
170
case DRIVE_REMOVABLE:
171
return d_ptr->floppy;
173
return d_ptr->harddisk;
175
return d_ptr->network;
181
return d_ptr->generic;
182
case DRIVE_NO_ROOT_DIR:
183
return d_ptr->generic;
187
return d_ptr->generic;
190
if (info.isSymLink())
191
return d_ptr->fileLink;
195
if (info.isSymLink())
196
return d_ptr->directoryLink;
198
return d_ptr->directory;
203
Returns the type of the file described by \a info.
206
QString QFileIconProvider::type(const QFileInfo &info) const
209
return QObject::tr("Drive");
211
return info.suffix() + " " + QObject::tr("File");
213
return QObject::tr("Directory");
214
if (info.isSymLink())
215
return QObject::tr("Symbolic Link");
216
return QObject::tr("Unknown");
219
#define Q_DIRMODEL_CACHED
221
class QDirModelPrivate : public QAbstractItemModelPrivate
223
Q_DECLARE_PUBLIC(QDirModel)
229
mutable QVector<QDirNode> children;
230
mutable bool populated; // have we read the children
231
#ifndef Q_DIRMODEL_CACHED
232
inline qint64 size() const { return info.size(); }
233
inline QDateTime lastModified() const { return info.lastModified(); }
235
inline qint64 size() const { return cached_size; }
236
inline QDateTime lastModified() const { return cached_modified; }
238
QDateTime cached_modified;
243
: resolveSymlinks(true),
245
lazyChildCount(false),
246
iconProvider(&defaultProvider) {}
249
QDirNode *node(int row, QDirNode *parent) const;
250
QDirNode *parent(QDirNode *child) const;
251
QVector<QDirNode> children(QDirNode *parent) const;
252
int idx(QDirNode *node) const;
253
void refresh(QDirNode *parent);
255
void savePersistentIndexes();
256
void restorePersistentIndexes();
258
inline QIcon rootIcon() const {
259
return iconProvider->icon(QFileIconProvider::Computer);
262
inline QFileInfoList entryInfoList(const QString &path) const {
263
const QDir dir(path);
264
QFileInfoList fil = dir.entryInfoList(nameFilters, filters, sort);
265
for (int i = 0; i < fil.count(); ++i) {
266
QString fn = fil.at(i).fileName();
267
if (fn == "." || fn == "..")
273
inline QStringList entryList(const QString &path) const {
274
const QDir dir(path);
275
QStringList sl = dir.entryList(nameFilters, filters, sort);
276
for (int i = 0; i < sl.count(); ++i) {
277
QString fn = sl.at(i);
278
if (fn == "." || fn == "..")
284
inline void populate(QDirNode *parent) const {
286
parent->children = children(parent);
287
parent->populated = true;
290
inline void clear(QDirNode *parent) const {
292
parent->children.clear();
293
parent->populated = false;
296
mutable QDirNode root;
297
bool resolveSymlinks;
301
QDir::Filters filters;
302
QDir::SortFlags sort;
303
QStringList nameFilters;
305
QFileIconProvider *iconProvider;
306
QFileIconProvider defaultProvider;
308
QList< QPair<QString,int> > saved;
312
\class QDirModel qdirmodel.h
314
\brief The QDirModel class provides a data model for the local filesystem.
318
This class provides access to the local filesystem, providing functions
319
for renaming and removing files and directories, and for creating new
320
directories. In the simplest case, it can be used with a suitable display
321
widget as part of a browser or filer.
323
QDirModel does not store file information internally or cache file data.
325
A directory model that displays the contents of a default directory
326
is usually constructed with a parent object:
328
\quotefromfile snippets/shareddirmodel/main.cpp
329
\skipto QDirModel *model
330
\printuntil QDirModel *model
332
A tree view can be used to display the contents of the model
334
\skipto QTreeView *tree
335
\printuntil tree->setModel(
337
and the contents of a particular directory can be displayed by
338
setting the tree view's root index:
340
\printuntil tree->setRootIndex(
342
The view's root index can be used to control how much of a
343
hierarchical model is displayed. QDirModel provides a convenience
344
function that returns a suitable model index for a path to a
345
directory within the model.
347
QDirModel can be accessed using the standard interface provided by
348
QAbstractItemModel, but it also provides some convenience functions that are
349
specific to a directory model.
350
The fileInfo(), isDir(), name(), and path() functions provide information
351
about the underlying files and directories related to items in the model.
352
Directories can be created and removed using mkdir(), rmdir(), and the
353
model will be automatically updated to take the changes into account.
355
\sa nameFilters(), setFilter(), filter(),
356
\link model-view-programming.html Model/View Programming\endlink QListView QTreeView
361
Constructs a new directory model with the given \a parent.
362
Only those files matching the \a nameFilters and the
363
\a filters are included in the model. The sort order is given by the
367
QDirModel::QDirModel(const QStringList &nameFilters,
368
QDir::Filters filters,
369
QDir::SortFlags sort,
371
: QAbstractItemModel(*new QDirModelPrivate, parent)
374
// we always start with QDir::drives()
375
d->nameFilters = nameFilters.isEmpty() ? QStringList("*") : nameFilters;
376
d->filters = filters;
379
d->root.info = QFileInfo();
384
Constructs a directory model with the given \a parent.
387
QDirModel::QDirModel(QObject *parent)
388
: QAbstractItemModel(*new QDirModelPrivate, parent)
397
QDirModel::QDirModel(QDirModelPrivate &dd, QObject *parent)
398
: QAbstractItemModel(dd, parent)
405
Destroys this directory model.
408
QDirModel::~QDirModel()
414
Returns the model item index for the item in the \a parent with the
415
given \a row and \a column.
419
QModelIndex QDirModel::index(int row, int column, const QModelIndex &parent) const
421
Q_D(const QDirModel);
422
if (column < 0 || column >= 4 || row < 0 || row >= rowCount(parent)) // does lazy population
423
return QModelIndex();
425
QDirModelPrivate::QDirNode *p =
426
static_cast<QDirModelPrivate::QDirNode*>(parent.internalPointer());
427
QDirModelPrivate::QDirNode *n = d->node(row, p);
430
return createIndex(row, column, n);
434
Return the parent of the given \a child model item.
437
QModelIndex QDirModel::parent(const QModelIndex &child) const
439
Q_D(const QDirModel);
440
if (!child.isValid())
441
return QModelIndex();
443
QDirModelPrivate::QDirNode *node =
444
static_cast<QDirModelPrivate::QDirNode*>(child.internalPointer());
447
QDirModelPrivate::QDirNode *par = d->parent(node);
449
return QModelIndex(); // parent is the root node
453
return createIndex(r, 0, par);
457
Returns the number of rows in the \a parent model item.
461
int QDirModel::rowCount(const QModelIndex &parent) const
463
Q_D(const QDirModel);
464
QDirModelPrivate::QDirNode *p =
465
static_cast<QDirModelPrivate::QDirNode*>(parent.internalPointer());
467
bool isDir = !p || p->info.isDir(); // no node pointer means that it is the root
468
if (!p) p = &(d->root);
469
if (isDir && !p->populated) // lazy population
471
return p->children.count();
475
Returns the number of columns in the \a parent model item.
479
int QDirModel::columnCount(const QModelIndex &) const
485
Returns the data for the model item \a index with the given \a role.
489
QVariant QDirModel::data(const QModelIndex &index, int role) const
491
Q_D(const QDirModel);
492
if (!index.isValid())
495
QDirModelPrivate::QDirNode *node =
496
static_cast<QDirModelPrivate::QDirNode*>(index.internalPointer());
499
if (role == Qt::DisplayRole || role == Qt::EditRole) {
500
switch (index.column()) {
502
if (node->info.isRoot()) {
503
QString name = node->info.absoluteFilePath();
505
if (name.at(0) == '/') // UNC host
506
return node->info.fileName();
507
if (name.at(name.length() - 1) == '/')
512
return node->info.fileName();
513
case 1: return node->size();
514
case 2: return d->iconProvider->type(node->info);
515
case 3: return node->lastModified();
517
qWarning("data: invalid display value column %d", index.column());
522
if (index.column() == 0) {
523
if (role == FileIconRole)
524
return fileIcon(index);
525
if (role == FilePathRole)
526
return filePath(index);
527
if (role == FileNameRole)
528
return fileName(index);
534
Sets the data for the model item \a index with the given \a role to
535
the data referenced by the \a value. Returns true if successful;
536
otherwise returns false.
540
bool QDirModel::setData(const QModelIndex &index, const QVariant &value, int role)
543
if (!index.isValid() || index.column() != 0
544
|| (flags(index) & Qt::ItemIsEditable) == 0 || role != Qt::EditRole)
547
QDirModelPrivate::QDirNode *node =
548
static_cast<QDirModelPrivate::QDirNode*>(index.internalPointer());
550
QDir dir = node->info.dir();
551
if (dir.rename(node->info.fileName(), value.toString())) {
552
QModelIndex par = parent(index);
553
QDirModelPrivate::QDirNode *p =
554
static_cast<QDirModelPrivate::QDirNode*>(par.internalPointer());
556
QModelIndex topLeft = this->index(0, 0, par);
557
int rc = rowCount(par);
558
int cc = columnCount(par);
559
QModelIndex bottomRight = this->index(rc, cc, par);
560
emit dataChanged(topLeft, bottomRight);
568
Returns the data stored under the given \a role for the specified \a section
569
of the header with the given \a orientation.
572
QVariant QDirModel::headerData(int section, Qt::Orientation orientation, int role) const
574
if (orientation == Qt::Horizontal) {
575
if (role != Qt::DisplayRole)
578
case 0: return tr("Name");
579
case 1: return tr("Size");
580
case 2: return tr("Type");
581
case 3: return tr("Modified");
582
default: return QVariant();
585
return QAbstractItemModel::headerData(section, orientation, role);
589
Returns true if the \a parent model item has children; otherwise
593
bool QDirModel::hasChildren(const QModelIndex &parent) const
595
Q_D(const QDirModel);
596
if (!parent.isValid()) // the invalid index is the "My Computer" item
597
return true; // the drives
598
QDirModelPrivate::QDirNode *p =
599
static_cast<QDirModelPrivate::QDirNode*>(parent.internalPointer());
601
if (d->lazyChildCount) { // optimization that only checks for children if the node has been populated
603
return rowCount(parent) > 0; // rowCount will lazily populate if needed
604
return p->info.isDir();
606
return p->info.isDir() && rowCount(parent) > 0;
610
Returns the item flags for the given \a index in the model.
614
Qt::ItemFlags QDirModel::flags(const QModelIndex &index) const
616
Q_D(const QDirModel);
617
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
618
if (!index.isValid())
620
flags |= Qt::ItemIsDragEnabled;
623
QDirModelPrivate::QDirNode *node =
624
static_cast<QDirModelPrivate::QDirNode*>(index.internalPointer());
626
if ((index.column() == 0) && node->info.isWritable()) {
627
flags |= Qt::ItemIsEditable;
628
if (fileInfo(index).isDir()) // is directory and is editable
629
flags |= Qt::ItemIsDropEnabled;
635
Sort the model items in the \a column using the \a order given.
636
The order is a value defined in \l Qt::SortOrder.
639
void QDirModel::sort(int column, Qt::SortOrder order)
641
QDir::SortFlags sort = 0;
642
if (order == Qt::DescendingOrder)
643
sort |= QDir::Reversed;
653
// FIXME: we should sort on the type string
654
sort |= QDir::DirsFirst;
667
Returns a list of MIME types that can be used to describe a list of items
671
QStringList QDirModel::mimeTypes() const
673
return QStringList("text/uri-list");
677
Returns an object that contains a serialized description of the specified
678
\a indexes. The format used to describe the items corresponding to the
679
indexes is obtained from the mimeTypes() function.
681
If the list of indexes is empty, 0 is returned rather than a serialized
685
QMimeData *QDirModel::mimeData(const QModelIndexList &indexes) const
688
QList<QModelIndex>::const_iterator it = indexes.begin();
689
for (; it != indexes.end(); ++it)
690
if ((*it).column() == 0)
691
urls << QUrl::fromLocalFile(filePath(*it));
692
QMimeData *data = new QMimeData();
698
Handles the \a data supplied by a drag and drop operation that ended with
699
the given \a action over the row in the model specified by the \a row and
700
\a column and by the \a parent index.
702
\sa supportedDropActions()
705
bool QDirModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
706
int row, int /* column */, const QModelIndex &parent)
709
if (!parent.isValid() || isReadOnly())
712
QDirModelPrivate::QDirNode *p =
713
static_cast<QDirModelPrivate::QDirNode*>(parent.internalPointer());
717
QString to = filePath(parent) + QDir::separator();
719
QList<QUrl> urls = data->urls();
720
QList<QUrl>::const_iterator it = urls.begin();
722
int last = row + urls.count() - 1;
723
beginInsertRows(parent, row, last);
727
for (; it != urls.end(); ++it) {
728
QString path = (*it).toLocalFile();
729
success = QFile::copy(path, to + QFileInfo(path).fileName()) && success;
733
for (; it != urls.end(); ++it) {
734
QString path = (*it).toLocalFile();
735
success = QFile::link(path, to + QFileInfo(path).fileName()) && success;
739
for (; it != urls.end(); ++it) {
740
QString path = (*it).toLocalFile();
741
success = QFile::copy(path, to + QFileInfo(path).fileName())
742
&& QFile::remove(path) && success;
756
Returns the drop actions supported by this model.
761
Qt::DropActions QDirModel::supportedDropActions() const
763
return Qt::CopyAction | Qt::MoveAction; // FIXME: LinkAction is not supported yet
767
Sets the \a provider of file icons for the directory model.
771
void QDirModel::setIconProvider(QFileIconProvider *provider)
774
d->iconProvider = provider;
778
Returns the file icon provider for this directory model.
781
QFileIconProvider *QDirModel::iconProvider() const
783
Q_D(const QDirModel);
784
return d->iconProvider;
788
Sets the name \a filters for the directory model.
791
void QDirModel::setNameFilters(const QStringList &filters)
795
d->savePersistentIndexes();
796
beginRemoveRows(QModelIndex(), 0, rowCount(QModelIndex()) - 1);
798
d->nameFilters = filters;
799
d->clear(&d->root); // clear model
802
d->restorePersistentIndexes();
806
Returns a list of filters applied to the names in the model.
809
QStringList QDirModel::nameFilters() const
811
Q_D(const QDirModel);
812
return d->nameFilters;
816
Sets the directory model's filter to that specified by \a filters.
821
void QDirModel::setFilter(QDir::Filters filters)
825
d->savePersistentIndexes();
826
beginRemoveRows(QModelIndex(), 0, rowCount(QModelIndex()) - 1);
828
d->filters = filters;
829
d->clear(&d->root); // clear model
832
d->restorePersistentIndexes();
836
Returns the filter specification for the directory model.
841
QDir::Filters QDirModel::filter() const
843
Q_D(const QDirModel);
848
Sets the directory model's sorting order to that specified by \a sort.
853
void QDirModel::setSorting(QDir::SortFlags sort)
857
d->savePersistentIndexes();
858
beginRemoveRows(QModelIndex(), 0, rowCount(QModelIndex()) - 1);
861
d->clear(&d->root); // clear model
864
d->restorePersistentIndexes();
868
Returns the sorting method used for the directory model.
870
\sa QDir::SortFlags */
872
QDir::SortFlags QDirModel::sorting() const
874
Q_D(const QDirModel);
879
\property QDirModel::resolveSymlinks
880
\brief Whether the directory model should resolve symbolic links
882
This is only relevant on operating systems that support symbolic
885
void QDirModel::setResolveSymlinks(bool enable)
888
d->resolveSymlinks = enable;
891
bool QDirModel::resolveSymlinks() const
893
Q_D(const QDirModel);
894
return d->resolveSymlinks;
898
\property QDirModel::readOnly
899
\brief Whether the directory model allows writing to the file system
901
If this property is set to false, the directory model will allow renaming, copying
902
and deleting of files and directories.
904
This property is true by default
907
void QDirModel::setReadOnly(bool enable)
910
d->readOnly = enable;
913
bool QDirModel::isReadOnly() const
915
Q_D(const QDirModel);
920
\property QDirModel::lazyChildCount
921
\brief Whether the directory model optimizes the hasChildren function
922
to only check if the item is a directory.
924
If this property is set to true, the directory model will make sure that a directory
925
actually containes any files before reporting that it has children.
926
Otherwise the directory model will report that an item has children if the item
929
This property is false by default
932
void QDirModel::setLazyChildCount(bool enable)
935
d->lazyChildCount = enable;
938
bool QDirModel::lazyChildCount() const
940
Q_D(const QDirModel);
941
return d->lazyChildCount;
945
Refreshes (rereads) the children of \a parent.
948
void QDirModel::refresh(const QModelIndex &parent)
952
QDirModelPrivate::QDirNode *p =
953
static_cast<QDirModelPrivate::QDirNode*>(parent.internalPointer());
954
QDirModelPrivate::QDirNode *n = (p ? p : &(d->root));
956
d->savePersistentIndexes();
957
beginRemoveRows(parent, 0, n->children.count() - 1);
959
d->refresh(p); // if (p == 0) it reads the drives
962
d->restorePersistentIndexes();
968
Returns the model item index for the given \a path.
971
QModelIndex QDirModel::index(const QString &path, int column) const
973
Q_D(const QDirModel);
975
if (path.isEmpty() || path == QObject::tr("My Computer"))
976
return QModelIndex();
978
QString absolutePath = QDir(path).absolutePath();
979
QStringList pathElements = absolutePath.split(QChar('/'), QString::SkipEmptyParts);
980
if ((pathElements.isEmpty() || !QFileInfo(path).exists())
985
return QModelIndex();
987
QModelIndex idx; // start with "My Computer"
988
if (!d->root.populated) // make sure the root is populated
989
d->populate(&d->root);
992
if (absolutePath.startsWith("//")) { // UNC path
993
QString host = pathElements.first();
995
for (; r < d->root.children.count(); ++r) {
996
if (d->root.children.at(r).info.fileName() == host)
999
if (r >= d->root.children.count()) {
1000
QFileInfo info("//" + host);
1001
QDirModelPrivate::QDirNode node;
1004
node.populated = false;
1005
#ifdef Q_DIRMODEL_CACHED
1006
node.cached_size = info.size();
1007
node.cached_modified = info.lastModified();
1009
d->root.children.append(node);
1011
idx = index(r, 0, QModelIndex());
1012
pathElements.pop_front();
1013
} else if (pathElements.at(0).endsWith(":")) {
1014
pathElements[0] += "/";
1017
// add the "/" item, since it is a valid path element on unix
1018
pathElements.prepend("/");
1020
for (int i = 0; i < pathElements.count(); ++i) {
1021
QStringList entries;
1022
Q_ASSERT(!pathElements.at(i).isEmpty()); // we don't allow empty elements
1023
// get the list of children of the current path element
1024
if (idx.isValid()) {
1025
QDirModelPrivate::QDirNode *node =
1026
static_cast<QDirModelPrivate::QDirNode*>(idx.internalPointer());
1028
entries = d->entryList(node->info.absoluteFilePath());
1029
} else { // parent is "My Computer"
1030
for (int j = 0; j < d->root.children.count(); ++j)
1031
entries << QDir::cleanPath(d->root.children.at(j).info.absoluteFilePath());
1034
// find the row of the current path element in the list of children
1035
int row = entries.indexOf(pathElements.at(i));
1036
idx = index(row, column, idx); // will check row and lazily populate
1037
// hit an invalid element (could be hidden or just not found)
1038
if (!idx.isValid()) {
1039
qWarning() << "The file or directory" << pathElements.at(i)
1040
<< "in the path" << path << "could not be found.";
1041
break; // return an invalid index
1049
Returns true if the model item \a index represents a directory;
1050
otherwise returns false.
1053
bool QDirModel::isDir(const QModelIndex &index) const
1055
Q_ASSERT(index.isValid());
1056
QDirModelPrivate::QDirNode *node =
1057
static_cast<QDirModelPrivate::QDirNode*>(index.internalPointer());
1059
return node->info.isDir();
1063
Create a directory with the \a name in the \a parent model item.
1066
QModelIndex QDirModel::mkdir(const QModelIndex &parent, const QString &name)
1069
if (!parent.isValid())
1070
return QModelIndex();
1072
QDirModelPrivate::QDirNode *p =
1073
static_cast<QDirModelPrivate::QDirNode*>(parent.internalPointer());
1075
QString path = p->info.absoluteFilePath();
1076
// For the indexOf() method to work, the new directory has to be a direct child of
1077
// the parent directory.
1081
if (newDir.isRelative())
1082
newDir = QDir(path + "/" + name);
1083
QString childName = newDir.dirName(); // Get the singular name of the directory
1086
if (newDir.absolutePath() != dir.absolutePath() || !dir.mkdir(name))
1087
return QModelIndex(); // nothing happened
1091
QStringList entryList = d->entryList(path);
1092
int r = entryList.indexOf(childName);
1093
QModelIndex i = index(r, 0, parent); // return an invalid index
1099
Removes the directory corresponding to the model item \a index in the
1100
directory model, returning true if successful. If the directory
1101
cannot be removed, false is returned.
1105
bool QDirModel::rmdir(const QModelIndex &index)
1107
if (!index.isValid())
1110
QDirModelPrivate::QDirNode *n =
1111
static_cast<QDirModelPrivate::QDirNode*>(index.internalPointer());
1114
if (!n->info.isDir()) {
1115
qWarning("rmdir: the node is not a directory");
1119
QModelIndex par = parent(index);
1120
QDirModelPrivate::QDirNode *p =
1121
static_cast<QDirModelPrivate::QDirNode*>(par.internalPointer());
1124
QDir dir = p->info.dir(); // parent dir
1125
QString path = n->info.absoluteFilePath();
1126
if (!dir.rmdir(path))
1135
Removes the model item \a index from the directory model, returning
1136
true if successful. If the item cannot be removed, false is returned.
1140
bool QDirModel::remove(const QModelIndex &index)
1142
if (!index.isValid())
1145
QDirModelPrivate::QDirNode *n =
1146
static_cast<QDirModelPrivate::QDirNode*>(index.internalPointer());
1149
if (n->info.isDir())
1152
QModelIndex par = parent(index);
1153
QDirModelPrivate::QDirNode *p =
1154
static_cast<QDirModelPrivate::QDirNode*>(par.internalPointer());
1157
QDir dir = p->info.dir(); // parent dir
1158
QString path = n->info.absoluteFilePath();
1159
if (!dir.remove(path))
1168
Returns the path of the item stored in the model under the
1173
QString QDirModel::filePath(const QModelIndex &index) const
1175
Q_D(const QDirModel);
1176
if (index.isValid()) {
1177
QFileInfo fi = fileInfo(index);
1178
if (d->resolveSymlinks && fi.isSymLink()) {
1179
QString link = fi.readLink();
1180
if (link.at(link.size() - 1) == QDir::separator())
1182
return QDir::cleanPath(link);
1184
return QDir::cleanPath(fi.absoluteFilePath());
1186
return QString(); // root path
1190
Returns the name of the item stored in the model under the
1195
QString QDirModel::fileName(const QModelIndex &index) const
1197
if (!index.isValid())
1198
return QObject::tr("My Computer");
1199
QFileInfo info = fileInfo(index);
1201
return info.absoluteFilePath();
1202
return info.fileName();
1206
Returns the icons for the item stored in the model under the given
1210
QIcon QDirModel::fileIcon(const QModelIndex &index) const
1212
Q_D(const QDirModel);
1213
if (!index.isValid())
1214
return d->rootIcon();
1215
return d->iconProvider->icon(fileInfo(index));
1219
Returns the file information for the model item \a index.
1223
QFileInfo QDirModel::fileInfo(const QModelIndex &index) const
1225
Q_ASSERT(index.isValid());
1227
QDirModelPrivate::QDirNode *node =
1228
static_cast<QDirModelPrivate::QDirNode*>(index.internalPointer());
1235
The root node is never seen outside the model.
1238
void QDirModelPrivate::init()
1240
filters = QDir::TypeMask;
1244
root.info = QFileInfo();
1248
QDirModelPrivate::QDirNode *QDirModelPrivate::node(int row, QDirNode *parent) const
1253
bool isDir = !parent || parent->info.isDir();
1254
QDirNode *p = (parent ? parent : &root);
1255
if (isDir && !p->populated)
1256
populate(p); // will also resolve symlinks
1258
if (row >= p->children.count()) {
1259
qWarning("node: the row does not exist");
1263
return const_cast<QDirNode*>(&p->children.at(row));
1266
QDirModelPrivate::QDirNode *QDirModelPrivate::parent(QDirNode *child) const
1268
return child ? child->parent : 0;
1271
QVector<QDirModelPrivate::QDirNode> QDirModelPrivate::children(QDirNode *parent) const
1275
if (parent == &root) {
1277
info = QDir::drives();
1278
} else if (parent->info.isDir()) {
1279
if (resolveSymlinks && parent->info.isSymLink()) {
1280
QString link = parent->info.readLink();
1281
if (link.at(link.size() - 1) == QDir::separator())
1283
info = entryInfoList(link);
1285
info = entryInfoList(parent->info.filePath());
1289
QVector<QDirNode> nodes(info.count());
1290
for (int i = 0; i < info.count(); ++i) {
1291
nodes[i].parent = parent;
1292
nodes[i].info = info.at(i);
1293
nodes[i].populated = false;
1294
#ifdef Q_DIRMODEL_CACHED
1295
nodes[i].cached_size = info.at(i).size();
1296
nodes[i].cached_modified = info.at(i).lastModified();
1303
int QDirModelPrivate::idx(QDirNode *node) const
1310
const QVector<QDirNode> children = node->parent ? node->parent->children : root.children;
1311
Q_ASSERT(children.count() > 0);
1313
const QDirNode *first = &(children.at(0));
1314
return (node - first);
1317
void QDirModelPrivate::refresh(QDirNode *parent)
1321
info = QDir::drives();
1322
else if (parent->info.isDir())
1323
info = entryInfoList(parent->info.filePath());
1325
QVector<QDirNode> *nodes = parent ? &(parent->children) : &(root.children);
1326
if (nodes->count() != info.count())
1327
nodes->resize(info.count());
1329
for (int i = 0; i < (int)info.count(); ++i) {
1330
(*nodes)[i].parent = parent;
1331
if (resolveSymlinks && info.at(i).isSymLink()) {
1332
QString link = info.at(i).readLink();
1333
if (link.at(link.size() - 1) == QDir::separator())
1335
(*nodes)[i].info = QFileInfo(link);
1337
(*nodes)[i].info = info.at(i);
1339
if (nodes->at(i).children.count() > 0)
1340
refresh(&(*nodes)[i]);
1344
void QDirModelPrivate::savePersistentIndexes()
1348
const QList<QPersistentModelIndexData*> indexes = persistent.indexes;
1349
for (int i = 0; i < indexes.count(); ++i) {
1350
QModelIndex idx = indexes.at(i)->index;
1351
QString path = q->filePath(idx);
1352
saved.append(qMakePair(path, idx.column()));
1353
persistent.indexes.at(i)->ref.ref(); // save
1354
persistent.indexes[i]->index = QModelIndex(); // invalidated
1358
void QDirModelPrivate::restorePersistentIndexes()
1361
const QList<QPersistentModelIndexData*> indexes = persistent.indexes;
1362
QList<QPersistentModelIndexData*> deleteList;
1363
for (int i = 0; i < indexes.count(); ++i) {
1364
persistent.indexes[i]->index = q->index(saved.at(i).first, saved.at(i).second);
1365
if (!persistent.indexes.at(i)->ref.deref()) // if we have no other references
1366
deleteList.append(indexes.at(i)); // make sure we delete it
1369
while (!deleteList.isEmpty()) {
1370
QPersistentModelIndexData::destroy(deleteList.last());
1371
deleteList.removeLast();