diff options
Diffstat (limited to 'src/widgets/dialogs/qfilesystemmodel.cpp')
-rw-r--r-- | src/widgets/dialogs/qfilesystemmodel.cpp | 160 |
1 files changed, 139 insertions, 21 deletions
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index e486037e08..a04189513a 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -57,6 +57,9 @@ #ifdef Q_OS_WIN # include <QtCore/QVarLengthArray> # include <qt_windows.h> +# ifndef Q_OS_WINRT +# include <shlobj.h> +# endif #endif QT_BEGIN_NAMESPACE @@ -227,11 +230,9 @@ bool QFileSystemModel::remove(const QModelIndex &aindex) /*! Constructs a file system model with the given \a parent. */ -QFileSystemModel::QFileSystemModel(QObject *parent) - : QAbstractItemModel(*new QFileSystemModelPrivate, parent) +QFileSystemModel::QFileSystemModel(QObject *parent) : + QFileSystemModel(*new QFileSystemModelPrivate, parent) { - Q_D(QFileSystemModel); - d->init(); } /*! @@ -247,9 +248,7 @@ QFileSystemModel::QFileSystemModel(QFileSystemModelPrivate &dd, QObject *parent) /*! Destroys this file system model. */ -QFileSystemModel::~QFileSystemModel() -{ -} +QFileSystemModel::~QFileSystemModel() = default; /*! \reimp @@ -841,8 +840,8 @@ QString QFileSystemModelPrivate::displayName(const QModelIndex &index) const { #if defined(Q_OS_WIN) QFileSystemNode *dirNode = node(index); - if (!dirNode->volumeName.isNull()) - return dirNode->volumeName + QLatin1String(" (") + name(index) + QLatin1Char(')'); + if (!dirNode->volumeName.isEmpty()) + return dirNode->volumeName; #endif return name(index); } @@ -1268,6 +1267,107 @@ Qt::DropActions QFileSystemModel::supportedDropActions() const } /*! + \enum QFileSystemModel::Option + \since 5.14 + + \value DontWatchForChanges Do not add file watchers to the paths. + This reduces overhead when using the model for simple tasks + like line edit completion. + + \value DontResolveSymlinks Don't resolve symlinks in the file + system model. By default, symlinks are resolved. + + \value DontUseCustomDirectoryIcons Always use the default directory icon. + Some platforms allow the user to set a different icon. Custom icon lookup + causes a big performance impact over network or removable drives. + This sets the QFileIconProvider::DontUseCustomDirectoryIcons + option in the icon provider accordingly. + + \sa resolveSymlinks +*/ + +/*! + \since 5.14 + Sets the given \a option to be enabled if \a on is true; otherwise, + clears the given \a option. + + Options should be set before changing properties. + + \sa options, testOption() +*/ +void QFileSystemModel::setOption(Option option, bool on) +{ + QFileSystemModel::Options previousOptions = options(); + setOptions(previousOptions.setFlag(option, on)); +} + +/*! + \since 5.14 + + Returns \c true if the given \a option is enabled; otherwise, returns + false. + + \sa options, setOption() +*/ +bool QFileSystemModel::testOption(Option option) const +{ + return options().testFlag(option); +} + +/*! + \property QFileSystemModel::options + \brief the various options that affect the model + \since 5.14 + + By default, all options are disabled. + + Options should be set before changing properties. + + \sa setOption(), testOption() +*/ +void QFileSystemModel::setOptions(Options options) +{ + const Options changed = (options ^ QFileSystemModel::options()); + + if (changed.testFlag(DontResolveSymlinks)) + setResolveSymlinks(!options.testFlag(DontResolveSymlinks)); + +#if QT_CONFIG(filesystemwatcher) + Q_D(QFileSystemModel); + if (changed.testFlag(DontWatchForChanges)) + d->fileInfoGatherer.setWatching(!options.testFlag(DontWatchForChanges)); +#endif + + if (changed.testFlag(DontUseCustomDirectoryIcons)) { + if (auto provider = iconProvider()) { + QFileIconProvider::Options providerOptions = provider->options(); + providerOptions.setFlag(QFileIconProvider::DontUseCustomDirectoryIcons, + options.testFlag(QFileSystemModel::DontUseCustomDirectoryIcons)); + provider->setOptions(providerOptions); + } else { + qWarning("Setting QFileSystemModel::DontUseCustomDirectoryIcons has no effect when no provider is used"); + } + } +} + +QFileSystemModel::Options QFileSystemModel::options() const +{ + QFileSystemModel::Options result; + result.setFlag(DontResolveSymlinks, !resolveSymlinks()); +#if QT_CONFIG(filesystemwatcher) + Q_D(const QFileSystemModel); + result.setFlag(DontWatchForChanges, !d->fileInfoGatherer.isWatching()); +#else + result.setFlag(DontWatchForChanges); +#endif + if (auto provider = iconProvider()) { + result.setFlag(DontUseCustomDirectoryIcons, + provider->options().testFlag(QFileIconProvider::DontUseCustomDirectoryIcons)); + } + return result; +} + +/*! Returns the path of the item stored in the model under the \a index given. */ @@ -1390,7 +1490,7 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath) if (d->rootDir.path() == longNewPath) return d->index(rootPath()); - bool showDrives = (longNewPath.isEmpty() || longNewPath == d->myComputer()); + bool showDrives = (longNewPath.isEmpty() || longNewPath == QFileSystemModelPrivate::myComputer()); if (!showDrives && !newPathDir.exists()) return d->index(rootPath()); @@ -1513,6 +1613,8 @@ QDir::Filters QFileSystemModel::filter() const This is only relevant on Windows. By default, this property is \c true. + + \sa QFileSystemModel::Options */ void QFileSystemModel::setResolveSymlinks(bool enable) { @@ -1674,6 +1776,27 @@ void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, cons removeNode(parentNode, toRemove[i]); } +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +static QString volumeName(const QString &path) +{ + IShellItem *item = nullptr; + const QString native = QDir::toNativeSeparators(path); + HRESULT hr = SHCreateItemFromParsingName(reinterpret_cast<const wchar_t *>(native.utf16()), + nullptr, IID_IShellItem, + reinterpret_cast<void **>(&item)); + if (FAILED(hr)) + return QString(); + LPWSTR name = nullptr; + hr = item->GetDisplayName(SIGDN_NORMALDISPLAY, &name); + if (FAILED(hr)) + return QString(); + QString result = QString::fromWCharArray(name); + CoTaskMemFree(name); + item->Release(); + return result; +} +#endif // Q_OS_WIN && !Q_OS_WINRT + /*! \internal @@ -1692,15 +1815,8 @@ QFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFile #endif #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) //The parentNode is "" so we are listing the drives - if (parentNode->fileName.isEmpty()) { - wchar_t name[MAX_PATH + 1]; - //GetVolumeInformation requires to add trailing backslash - const QString nodeName = fileName + QLatin1String("\\"); - BOOL success = ::GetVolumeInformation((wchar_t *)(nodeName.utf16()), - name, MAX_PATH + 1, NULL, 0, NULL, NULL, 0); - if (success && name[0]) - node->volumeName = QString::fromWCharArray(name); - } + if (parentNode->fileName.isEmpty()) + node->volumeName = volumeName(fileName); #endif Q_ASSERT(!parentNode->children.contains(fileName)); parentNode->children.insert(fileName, node); @@ -1847,8 +1963,7 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QV std::sort(rowsToUpdate.begin(), rowsToUpdate.end()); QString min; QString max; - for (int i = 0; i < rowsToUpdate.count(); ++i) { - QString value = rowsToUpdate.at(i); + for (const QString &value : qAsConst(rowsToUpdate)) { //##TODO is there a way to bundle signals with QString as the content of the list? /*if (min.isEmpty()) { min = value; @@ -1946,6 +2061,9 @@ QStringList QFileSystemModelPrivate::unwatchPathsAt(const QModelIndex &index) void QFileSystemModelPrivate::init() { Q_Q(QFileSystemModel); + + delayedSortTimer.setSingleShot(true); + qRegisterMetaType<QVector<QPair<QString,QFileInfo> > >(); #if QT_CONFIG(filesystemwatcher) q->connect(&fileInfoGatherer, SIGNAL(newListOfFiles(QString,QStringList)), |