📄 qfilesystemmodel.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qfilesystemmodel_p.h"#include <qlocale.h>#include <qmime.h>#include <qurl.h>#include <qdebug.h>#include <qmessagebox.h>#ifndef QT_NO_FILESYSTEMWATCHER/*! \enum QFileSystemModel::Roles \value FileIconRole \value FilePathRole \value FileNameRole*/QFileSystemModel::QFileSystemModel(QObject *parent) : QAbstractItemModel(*new QFileSystemModelPrivate, parent){ Q_D(QFileSystemModel); d->init();}QFileSystemModel::QFileSystemModel(QFileSystemModelPrivate &dd, QObject *parent) : QAbstractItemModel(dd, parent){ Q_D(QFileSystemModel); d->init();}QFileSystemModel::~QFileSystemModel(){}/*! \reimp*/QModelIndex QFileSystemModel::index(int row, int column, const QModelIndex &parent) const{ Q_D(const QFileSystemModel); if (!hasIndex(row, column, parent)) return QModelIndex(); // get the parent node QFileSystemModelPrivate::QFileSystemNode *parentNode = (d->indexValid(parent) ? d->node(parent) : const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&d->root)); Q_ASSERT(parentNode); // now get the internal pointer for the index int realRow = parentNode->visibleChildren[d->translateVisibleLocation(parentNode, row)]; const QFileSystemModelPrivate::QFileSystemNode *indexNode = &parentNode->children.at(realRow); Q_ASSERT(indexNode); return createIndex(row, column, const_cast<QFileSystemModelPrivate::QFileSystemNode*>(indexNode));}/*! \overload Returns the model item index for the given \a path.*/QModelIndex QFileSystemModel::index(const QString &path, int column) const{ Q_D(const QFileSystemModel); QFileSystemModelPrivate::QFileSystemNode *node = d->node(path, false); QModelIndex idx = d->index(node); if (idx.column() != column) idx = idx.sibling(idx.row(), column); return idx;}/*! \internal Return the QFileSystemNode that goes to index. */QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QModelIndex &index) const{ if (!index.isValid()) return const_cast<QFileSystemNode*>(&root); QFileSystemModelPrivate::QFileSystemNode *indexNode = static_cast<QFileSystemModelPrivate::QFileSystemNode*>(index.internalPointer()); Q_ASSERT(indexNode); return indexNode;}#ifdef Q_OS_WIN#include <windows.h>static QString qt_GetLongPathName(const QString &strShortPath){ QString longPath; int i = 0; if (strShortPath == QLatin1String(".")) return strShortPath; QString::const_iterator it = strShortPath.constBegin(); QString::const_iterator constEnd = strShortPath.constEnd(); do { bool isSep = (*it == QLatin1Char('\\') || *it == QLatin1Char('/')); if (isSep || it == constEnd) { QString section = (it == constEnd ? strShortPath : strShortPath.left(i)); // FindFirstFile does not handle volumes ("C:"), so we have to catch that ourselves. if (section.endsWith(QLatin1Char(':'))) { longPath.append(section); } else { HANDLE h; QT_WA({ WIN32_FIND_DATAW findData; h = ::FindFirstFileW((wchar_t *)section.utf16(), &findData); if (h != INVALID_HANDLE_VALUE) longPath.append(QString::fromUtf16((ushort*)findData.cFileName)); } , { WIN32_FIND_DATAA findData; h = ::FindFirstFileA(section.toLocal8Bit(), &findData); if (h != INVALID_HANDLE_VALUE) longPath.append(QString::fromLocal8Bit(findData.cFileName)); }); if (h == INVALID_HANDLE_VALUE) { longPath.append(section); break; } } if (it != constEnd) longPath.append(*it); else break; } ++it; if (isSep && it == constEnd) // break out if the last character is a separator break; ++i; } while (true); return longPath;}#endif/*! \internal Given a path return the matching QFileSystemNode or &root if invalid*/QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QString &path, bool fetch) const{ Q_Q(const QFileSystemModel); Q_UNUSED(q); if (path.isEmpty() || path == myComputer() || path.startsWith(QLatin1String(":"))) return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root); // Construct the nodes up to the new root path if they need to be built QString absolutePath;#ifdef Q_OS_WIN QString longPath = qt_GetLongPathName(path);#else QString longPath = path;#endif if (longPath == rootDir.path()) absolutePath = rootDir.absolutePath(); else absolutePath = QDir(longPath).absolutePath(); // ### TODO can we use bool QAbstractFileEngine::caseSensitive() const? QStringList pathElements = absolutePath.split(QLatin1Char('/'), QString::SkipEmptyParts); if ((pathElements.isEmpty())#ifndef Q_OS_WIN && longPath != QLatin1String("/")#endif ) return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root); QModelIndex index = QModelIndex(); // start with "My Computer"#ifdef Q_OS_WIN if (absolutePath.startsWith(QLatin1String("//"))) { // UNC path QString host = QLatin1String("\\\\") + pathElements.first(); int r = 0; for (; r < root.children.count(); ++r) if (root.children.at(r).fileName.toLower() == host.toLower()) break; QFileSystemModelPrivate::QFileSystemNode *rootNode = const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root); if (r >= root.children.count()) { if (pathElements.count() == 1 && !absolutePath.endsWith(QLatin1Char('/'))) return rootNode; QFileInfo info(host); if (!info.exists()) return rootNode; QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this); r = p->addNode(rootNode, host); p->addVisibleFiles(rootNode, QStringList(host)); } r = rootNode->visibleLocation(r); r = translateVisibleLocation(rootNode, r); index = q->index(r, 0, QModelIndex()); pathElements.pop_front(); } else { if (!pathElements.at(0).contains(QLatin1String(":"))) pathElements.prepend(QDir(longPath).rootPath()); if (pathElements.at(0).endsWith(QLatin1Char('/'))) pathElements[0].chop(1); }#else // add the "/" item, since it is a valid path element on Unix if (absolutePath[0] == QLatin1Char('/')) pathElements.prepend(QLatin1String("/"));#endif QFileSystemModelPrivate::QFileSystemNode *parent = node(index); for (int i = 0; i < pathElements.count(); ++i) { QString element = pathElements.at(i);#ifdef Q_OS_WIN // On Windows, "filename......." and "filename" are equivalent Task #133928 while (element.endsWith(QLatin1Char('.'))) element.chop(1);#endif int row = -1; if (parent->children.count() != 0) row = findChild(parent, QFileSystemNode(element)); // we couldn't find the path element, we create a new node since we // _know_ that the path is valid if (row != -1) { if ((parent->children.count() == 0) || (parent->caseSensitive() && parent->children[row].fileName != element) || (!parent->caseSensitive() && parent->children[row].fileName.toLower() != element.toLower())) row = -1; } bool alreadyExisted = (row != -1); if (row == -1) { // Someone might call ::index("file://cookie/monster/doesn't/like/veggies"), // a path that doesn't exists, I.E. don't blindly create directories. QFileInfo info(absolutePath); if (!info.exists()) return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root); QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this); row = p->addNode(parent, element);#ifdef QT_NO_FILESYSTEMWATCHER parent->children[row].populate(fileInfoGatherer.getInfo(info));#else parent->children[row].populate(fileInfoGatherer.getInfo(info));#endif } Q_ASSERT(row >= 0); if (parent->visibleLocation(row) == -1) { // It has been filtered out if (alreadyExisted && parent->children.at(row).hasInformation() && !fetch) return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root); QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this); p->addVisibleFiles(parent, QStringList(element)); if (!p->bypassFilters.contains(&parent->children.at(row))) p->bypassFilters.append(&parent->children.at(row)); QString dir = q->filePath(this->index(parent)); if (!parent->children.at(row).hasInformation() && fetch) { Fetching f; f.dir = dir; f.file = element; f.node = &parent->children.at(row); p->toFetch.append(f); p->fetchingTimer.start(0, const_cast<QFileSystemModel*>(q)); } } parent = &parent->children[row]; } return parent;}void QFileSystemModel::timerEvent(QTimerEvent *event){ Q_D(QFileSystemModel); if (event->timerId() == d->fetchingTimer.timerId()) { d->fetchingTimer.stop(); for (int i = 0; i < d->toFetch.count(); ++i) { const QFileSystemModelPrivate::QFileSystemNode *node = d->toFetch.at(i).node; if (!node->hasInformation()) { d->fileInfoGatherer.fetchExtendedInformation(d->toFetch.at(i).dir, QStringList(d->toFetch.at(i).file)); } else { // qDebug() << "yah!, you saved a little gerbil soul"; } } d->toFetch.clear(); }}/*! Returns true if the model item \a index represents a directory; otherwise returns false.*/bool QFileSystemModel::isDir(const QModelIndex &index) const{ // This function is for public usage only because it could create a file info Q_D(const QFileSystemModel); if (!index.isValid()) return true; QFileSystemModelPrivate::QFileSystemNode *n = d->node(index); if (n->hasInformation()) return n->isDir(); return fileInfo(index).isDir();}qint64 QFileSystemModel::size(const QModelIndex &index) const{ Q_D(const QFileSystemModel); if (!index.isValid()) return 0; return d->node(index)->size();}QString QFileSystemModel::type(const QModelIndex &index) const{ Q_D(const QFileSystemModel); if (!index.isValid()) return QString(); return d->node(index)->type();}QDateTime QFileSystemModel::lastModified(const QModelIndex &index) const{ Q_D(const QFileSystemModel); if (!index.isValid()) return QDateTime(); return d->node(index)->lastModified();}/*! \reimp*/QModelIndex QFileSystemModel::parent(const QModelIndex &index) const{ Q_D(const QFileSystemModel); if (!d->indexValid(index)) return QModelIndex(); QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(index); Q_ASSERT(indexNode != 0); QFileSystemModelPrivate::QFileSystemNode *parentNode = (indexNode ? indexNode->parent : 0); if (parentNode == 0 || parentNode == &d->root) return QModelIndex(); // get the parent's row QFileSystemModelPrivate::QFileSystemNode *grandParentNode = parentNode->parent; int realRow = d->findChild(grandParentNode, *parentNode); Q_ASSERT(realRow >= 0); int visualRow = d->translateVisibleLocation(grandParentNode, grandParentNode->visibleLocation(realRow)); if (visualRow == -1) return QModelIndex(); return createIndex(visualRow, 0, parentNode);}/* \internal return the index for node*/QModelIndex QFileSystemModelPrivate::index(const QFileSystemModelPrivate::QFileSystemNode *node) const{ Q_Q(const QFileSystemModel); QFileSystemModelPrivate::QFileSystemNode *parentNode = (node ? node->parent : 0); if (node == &root) return QModelIndex(); // get the parent's row int realRow = findChild(parentNode, *node); Q_ASSERT(realRow >= 0); int visualRow = translateVisibleLocation(parentNode, parentNode->visibleLocation(realRow)); if (visualRow == -1) return QModelIndex(); return q->createIndex(visualRow, 0, const_cast<QFileSystemNode*>(node));}/*! \reimp*/bool QFileSystemModel::hasChildren(const QModelIndex &parent) const{ Q_D(const QFileSystemModel); if (parent.column() > 0) return false; if (!parent.isValid()) // drives return true; const QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent); Q_ASSERT(indexNode); return (indexNode->isDir());}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -