📄 qdirmodel.cpp
字号:
/*! \overload Returns the model item index for the given \a path.*/QModelIndex QDirModel::index(const QString &path, int column) const{ Q_D(const QDirModel); if (path.isEmpty() || path == QCoreApplication::translate("QFileDialog", "My Computer")) return QModelIndex(); QString absolutePath = QDir(path).absolutePath();#ifdef Q_OS_WIN absolutePath = absolutePath.toLower(); // On Windows, "filename......." and "filename" are equivalent if (absolutePath.endsWith(QLatin1Char('.'))) { int i; for (i = absolutePath.count() - 1; i >= 0; --i) { if (absolutePath.at(i) != QLatin1Char('.')) break; } absolutePath = absolutePath.left(i+1); }#endif QStringList pathElements = absolutePath.split(QChar('/'), QString::SkipEmptyParts); if ((pathElements.isEmpty() || !QFileInfo(path).exists())#ifndef Q_OS_WIN && path != QLatin1String("/")#endif ) return QModelIndex(); QModelIndex idx; // start with "My Computer" if (!d->root.populated) // make sure the root is populated d->populate(&d->root);#ifdef Q_OS_WIN if (absolutePath.startsWith(QLatin1String("//"))) { // UNC path QString host = pathElements.first(); int r = 0; for (; r < d->root.children.count(); ++r) if (d->root.children.at(r).info.fileName() == host) break; if (r >= d->root.children.count() && d->allowAppendChild) d->appendChild(&d->root, QLatin1String("//") + host); idx = index(r, 0, QModelIndex()); pathElements.pop_front(); } else if (pathElements.at(0).endsWith(QLatin1Char(':'))) { pathElements[0] += QLatin1Char('/'); }#else // add the "/" item, since it is a valid path element on unix pathElements.prepend(QLatin1String("/"));#endif for (int i = 0; i < pathElements.count(); ++i) { Q_ASSERT(!pathElements.at(i).isEmpty()); QString element = pathElements.at(i); QDirModelPrivate::QDirNode *parent = (idx.isValid() ? d->node(idx) : &d->root); Q_ASSERT(parent); if (!parent->populated) d->populate(parent); // search for the element in the child nodes first int row = -1; for (int j = parent->children.count() - 1; j >= 0; --j) { const QFileInfo& fi = parent->children.at(j).info; QString childFileName;#ifdef Q_OS_WIN childFileName = idx.isValid() ? fi.fileName() : fi.absoluteFilePath(); childFileName = childFileName.toLower();#else childFileName = idx.isValid() ? fi.fileName() : fi.absoluteFilePath();#endif if (childFileName == element) { if (i == pathElements.count() - 1) parent->children[j].stat = true; row = j; break; } } // we couldn't find the path element, we create a new node since we _know_ that the path is valid if (row == -1) { QString newPath = parent->info.absoluteFilePath() + "/" + element; if (!d->allowAppendChild || !QFileInfo(newPath).isDir()) return QModelIndex(); d->appendChild(parent, newPath); row = parent->children.count() - 1; if (i == pathElements.count() - 1) // always stat children of the last element parent->children[row].stat = true; emit const_cast<QDirModel*>(this)->layoutChanged(); } Q_ASSERT(row >= 0); idx = createIndex(row, 0, static_cast<void*>(&parent->children[row])); Q_ASSERT(idx.isValid()); } if (column != 0) return idx.sibling(idx.row(), column); return idx;}/*! Returns true if the model item \a index represents a directory; otherwise returns false.*/bool QDirModel::isDir(const QModelIndex &index) const{ Q_D(const QDirModel); Q_ASSERT(index.isValid()); QDirModelPrivate::QDirNode *node = d->node(index); return node->info.isDir();}/*! Create a directory with the \a name in the \a parent model item.*/QModelIndex QDirModel::mkdir(const QModelIndex &parent, const QString &name){ Q_D(QDirModel); if (!parent.isValid() || isReadOnly()) return QModelIndex(); QDirModelPrivate::QDirNode *p = d->node(parent); QString path = p->info.absoluteFilePath(); // For the indexOf() method to work, the new directory has to be a direct child of // the parent directory. QDir newDir(name); QDir dir(path); if (newDir.isRelative()) newDir = QDir(path + QLatin1Char('/') + name); QString childName = newDir.dirName(); // Get the singular name of the directory newDir.cdUp(); if (newDir.absolutePath() != dir.absolutePath() || !dir.mkdir(name)) return QModelIndex(); // nothing happened refresh(parent); QStringList entryList = d->entryList(path); int r = entryList.indexOf(childName); QModelIndex i = index(r, 0, parent); // return an invalid index return i;}/*! Removes the directory corresponding to the model item \a index in the directory model, returning true if successful. If the directory cannot be removed, false is returned.*/bool QDirModel::rmdir(const QModelIndex &index){ if (!index.isValid() || isReadOnly()) return false; QDirModelPrivate::QDirNode *n = d_func()->node(index); if (!n->info.isDir()) { qWarning("rmdir: the node is not a directory"); return false; } QModelIndex par = parent(index); QDirModelPrivate::QDirNode *p = d_func()->node(par); QDir dir = p->info.dir(); // parent dir QString path = n->info.absoluteFilePath(); if (!dir.rmdir(path)) return false; refresh(par); return true;}/*! Removes the model item \a index from the directory model, returning true if successful. If the item cannot be removed, false is returned.*/bool QDirModel::remove(const QModelIndex &index){ if (!index.isValid() || isReadOnly()) return false; QDirModelPrivate::QDirNode *n = d_func()->node(index); if (n->info.isDir()) return false; QModelIndex par = parent(index); QDirModelPrivate::QDirNode *p = d_func()->node(par); QDir dir = p->info.dir(); // parent dir QString path = n->info.absoluteFilePath(); if (!dir.remove(path)) return false; refresh(par); return true;}/*! Returns the path of the item stored in the model under the \a index given.*/QString QDirModel::filePath(const QModelIndex &index) const{ Q_D(const QDirModel); if (index.isValid()) { QFileInfo fi = fileInfo(index); if (d->resolveSymlinks && fi.isSymLink()) fi = d->resolvedInfo(fi); return QDir::cleanPath(fi.absoluteFilePath()); } return QString(); // root path}/*! Returns the name of the item stored in the model under the \a index given.*/QString QDirModel::fileName(const QModelIndex &index) const{ Q_D(const QDirModel); if (!index.isValid()) return QString(); QFileInfo info = fileInfo(index); if (info.isRoot()) return info.absoluteFilePath(); if (d->resolveSymlinks && info.isSymLink()) info = d->resolvedInfo(info); return info.fileName();}/*! Returns the icons for the item stored in the model under the given \a index.*/QIcon QDirModel::fileIcon(const QModelIndex &index) const{ Q_D(const QDirModel); if (!index.isValid()) return d->iconProvider->icon(QFileIconProvider::Computer); QDirModelPrivate::QDirNode *node = d->node(index); if (node->icon.isNull()) node->icon = d->iconProvider->icon(node->info); return node->icon;}/*! Returns the file information for the model item \a index.*/QFileInfo QDirModel::fileInfo(const QModelIndex &index) const{ Q_ASSERT(index.isValid()); QDirModelPrivate::QDirNode *node = d_func()->node(index); return node->info;}/* The root node is never seen outside the model.*/void QDirModelPrivate::init(){ filters = QDir::AllEntries; sort = QDir::Name; nameFilters << QLatin1String("*"); root.parent = 0; root.info = QFileInfo(); clear(&root);}QDirModelPrivate::QDirNode *QDirModelPrivate::node(int row, QDirNode *parent) const{ if (row < 0) return 0; bool isDir = !parent || parent->info.isDir(); QDirNode *p = (parent ? parent : &root); if (isDir && !p->populated) populate(p); // will also resolve symlinks if (row >= p->children.count()) { qWarning("node: the row does not exist"); return 0; } return const_cast<QDirNode*>(&p->children.at(row));}QVector<QDirModelPrivate::QDirNode> QDirModelPrivate::children(QDirNode *parent, bool stat) const{ Q_ASSERT(parent); QFileInfoList infoList; if (parent == &root) { parent = 0; infoList = QDir::drives(); } else if (parent->info.isDir()) { if (parent->info.isSymLink()) { QString link = parent->info.readLink(); if (link.size() > 1 && link.at(link.size() - 1) == QDir::separator()) link.chop(1); if (stat) infoList = entryInfoList(link); else infoList = QDir(link).entryInfoList(nameFilters, QDir::AllEntries | QDir::System); } else { if (stat) infoList = entryInfoList(parent->info.absoluteFilePath()); else infoList = QDir(parent->info.absoluteFilePath()).entryInfoList(nameFilters, QDir::AllEntries | QDir::System); } } QVector<QDirNode> nodes(infoList.count()); for (int i = 0; i < infoList.count(); ++i) { QDirNode &node = nodes[i]; node.parent = parent; node.info = infoList.at(i); node.populated = false; node.stat = shouldStat; } return nodes;}void QDirModelPrivate::_q_refresh(){ Q_Q(QDirModel); q->refresh(toBeRefreshed); toBeRefreshed = QModelIndex();}void QDirModelPrivate::savePersistentIndexes(){ Q_Q(QDirModel); savedPaths.clear(); const QList<QPersistentModelIndexData*> indexes = persistent.indexes; for (int i = 0; i < indexes.count(); ++i) { QModelIndex idx = indexes.at(i)->index; QString path = q->filePath(idx); savedPaths.append(qMakePair(path, idx.column())); savedPersistentIndexes.append(idx); // make sure the ref >= 1 }}void QDirModelPrivate::restorePersistentIndexes(){ Q_Q(QDirModel); bool allow = allowAppendChild; allowAppendChild = false; for (int i = 0; i < persistent.indexes.count(); ++i) { QModelIndex index; if (i < savedPaths.count()) index = q->index(savedPaths.at(i).first, savedPaths.at(i).second); persistent.indexes.at(i)->index = index; } savedPersistentIndexes.clear(); savedPaths.clear(); allowAppendChild = allow;}QFileInfoList QDirModelPrivate::entryInfoList(const QString &path) const{ const QDir dir(path); return dir.entryInfoList(nameFilters, filters | QDir::NoDotAndDotDot, sort);}QStringList QDirModelPrivate::entryList(const QString &path) const{ const QDir dir(path); return dir.entryList(nameFilters, filters | QDir::NoDotAndDotDot, sort);}QString QDirModelPrivate::name(const QModelIndex &index) const{ const QDirNode *n = node(index); const QFileInfo info = n->info; if (info.isRoot()) { QString name = info.absoluteFilePath();#ifdef Q_OS_WIN if (name.startsWith(QLatin1Char('/'))) // UNC host return info.fileName(); if (name.endsWith(QLatin1Char('/'))) name.chop(1);#endif return name; } return info.fileName();}QString QDirModelPrivate::size(const QModelIndex &index) const{ quint64 bytes = node(index)->info.size(); if (bytes >= 1000000000) return QLocale().toString(bytes / 1000000000) + QString(" GB"); if (bytes >= 1000000) return QLocale().toString(bytes / 1000000) + QString(" MB"); if (bytes >= 1000) return QLocale().toString(bytes / 1000) + QString(" KB"); return QLocale().toString(bytes) + QString(" bytes");}QString QDirModelPrivate::type(const QModelIndex &index) const{ return iconProvider->type(node(index)->info);}QString QDirModelPrivate::time(const QModelIndex &index) const{#ifndef QT_NO_DATESTRING return node(index)->info.lastModified().toString("yyyy-MM-dd hh:mm:ss");#else Q_UNUSED(index); return QString();#endif}void QDirModelPrivate::appendChild(QDirModelPrivate::QDirNode *parent, const QString &path) const{ QDirModelPrivate::QDirNode node; node.populated = false; node.stat = shouldStat; node.parent = (parent == &root ? 0 : parent); node.info = QFileInfo(path); node.info.setCaching(true); // The following append(node) may reallocate the vector, thus // we need to update the pointers to the childnodes parent. QDirModelPrivate *that = const_cast<QDirModelPrivate *>(this); that->savePersistentIndexes(); parent->children.append(node); for (int i = 0; i < parent->children.count(); ++i) { QDirNode *childNode = &parent->children[i]; for (int j = 0; j < childNode->children.count(); ++j) childNode->children[j].parent = childNode; } that->restorePersistentIndexes();}QFileInfo QDirModelPrivate::resolvedInfo(QFileInfo info){#ifdef Q_OS_WIN // On windows, we cannot create a shortcut to a shortcut. return QFileInfo(info.readLink());#else QStringList paths; do { QFileInfo link(info.readLink()); if (link.isRelative()) info.setFile(info.absolutePath(), link.filePath()); else info = link; if (paths.contains(info.absoluteFilePath())) return QFileInfo(); paths.append(info.absoluteFilePath()); } while (info.isSymLink()); return info;#endif}#include "moc_qdirmodel.cpp"#endif // QT_NO_DIRMODEL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -