📄 qfilesystemmodel.cpp
字号:
}bool QFileSystemModel::isReadOnly() const{ Q_D(const QFileSystemModel); return d->readOnly;}/*! \property QFileSystemModel::nameFilterDisables \brief Whether files that don't pass the name filter are hidden or disabled This property is true by default*/void QFileSystemModel::setNameFilterDisables(bool enable){ Q_D(QFileSystemModel); if (d->nameFilterDisables == enable) return; d->nameFilterDisables = enable; d->forceSort = true; d->delayedSort();}bool QFileSystemModel::nameFilterDisables() const{ Q_D(const QFileSystemModel); return d->nameFilterDisables;}/*! Sets the name \a filters to apply against the existing files.*/void QFileSystemModel::setNameFilters(const QStringList &filters){ // Prep the regexp's ahead of time#ifndef QT_NO_REGEXP Q_D(QFileSystemModel); d->nameFilters.clear(); const Qt::CaseSensitivity caseSensitive = (filter() & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive; for (int i = 0; i < filters.size(); ++i) { d->nameFilters << QRegExp(filters.at(i), caseSensitive, QRegExp::Wildcard); } d->forceSort = true; d->delayedSort();#endif}/*! Returns a list of filters applied to the names in the model.*/QStringList QFileSystemModel::nameFilters() const{ Q_D(const QFileSystemModel); QStringList filters;#ifndef QT_NO_REGEXP for (int i = 0; i < d->nameFilters.size(); ++i) { filters << d->nameFilters.at(i).pattern(); }#endif return filters;}/*! \internal Performed quick listing and see if any files have been added or removed, then fetch more information on visible files. */void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, const QStringList &files){ QFileSystemModelPrivate::QFileSystemNode *parentNode = node(directory, false); QStringList newFiles = files; // sort new files for faster inserting qSort(newFiles.begin(), newFiles.end()); // Ignore files we already have and cleanup filtered files that were removed. // non-filtered files will be removed in a fileSystemChanged() for (int i = parentNode->children.count() - 1; i >= 0; --i) { QStringList::const_iterator iterator; iterator = qBinaryFind(newFiles.begin(), newFiles.end(), parentNode->children.at(i).fileName); if (iterator == newFiles.constEnd()) { removeNode(parentNode, i); } }}/*! \internal Adds a new file to the children of parentNode *WARNING* this will change the count of children*/int QFileSystemModelPrivate::addNode(QFileSystemNode *parentNode, const QString &fileName){ // In the common case, itemLocation == count() so check there first QFileSystemModelPrivate::QFileSystemNode node(fileName, parentNode); int itemLocation = 0; if (parentNode->children.count() > 0) { if (parentNode->children.at(parentNode->children.count() - 1).hasInformation() && parentNode->children.at(parentNode->children.count() - 1) < fileName) { itemLocation = parentNode->children.count(); } else { itemLocation = findWhereToInsertChild(parentNode, &node); } } parentNode->children.insert(itemLocation, node); for (int i = 0; i < parentNode->visibleChildren.count(); ++i) if (parentNode->visibleChildren.at(i) >= itemLocation) ++parentNode->visibleChildren[i]; return itemLocation;}/*! \internal File at parentNode->children(itemLocation) has been removed, remove from the lists and emit signals if necessary *WARNING* this will change the count of children and could change visibleChildren */void QFileSystemModelPrivate::removeNode(QFileSystemModelPrivate::QFileSystemNode *parentNode, int itemLocation){ Q_Q(QFileSystemModel); QModelIndex parent = index(parentNode); bool indexHidden = isHiddenByFilter(parentNode, parent); int vLocation = parentNode->visibleLocation(itemLocation); if (vLocation >= 0 && !indexHidden) q->beginRemoveRows(parent, translateVisibleLocation(parentNode, vLocation), translateVisibleLocation(parentNode, vLocation)); parentNode->children.removeAt(itemLocation); // cleanup sort files after removing rather then re-sorting which is O(n) if (vLocation >= 0) parentNode->visibleChildren.removeAt(vLocation); // update all the rest of the visible children for (int j = 0; j < parentNode->visibleChildren.count(); ++j) if (parentNode->visibleChildren.at(j) > itemLocation) --parentNode->visibleChildren[j]; if (vLocation >= 0 && !indexHidden) q->endRemoveRows();}/* \internal Helper functor used by addVisibleFiles()*/class QFileSystemModelVisibleFinder{public: inline QFileSystemModelVisibleFinder(QFileSystemModelPrivate::QFileSystemNode *node, QFileSystemModelSorter *sorter) : parentNode(node), sorter(sorter) {} bool operator()(const QString &, int r) const { return sorter->compareNodes(&(parentNode->children.at(location)), &(parentNode->children.at(r))); } int location;private: QFileSystemModelPrivate::QFileSystemNode *parentNode; QFileSystemModelSorter *sorter;};/*! \internal File at parentNode->children(itemLocation) was not visible before, but now should be and emit signals if necessary. *WARNING* this will change the visible count */void QFileSystemModelPrivate::addVisibleFiles(QFileSystemNode *parentNode, const QStringList &newFiles){ Q_Q(QFileSystemModel); QModelIndex parent = index(parentNode); bool indexHidden = isHiddenByFilter(parentNode, parent); QFileSystemModelSorter sorter(sortColumn); QFileSystemModelVisibleFinder vf(parentNode, &sorter); for (int i = 0; i < newFiles.count(); ++i) { QString newFile = newFiles.at(i); int location = findChild(parentNode, QFileSystemNode(newFile)); Q_ASSERT(location >= 0); vf.location = location; QList<int>::const_iterator iterator = qUpperBound(parentNode->visibleChildren.begin(), parentNode->visibleChildren.end(), newFile, vf); int realHome = (iterator - parentNode->visibleChildren.begin()); if (!indexHidden) q->beginInsertRows(parent, realHome, realHome); parentNode->visibleChildren.insert(realHome, location); if (!indexHidden) q->endInsertRows(); }}/*! \internal File was visible before, but now should NOT be *WARNING* this will change the visible count */void QFileSystemModelPrivate::removeVisibleFile(QFileSystemNode *parentNode, int vLocation){ Q_Q(QFileSystemModel); if (vLocation == -1) return; QModelIndex parent = index(parentNode); bool indexHidden = isHiddenByFilter(parentNode, parent); if (!indexHidden) q->beginRemoveRows(parent, translateVisibleLocation(parentNode, vLocation), translateVisibleLocation(parentNode, vLocation)); parentNode->visibleChildren.removeAt(vLocation); if (!indexHidden) q->endRemoveRows();}/*! \internal The thread has received new information about files, update and emit dataChanged if it has actually changed. */void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QList<QPair<QString, QFileInfo> > &updates){ Q_Q(QFileSystemModel); QVector<int> rowsToUpdate; QStringList newFiles; QFileSystemModelPrivate::QFileSystemNode *parentNode = node(path, false); QModelIndex parentIndex = index(parentNode); for (int i = 0; i < updates.count(); ++i) { QString fileName = updates.at(i).first; Q_ASSERT(!fileName.isEmpty()); QExtendedInformation info = fileInfoGatherer.getInfo(updates.at(i).second); int itemLocation = findChild(parentNode, QFileSystemNode(fileName)); if (itemLocation < 0) { itemLocation = addNode(parentNode, fileName); for (int i = 0; i < rowsToUpdate.count(); ++i) if (rowsToUpdate.at(i) >= itemLocation) ++rowsToUpdate[i]; } if (parentNode->caseSensitive()) { if (parentNode->children.at(itemLocation).fileName != fileName) continue; } else { if (parentNode->children.at(itemLocation).fileName.toLower() != fileName.toLower()) continue; } if (parentNode->caseSensitive()) { Q_ASSERT(parentNode->children.at(itemLocation).fileName == fileName); } else { parentNode->children[itemLocation].fileName = fileName; } if (info.size == -1) { removeNode(parentNode, itemLocation); continue; } if (parentNode->children.at(itemLocation) != info ) { parentNode->children[itemLocation].populate(info); int visibleLocation = parentNode->visibleLocation(itemLocation); bypassFilters.removeAll(&(parentNode->children.at(itemLocation))); // brand new information. if (filtersAcceptsNode(&(parentNode->children[itemLocation]))) { if (visibleLocation == -1) { newFiles.append(fileName); } else { rowsToUpdate.append(itemLocation); } } else { if (visibleLocation != -1) { removeVisibleFile(parentNode, visibleLocation); } else { // The file is not visible, don't do anything } } } } // bundle up all of the changed signals into as few as possible. qSort(rowsToUpdate.begin(), rowsToUpdate.end()); int min = -2; // ### TODO double check that -2 isn't needed int max = -2; for (int i = 0; i < rowsToUpdate.count(); ++i) { int value = rowsToUpdate.at(i); if (min == -2) { min = value; if (i != rowsToUpdate.count() - 1) continue; } if (i != rowsToUpdate.count() - 1) { if ((value == min + 1 && max == -2) || value == max + 1) { max = value; continue; } } int visibleMin = parentNode->visibleLocation(min); Q_ASSERT(parentNode->visibleChildren.at(visibleMin) == min); int visibleMax = max >= 0 ? parentNode->visibleLocation(max) : visibleMin; Q_ASSERT(visibleMin >= 0 && visibleMax >= 0); QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMin), 0, parentIndex); QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMax), 3, parentIndex); emit q->dataChanged(bottom, top); min = -2; max = -2; } if (newFiles.count() > 0) { addVisibleFiles(parentNode, newFiles); } if (sortColumn != 0 && rowsToUpdate.count() > 0) { forceSort = true; delayedSort(); }}/*! \internal*/void QFileSystemModelPrivate::_q_resolvedName(const QString &fileName, const QString &resolvedName){ resolvedSymLinks[fileName] = resolvedName;}/*! \internal*/void QFileSystemModelPrivate::init(){ Q_Q(QFileSystemModel); qRegisterMetaType<QList<QPair<QString,QFileInfo> > >("QList<QPair<QString,QFileInfo> >"); q->connect(&fileInfoGatherer, SIGNAL(newListOfFiles(const QString &, const QStringList &)), q, SLOT(_q_directoryChanged(const QString &, const QStringList &))); q->connect(&fileInfoGatherer, SIGNAL(updates(const QString &, const QList<QPair<QString, QFileInfo> > &)), q, SLOT(_q_fileSystemChanged(const QString &, const QList<QPair<QString, QFileInfo> > &))); q->connect(&fileInfoGatherer, SIGNAL(nameResolved(const QString &, const QString &)), q, SLOT(_q_resolvedName(const QString &, const QString &))); q->connect(&delayedSortTimer, SIGNAL(timeout()), q, SLOT(_q_performDelayedSort()), Qt::QueuedConnection);}/*! \internal Returns false if node doesn't pass the filters otherwise true QDir::Modified is not supported QDir::Drives is not supported*/bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) const{ // always accept drives if (node->parent == &root || bypassFilters.contains(node)) return true; // If we don't know anything yet don't accept it if (!node->hasInformation()) return false; const bool filterPermissions = ((filters & QDir::PermissionMask) && (filters & QDir::PermissionMask) != QDir::PermissionMask); const bool hideDirs = !(filters & (QDir::Dirs | QDir::AllDirs)); const bool hideFiles = !(filters & QDir::Files); const bool hideReadable = !(!filterPermissions || (filters & QDir::Readable)); const bool hideWritable = !(!filterPermissions || (filters & QDir::Writable)); const bool hideExecutable = !(!filterPermissions || (filters & QDir::Executable)); const bool hideHidden = !(filters & QDir::Hidden); const bool hideSystem = !(filters & QDir::System); const bool hideSymlinks = (filters & QDir::NoSymLinks); const bool hideDotAndDotDot = (filters & QDir::NoDotAndDotDot); // Note that we match the behavior of entryList and not QFileInfo on this and this // incompatibility won't be fixed until Qt 5 at least bool isDotOrDot = ( (node->fileName == QLatin1String(".") || node->fileName == QLatin1String(".."))); if ( (hideHidden && (!isDotOrDot && node->isHidden())) || (hideSystem && node->isSystem()) || (hideDirs && node->isDir()) || (hideFiles && node->isFile()) || (hideSymlinks && node->isSymLink()) || (hideReadable && node->isReadable()) || (hideWritable && node->isWritable()) || (hideExecutable && node->isExecutable()) || (hideDotAndDotDot && isDotOrDot)) return false; return nameFilterDisables || passNameFilters(node);}/* \internal Returns true if node passes the name filters and should be visible. */bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const{#ifndef QT_NO_REGEXP if (nameFilters.isEmpty()) return true; // Check the name regularexpression filters if (!(node->isDir() && (filters & QDir::AllDirs))) { for (int i = 0; i < nameFilters.size(); ++i) { if (nameFilters.at(i).exactMatch(node->fileName)) return true; } return false; }#endif return true;}//#include "moc_qfilesystemmodel.cpp"#endif // QT_NO_FILESYSTEMWATCHER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -