filesystem: Add QFSEngine for filepaths

Change-Id: Ibd0c88c69863c0877138d8cc45541530c359bd9c
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2022-05-31 11:16:44 +02:00
parent a5d44fb32b
commit 3462bc67be
87 changed files with 2194 additions and 192 deletions

View File

@@ -35,6 +35,7 @@
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fsengine.h>
#include <utils/hostosinfo.h>
#include <utils/optional.h>
#include <utils/qtcsettings.h>
@@ -451,6 +452,8 @@ int main(int argc, char **argv)
Restarter restarter(argc, argv);
Utils::Environment::systemEnvironment(); // cache system environment before we do any changes
Utils::FSEngine fileSystemEngine;
// Manually determine various command line options
// We can't use the regular way of the plugin manager,
// because settings can change the way plugin manager behaves

View File

@@ -57,6 +57,8 @@ add_qtc_library(Utils
filewizardpage.cpp filewizardpage.h
fixedsizeclicklabel.cpp fixedsizeclicklabel.h
flowlayout.cpp flowlayout.h
fsengine/fsengine.cpp fsengine/fsengine.h
fsengine/fileiconprovider.cpp fsengine/fileiconprovider.h
functiontraits.h
futuresynchronizer.cpp futuresynchronizer.h
fuzzymatcher.cpp fuzzymatcher.h
@@ -247,6 +249,20 @@ extend_qtc_library(Utils CONDITION UNIX AND NOT APPLE
touchbar/touchbar.cpp
)
extend_qtc_library(Utils
CONDITION TARGET Qt5::CorePrivate
DEPENDS Qt5::CorePrivate
DEFINES QTC_UTILS_WITH_FSENGINE
SOURCES fsengine/fsengine_impl.cpp
fsengine/fsengine_impl.h
fsengine/diriterator.h
fsengine/fileiteratordevicesappender.h
fsengine/rootinjectfsengine.h
fsengine/fixedlistfsengine.h
fsengine/fsenginehandler.cpp
fsengine/fsenginehandler.h
)
if (WIN32)
add_qtc_executable(qtcreator_process_stub
SOURCES process_stub_win.c
@@ -263,3 +279,4 @@ if (WIN32)
else()
add_qtc_executable(qtcreator_process_stub SOURCES process_stub_unix.c)
endif()

View File

@@ -39,6 +39,7 @@
#include <QRegularExpression>
#include <QStorageInfo>
#include <QUrl>
#include <QStringView>
#ifdef Q_OS_WIN
#ifdef QTCREATOR_PCH_H
@@ -480,9 +481,20 @@ QString FilePath::toString() const
{
if (m_scheme.isEmpty())
return m_data;
if (m_data.startsWith('/'))
return m_scheme + "://" + hostEncoded(m_host) + m_data;
return m_scheme + "://" + hostEncoded(m_host) + "/./" + m_data;
return specialPath(SpecialPathComponent::RootPath) + "/" + m_scheme + "/" + hostEncoded(m_host) + m_data;
return specialPath(SpecialPathComponent::RootPath) + "/" + m_scheme + "/" + hostEncoded(m_host) + "/./" + m_data;
}
QString FilePath::toFSPathString() const
{
if (m_scheme.isEmpty())
return m_data;
if (m_data.startsWith('/'))
return specialPath(SpecialPathComponent::RootPath) + "/" + m_scheme + "/" + hostEncoded(m_host) + m_data;
return specialPath(SpecialPathComponent::RootPath) + "/" + m_scheme + "/" + hostEncoded(m_host) + "/./" + m_data;
}
QUrl FilePath::toUrl() const
@@ -504,6 +516,12 @@ void FileUtils::setDeviceFileHooks(const DeviceFileHooks &hooks)
/// this path belongs to.
QString FilePath::toUserOutput() const
{
if (needsDevice()) {
if (m_data.startsWith('/'))
return m_scheme + "://" + hostEncoded(m_host) + m_data;
return m_scheme + "://" + hostEncoded(m_host) + "/./" + m_data;
}
FilePath tmp = *this;
if (osType() == OsTypeWindows)
tmp.m_data.replace('/', '\\');
@@ -941,6 +959,27 @@ FilePath FilePath::absoluteFilePath() const
return result;
}
QString FilePath::specialPath(SpecialPathComponent component)
{
switch (component) {
case SpecialPathComponent::RootName:
return QLatin1String("__qtc_devices__");
case SpecialPathComponent::RootPath:
return (QDir::rootPath() + "__qtc_devices__");
case SpecialPathComponent::DeviceRootName:
return QLatin1String("device");
case SpecialPathComponent::DeviceRootPath:
return QDir::rootPath() + "__qtc_devices__/device";
}
QTC_ASSERT(false, return {});
}
FilePath FilePath::specialFilePath(SpecialPathComponent component)
{
return FilePath::fromString(specialPath(component));
}
FilePath FilePath::normalizedPathName() const
{
FilePath result = *this;
@@ -1005,28 +1044,88 @@ FilePath FilePath::fromString(const QString &filepath)
void FilePath::setFromString(const QString &filename)
{
if (filename.startsWith('/')) {
m_data = filename; // fast track: absolute local paths
} else {
int pos1 = filename.indexOf("://");
if (pos1 >= 0) {
m_scheme = filename.left(pos1);
pos1 += 3;
int pos2 = filename.indexOf('/', pos1);
if (pos2 == -1) {
m_data = filename.mid(pos1);
} else {
m_host = filename.mid(pos1, pos2 - pos1);
m_host.replace("%2f", "/");
m_host.replace("%25", "%");
m_data = filename.mid(pos2);
#ifndef UTILS_FILEPATH_USE_REGEXP
static const QLatin1String qtcDevSlash("__qtc_devices__/");
const QStringView fileNameView(filename);
const QString rootPath = QDir::rootPath();
if (fileNameView.startsWith(rootPath, Qt::CaseInsensitive)) { // Absolute path ...
const QStringView withoutRootPath = fileNameView.mid(rootPath.size());
if (withoutRootPath.startsWith(qtcDevSlash)) { // Starts with "/__qtc_devices__/" ...
const QStringView withoutQtcDeviceRoot = withoutRootPath.mid(qtcDevSlash.size());
const auto firstSlash = withoutQtcDeviceRoot.indexOf('/');
if (firstSlash != -1) {
m_scheme = withoutQtcDeviceRoot.left(firstSlash).toString();
const auto secondSlash = withoutQtcDeviceRoot.indexOf('/', firstSlash + 1);
m_host = withoutQtcDeviceRoot.mid(firstSlash + 1, secondSlash - firstSlash - 1)
.toString();
if (secondSlash != -1) {
const QStringView path = withoutQtcDeviceRoot.mid(secondSlash);
m_data = path.startsWith(QLatin1String("/./")) ? path.mid(3).toString()
: path.toString();
return;
}
m_data = "/";
return;
}
if (m_data.startsWith("/./"))
m_data = m_data.mid(3);
} else {
m_data = filename; // treat everything else as local, too.
m_scheme = "";
m_host = "";
m_data = filename;
return;
}
}
const auto firstSlash = filename.indexOf('/');
const auto schemeEnd = filename.indexOf("://");
if (schemeEnd != -1 && schemeEnd < firstSlash) {
// This is a pseudo Url, we can't use QUrl here sadly.
m_scheme = filename.left(schemeEnd);
const auto hostEnd = filename.indexOf('/', schemeEnd + 3);
m_host = filename.mid(schemeEnd + 3, hostEnd - schemeEnd - 3);
m_data = filename.mid(hostEnd);
return;
}
m_data = filename;
return;
#else
// Convert the root path ( "/" or e.g. "c:/") to a regex match string ( e.g. ^[(?i)c(?-i)]:\/ )
// (?i) will turn on case insensitivity, (?-i) will turn it off again.
static const QString rootPart = '^'
+ QDir::rootPath()
.replace('/', "\\/")
.replace(QRegularExpression("([a-zA-Z])"),
R"((?i)[\1](?-i))");
static const QString pathPattern = rootPart + specialPath(SpecialPathComponent::RootName)
+ QString(R"(\/([^\/]+)\/([^\/]+)(\/.*)?)");
static const QRegularExpression rePath(pathPattern);
static const QRegularExpression reUrl(R"(^\/?([^:]+):\/{2}([^\/]*)(\/.*))");
const auto m = filename.startsWith(specialPath(SpecialPathComponent::RootPath),
Qt::CaseInsensitive)
? rePath.match(filename)
: reUrl.match(filename);
if (m.hasMatch()) {
m_scheme = m.captured(1);
m_host = m.captured(2);
m_host.replace("%2f", "/");
m_host.replace("%25", "%");
m_data = m.captured(3).isEmpty() ? "/" : m.captured(3);
} else {
m_data = filename;
}
#endif
}
/// Constructs a FilePath from \a filePath. The \a defaultExtension is appended

View File

@@ -78,6 +78,7 @@ public:
QString toUserOutput() const;
QString toString() const;
QString toFSPathString() const;
QVariant toVariant() const;
QUrl toUrl() const;
@@ -210,6 +211,16 @@ public:
[[nodiscard]] FilePath absolutePath() const; // Avoid. Use resolvePath(...)[.parent()] with proper base.
[[nodiscard]] FilePath absoluteFilePath() const; // Avoid. Use resolvePath(...) with proper base.
enum class SpecialPathComponent {
RootName,
RootPath,
DeviceRootName,
DeviceRootPath,
};
[[nodiscard]] static QString specialPath(SpecialPathComponent component);
[[nodiscard]] static FilePath specialFilePath(SpecialPathComponent component);
private:
friend class ::tst_fileutils;
static QString calcRelativePath(const QString &absolutePath, const QString &absoluteAnchorPath);

View File

@@ -29,6 +29,9 @@
#include "algorithm.h"
#include "qtcassert.h"
#include "fsengine/fileiconprovider.h"
#include "fsengine/fsengine.h"
#include <QDataStream>
#include <QDebug>
#include <QOperatingSystemVersion>
@@ -41,6 +44,7 @@
#ifdef QT_GUI_LIB
#include <QMessageBox>
#include <QRegularExpression>
#include <QGuiApplication>
#endif
#ifdef Q_OS_WIN
@@ -438,8 +442,15 @@ FilePath FileUtils::getOpenFilePath(QWidget *parent,
const FilePath &dir,
const QString &filter,
QString *selectedFilter,
QFileDialog::Options options)
QFileDialog::Options options,
bool fromDeviceIfShiftIsPressed)
{
#ifdef QT_GUI_LIB
if (fromDeviceIfShiftIsPressed && qApp->queryKeyboardModifiers() & Qt::ShiftModifier) {
return getOpenFilePathFromDevice(parent, caption, dir, filter, selectedFilter, options);
}
#endif
const QString result = QFileDialog::getOpenFileName(dialogParent(parent),
caption,
dir.toString(),
@@ -493,6 +504,47 @@ FilePaths FileUtils::getOpenFilePaths(QWidget *parent,
return transform(result, &FilePath::fromString);
}
FilePath FileUtils::getOpenFilePathFromDevice(QWidget *parent,
const QString &caption,
const FilePath &dir,
const QString &filter,
QString *selectedFilter,
QFileDialog::Options options)
{
QFileDialog dialog;
dialog.setOptions(options | QFileDialog::DontUseNativeDialog);
dialog.setWindowTitle(caption);
dialog.setDirectory(dir.toString());
dialog.setNameFilter(filter);
QList<QUrl> sideBarUrls = Utils::transform(Utils::filtered(FSEngine::registeredDeviceRoots(),
[](const auto &filePath) {
return filePath.exists();
}),
[](const auto &filePath) {
return QUrl::fromLocalFile(
filePath.toFSPathString());
});
dialog.setSidebarUrls(sideBarUrls);
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setIconProvider(Utils::FileIconProvider::iconProvider());
if (dialog.exec()) {
FilePaths filePaths = Utils::transform(dialog.selectedFiles(), [](const auto &path) {
return FilePath::fromString(path);
});
if (selectedFilter) {
*selectedFilter = dialog.selectedNameFilter();
}
return filePaths.first();
}
return {};
}
// Used on 'ls' output on unix-like systems.
void FileUtils::iterateLsOutput(const FilePath &base,
const QStringList &entries,

View File

@@ -152,7 +152,8 @@ public:
const FilePath &dir = {},
const QString &filter = {},
QString *selectedFilter = nullptr,
QFileDialog::Options options = {});
QFileDialog::Options options = {},
bool fromDeviceIfShiftIsPressed = false);
static FilePath getSaveFilePath(QWidget *parent,
const QString &caption,
@@ -172,6 +173,13 @@ public:
const QString &filter = {},
QString *selectedFilter = nullptr,
QFileDialog::Options options = {});
static FilePath getOpenFilePathFromDevice(QWidget *parent,
const QString &caption,
const FilePath &dir = {},
const QString &filter = {},
QString *selectedFilter = nullptr,
QFileDialog::Options options = {});
#endif
};

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "../filepath.h"
#include "../stringutils.h"
#include <QFileInfo>
#include <QString>
#include <QtCore/private/qabstractfileengine_p.h>
namespace Utils {
namespace Internal {
class DirIterator : public QAbstractFileEngineIterator
{
public:
DirIterator(FilePaths paths)
: QAbstractFileEngineIterator({}, {})
, m_filePaths(std::move(paths))
, it(m_filePaths.begin())
{}
// QAbstractFileEngineIterator interface
public:
QString next() override
{
if (it == m_filePaths.end())
return QString();
const QString r = currentFilePath();
++it;
return r;
}
bool hasNext() const override { return !m_filePaths.empty() && m_filePaths.end() != it + 1; }
QString currentFileName() const override { return chopIfEndsWith(it->toString(), '/'); }
QFileInfo currentFileInfo() const override
{
return QFileInfo(chopIfEndsWith(it->toString(), '/'));
}
private:
const FilePaths m_filePaths;
FilePaths::const_iterator it;
};
} // namespace Internal
} // namespace Utils

View File

@@ -41,11 +41,14 @@
#include <QFileIconProvider>
#include <QIcon>
#include <QLoggingCategory>
using namespace Utils;
Q_LOGGING_CATEGORY(fileIconProvider, "qtc.core.fileiconprovider", QtWarningMsg)
/*!
\namespace Core::FileIconProvider
\namespace Utils::FileIconProvider
\inmodule QtCreator
\brief Provides functions for registering custom overlay icons for system
icons.
@@ -64,11 +67,9 @@ using namespace Utils;
using Item = Utils::variant<QIcon, QString>; // icon or filename for the icon
namespace Core {
namespace Utils {
namespace FileIconProvider {
enum { debug = 0 };
static Utils::optional<QIcon> getIcon(QHash<QString, Item> &cache, const QString &key)
{
auto it = cache.constFind(key);
@@ -128,8 +129,44 @@ public:
// Mapping of file suffix to icon.
mutable QHash<QString, Item> m_suffixCache;
mutable QHash<QString, Item> m_filenameCache;
// QAbstractFileIconProvider interface
public:
QIcon icon(IconType) const override;
QIcon icon(const QFileInfo &) const override;
QString type(const QFileInfo &) const override;
};
QIcon FileIconProviderImplementation::icon(IconType type) const
{
return QFileIconProvider::icon(type);
}
QIcon FileIconProviderImplementation::icon(const QFileInfo &fi) const
{
return icon(FilePath::fromString(fi.filePath()));
}
QString FileIconProviderImplementation::type(const QFileInfo &fi) const
{
const FilePath fPath = FilePath::fromString(fi.filePath());
if (fPath.needsDevice()) {
if (fPath.isDir()) {
#ifdef Q_OS_WIN
return QGuiApplication::translate("QAbstractFileIconProvider", "File Folder", "Match Windows Explorer");
#else
return QGuiApplication::translate("QAbstractFileIconProvider", "Folder", "All other platforms");
#endif
}
if (fPath.isExecutableFile()) {
return "Program";
}
return QFileIconProvider::type(fi);
}
return QFileIconProvider::type(fi);
}
FileIconProviderImplementation *instance()
{
static FileIconProviderImplementation theInstance;
@@ -155,11 +192,20 @@ static const QIcon &dirIcon()
QIcon FileIconProviderImplementation::icon(const FilePath &filePath) const
{
if (debug)
qDebug() << "FileIconProvider::icon" << filePath.absoluteFilePath();
qCDebug(fileIconProvider) << "FileIconProvider::icon" << filePath.absoluteFilePath();
if (filePath.isEmpty())
return unknownFileIcon();
// Check if its one of the virtual devices directories
if (filePath.path().startsWith(FilePath::specialPath(FilePath::SpecialPathComponent::RootPath))) {
// If the filepath does not need a device, it is a virtual device directory
if (!filePath.needsDevice())
return dirIcon();
}
bool isDir = filePath.isDir();
if (filePath.needsDevice())
return isDir ? dirIcon() : unknownFileIcon();
// Check for cached overlay icons by file suffix.
const QString filename = !isDir ? filePath.fileName() : QString();
if (!filename.isEmpty()) {
@@ -167,6 +213,7 @@ QIcon FileIconProviderImplementation::icon(const FilePath &filePath) const
if (icon)
return *icon;
}
const QString suffix = !isDir ? filePath.suffix() : QString();
if (!suffix.isEmpty()) {
const Utils::optional<QIcon> icon = getIcon(m_suffixCache, suffix);
@@ -174,6 +221,9 @@ QIcon FileIconProviderImplementation::icon(const FilePath &filePath) const
return *icon;
}
if (filePath.needsDevice())
return isDir ? dirIcon() : unknownFileIcon();
// Get icon from OS (and cache it based on suffix!)
QIcon icon;
if (HostOsInfo::isWindowsHost() || HostOsInfo::isMacHost())
@@ -263,7 +313,7 @@ QIcon directoryIcon(const QString &overlay)
const QPixmap dirPixmap = QApplication::style()->standardIcon(QStyle::SP_DirIcon).pixmap(desiredSize);
const QIcon overlayIcon(overlay);
QIcon result;
result.addPixmap(Core::FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
result.addPixmap(FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
return result;
}

View File

@@ -25,33 +25,41 @@
#pragma once
#include <coreplugin/core_global.h>
#include "../utils_global.h"
#ifdef QT_GUI_LIB
#include <QStyle>
#include <QFileIconProvider>
#include <QStyle>
namespace Utils { class FilePath; }
namespace Core {
namespace Utils {
class FilePath;
namespace FileIconProvider {
// Access to the single instance
CORE_EXPORT QFileIconProvider *iconProvider();
QTCREATOR_UTILS_EXPORT QFileIconProvider *iconProvider();
// Access to individual items
CORE_EXPORT QIcon icon(const Utils::FilePath &filePath);
CORE_EXPORT QIcon icon(QFileIconProvider::IconType type);
QTCREATOR_UTILS_EXPORT QIcon icon(const Utils::FilePath &filePath);
QTCREATOR_UTILS_EXPORT QIcon icon(QFileIconProvider::IconType type);
// Register additional overlay icons
CORE_EXPORT QPixmap overlayIcon(const QPixmap &baseIcon, const QIcon &overlayIcon);
CORE_EXPORT QPixmap overlayIcon(QStyle::StandardPixmap baseIcon, const QIcon &overlayIcon, const QSize &size);
CORE_EXPORT void registerIconOverlayForSuffix(const QString &path, const QString &suffix);
CORE_EXPORT void registerIconOverlayForFilename(const QString &path, const QString &filename);
CORE_EXPORT void registerIconOverlayForMimeType(const QString &path, const QString &mimeType);
CORE_EXPORT void registerIconOverlayForMimeType(const QIcon &icon, const QString &mimeType);
QTCREATOR_UTILS_EXPORT QPixmap overlayIcon(const QPixmap &baseIcon, const QIcon &overlayIcon);
QTCREATOR_UTILS_EXPORT QPixmap overlayIcon(QStyle::StandardPixmap baseIcon,
const QIcon &overlayIcon,
const QSize &size);
QTCREATOR_UTILS_EXPORT void registerIconOverlayForSuffix(const QString &path, const QString &suffix);
QTCREATOR_UTILS_EXPORT void registerIconOverlayForFilename(const QString &path,
const QString &filename);
QTCREATOR_UTILS_EXPORT void registerIconOverlayForMimeType(const QString &path,
const QString &mimeType);
QTCREATOR_UTILS_EXPORT void registerIconOverlayForMimeType(const QIcon &icon,
const QString &mimeType);
CORE_EXPORT QIcon directoryIcon(const QString &overlay);
QTCREATOR_UTILS_EXPORT QIcon directoryIcon(const QString &overlay);
} // namespace FileIconProvider
} // namespace Core
} // namespace Utils
#endif

View File

@@ -0,0 +1,146 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "../filepath.h"
#include <QtCore/private/qabstractfileengine_p.h>
namespace Utils {
namespace Internal {
// Based on http://bloglitb.blogspot.com/2011/12/access-to-private-members-safer.htm
template<typename Tag, typename Tag::type M>
struct PrivateAccess
{
friend typename Tag::type get(Tag) { return M; }
};
struct QAFEITag
{
using type = void (QAbstractFileEngineIterator::*)(const QString &);
friend type get(QAFEITag);
};
template struct PrivateAccess<QAFEITag, &QAbstractFileEngineIterator::setPath>;
class FileIteratorWrapper : public QAbstractFileEngineIterator
{
enum class State {
NotIteratingRoot,
IteratingRoot,
BaseIteratorEnd,
Ended,
};
public:
FileIteratorWrapper(std::unique_ptr<QAbstractFileEngineIterator> &&baseIterator,
QDir::Filters filters,
const QStringList &filterNames)
: QAbstractFileEngineIterator(filters, filterNames)
, m_baseIterator(std::move(baseIterator))
{}
public:
QString next() override
{
if (m_status == State::Ended)
return QString();
setPath();
checkStatus();
if (m_status == State::BaseIteratorEnd) {
m_status = State::Ended;
return "__qtc__devices__";
}
return m_baseIterator->next();
}
bool hasNext() const override
{
if (m_status == State::Ended)
return false;
setPath();
checkStatus();
if (m_status == State::BaseIteratorEnd)
return true;
return m_baseIterator->hasNext();
}
QString currentFileName() const override
{
if (m_status == State::Ended)
return FilePath::specialPath(FilePath::SpecialPathComponent::RootPath);
setPath();
checkStatus();
return m_baseIterator->currentFileName();
}
QFileInfo currentFileInfo() const override
{
if (m_status == State::Ended)
return QFileInfo(FilePath::specialPath(FilePath::SpecialPathComponent::RootPath));
setPath();
checkStatus();
return m_baseIterator->currentFileInfo();
}
private:
void setPath() const
{
if (!m_hasSetPath) {
const QString p = path();
if (p.toLower() == QDir::rootPath())
m_status = State::IteratingRoot;
((*m_baseIterator).*get(QAFEITag()))(p);
m_hasSetPath = true;
}
}
void checkStatus() const
{
if (m_status == State::NotIteratingRoot) {
return;
}
if (m_status == State::IteratingRoot) {
if (m_baseIterator->hasNext() == false) {
m_status = State::BaseIteratorEnd;
}
}
}
private:
std::unique_ptr<QAbstractFileEngineIterator> m_baseIterator;
mutable bool m_hasSetPath{false};
mutable State m_status{State::NotIteratingRoot};
};
} // namespace Internal
} // namespace Utils

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "diriterator.h"
#include "../filepath.h"
#include "../stringutils.h"
#include <QtCore/private/qabstractfileengine_p.h>
namespace Utils {
namespace Internal {
class FixedListFSEngine : public QAbstractFileEngine
{
const FilePath m_filePath;
FilePaths m_children;
public:
FixedListFSEngine(FilePath path, const FilePaths children)
: m_filePath(std::move(path))
, m_children(std::move(children))
{
m_children.prepend(m_filePath.pathAppended("."));
}
// QAbstractFileEngine interface
public:
bool isRelativePath() const override { return false; }
FileFlags fileFlags(FileFlags /*type*/) const override
{
return FileFlag::DirectoryType | FileFlag::ExistsFlag | FileFlag::ReadGroupPerm
| FileFlag::ReadUserPerm | FileFlag::ReadOwnerPerm | FileFlag::ReadOtherPerm;
}
QString fileName(FileName file) const override
{
switch (file) {
case QAbstractFileEngine::AbsoluteName:
case QAbstractFileEngine::DefaultName:
case QAbstractFileEngine::CanonicalName:
return chopIfEndsWith(m_filePath.toString(), '/');
break;
case QAbstractFileEngine::BaseName:
return m_filePath.baseName();
break;
case QAbstractFileEngine::PathName:
case QAbstractFileEngine::AbsolutePathName:
case QAbstractFileEngine::CanonicalPathName:
return chopIfEndsWith(m_filePath.parentDir().toString(), '/');
break;
default:
// case QAbstractFileEngine::LinkName:
// case QAbstractFileEngine::BundleName:
// case QAbstractFileEngine::JunctionName:
return {};
break;
}
return QAbstractFileEngine::fileName(file);
}
Iterator *beginEntryList(QDir::Filters /*filters*/, const QStringList & /*filterNames*/) override
{
return new DirIterator(m_children);
}
};
} // namespace Internal
} // namespace Utils

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "fsengine.h"
#ifdef QTC_UTILS_WITH_FSENGINE
#include "fsenginehandler.h"
#else
class Utils::Internal::FSEngineHandler
{};
#endif
#include <memory>
namespace Utils {
FSEngine::FSEngine()
: m_engineHandler(std::make_unique<Internal::FSEngineHandler>())
{}
FSEngine::~FSEngine() {}
bool FSEngine::isAvailable()
{
#ifdef QTC_UTILS_WITH_FSENGINE
return true;
#else
return false;
#endif
}
FilePaths FSEngine::registeredDeviceRoots()
{
return FSEngine::deviceRoots();
}
void FSEngine::addDevice(const FilePath &deviceRoot)
{
deviceRoots().append(deviceRoot);
}
void FSEngine::removeDevice(const FilePath &deviceRoot)
{
deviceRoots().removeAll(deviceRoot);
}
FilePaths &FSEngine::deviceRoots()
{
static FilePaths g_deviceRoots;
return g_deviceRoots;
}
QStringList &FSEngine::deviceSchemes()
{
static QStringList g_deviceSchemes {"device"};
return g_deviceSchemes;
}
void FSEngine::registerDeviceScheme(const QString &scheme)
{
deviceSchemes().append(scheme);
}
void FSEngine::unregisterDeviceScheme(const QString &scheme)
{
deviceSchemes().removeAll(scheme);
}
QStringList FSEngine::registeredDeviceSchemes()
{
return FSEngine::deviceSchemes();
}
} // namespace Utils

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "../filepath.h"
#include "../utils_global.h"
#include <memory>
namespace Utils {
namespace Internal {
class FSEngineHandler;
}
class QTCREATOR_UTILS_EXPORT FSEngine
{
friend class Internal::FSEngineHandler;
public:
FSEngine();
~FSEngine();
public:
static bool isAvailable();
static Utils::FilePaths registeredDeviceRoots();
static void addDevice(const Utils::FilePath &deviceRoot);
static void removeDevice(const Utils::FilePath &deviceRoot);
static void registerDeviceScheme(const QString &scheme);
static void unregisterDeviceScheme(const QString &scheme);
static QStringList registeredDeviceSchemes();
private:
static Utils::FilePaths &deviceRoots();
static QStringList &deviceSchemes();
private:
std::unique_ptr<Internal::FSEngineHandler> m_engineHandler;
};
} // namespace Utils

View File

@@ -0,0 +1,352 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "fsengine_impl.h"
#include "diriterator.h"
#include "../filepath.h"
#include "../qtcassert.h"
#include <QIODevice>
#include <QDateTime>
namespace Utils {
namespace Internal {
FSEngineImpl::FSEngineImpl(FilePath filePath)
: m_filePath(std::move(filePath))
{}
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
bool FSEngineImpl::open(QIODeviceBase::OpenMode openMode, std::optional<QFile::Permissions>)
#else
bool FSEngineImpl::open(QIODevice::OpenMode openMode)
#endif
{
QTC_ASSERT(m_tempStorage.open(), return false);
bool read = openMode & QIODevice::ReadOnly;
bool write = openMode & QIODevice::WriteOnly;
bool append = openMode & QIODevice::Append;
if (!write && !m_filePath.exists())
return false;
if (openMode & QIODevice::NewOnly && m_filePath.exists())
return false;
if (read || append) {
QTC_ASSERT(m_tempStorage.write(m_filePath.fileContents()) >= 0, return false);
if (!append)
m_tempStorage.seek(0);
}
if (write && !append)
m_hasChangedContent = true;
return true;
}
bool FSEngineImpl::close()
{
QTC_ASSERT(flush(), return false);
m_tempStorage.close();
return true;
}
bool FSEngineImpl::flush()
{
return syncToDisk();
}
bool FSEngineImpl::syncToDisk()
{
if (m_hasChangedContent) {
const qint64 oldPos = m_tempStorage.pos();
QTC_ASSERT(m_tempStorage.seek(0), return false);
QTC_ASSERT(m_filePath.writeFileContents(m_tempStorage.readAll()), return false);
m_tempStorage.seek(oldPos);
m_hasChangedContent = false;
return true;
}
return true;
}
qint64 FSEngineImpl::size() const
{
return m_filePath.fileSize();
}
qint64 FSEngineImpl::pos() const
{
return m_tempStorage.pos();
}
bool FSEngineImpl::seek(qint64 pos)
{
return m_tempStorage.seek(pos);
}
bool FSEngineImpl::isSequential() const
{
return false;
}
bool FSEngineImpl::remove()
{
return m_filePath.removeRecursively();
}
bool FSEngineImpl::copy(const QString &newName)
{
return m_filePath.copyFile(FilePath::fromString(newName));
}
bool FSEngineImpl::rename(const QString &newName)
{
return m_filePath.renameFile(FilePath::fromString(newName));
}
bool FSEngineImpl::renameOverwrite(const QString &newName)
{
Q_UNUSED(newName)
return false;
}
bool FSEngineImpl::link(const QString &newName)
{
Q_UNUSED(newName)
return false;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
bool FSEngineImpl::mkdir(const QString &dirName, bool createParentDirectories,
std::optional<QFile::Permissions>) const
#else
bool FSEngineImpl::mkdir(const QString &dirName, bool createParentDirectories) const
#endif
{
Q_UNUSED(createParentDirectories)
return FilePath::fromString(dirName).createDir();
}
bool FSEngineImpl::rmdir(const QString &dirName, bool recurseParentDirectories) const
{
if (recurseParentDirectories)
return false;
return m_filePath.pathAppended(dirName).removeRecursively();
}
bool FSEngineImpl::setSize(qint64 size)
{
return m_tempStorage.resize(size);
}
bool FSEngineImpl::caseSensitive() const
{
// TODO?
return true;
}
bool FSEngineImpl::isRelativePath() const
{
return false;
}
QStringList FSEngineImpl::entryList(QDir::Filters filters, const QStringList &filterNames) const
{
QStringList result;
m_filePath.iterateDirectory(
[&result](const FilePath &p) {
result.append(p.toFSPathString());
return true;
},
{filterNames, filters});
return result;
}
QAbstractFileEngine::FileFlags FSEngineImpl::fileFlags(FileFlags type) const
{
FileFlags result{0};
if (type & FileInfoAll && m_filePath.exists()) {
result |= QAbstractFileEngine::ExistsFlag;
if (type & DirectoryType && m_filePath.isDir())
result |= QAbstractFileEngine::DirectoryType;
if (type & FileType && m_filePath.isFile())
result |= QAbstractFileEngine::FileType;
if (type & PermsMask) {
result |= FileFlags::fromInt(m_filePath.permissions().toInt());
}
}
return result;
}
bool FSEngineImpl::setPermissions(uint /*perms*/)
{
return false;
}
QByteArray FSEngineImpl::id() const
{
return QAbstractFileEngine::id();
}
QString FSEngineImpl::fileName(FileName file) const
{
switch (file) {
case QAbstractFileEngine::AbsoluteName:
case QAbstractFileEngine::DefaultName:
return m_filePath.toFSPathString();
break;
case QAbstractFileEngine::BaseName:
return m_filePath.baseName();
break;
case QAbstractFileEngine::PathName:
case QAbstractFileEngine::AbsolutePathName:
return m_filePath.parentDir().toFSPathString();
break;
case QAbstractFileEngine::CanonicalName:
return m_filePath.canonicalPath().toFSPathString();
break;
case QAbstractFileEngine::CanonicalPathName:
return m_filePath.canonicalPath().parentDir().toFSPathString();
break;
default:
// case QAbstractFileEngine::LinkName:
// case QAbstractFileEngine::BundleName:
// case QAbstractFileEngine::JunctionName:
return {};
break;
}
return QAbstractFileEngine::fileName(file);
}
uint FSEngineImpl::ownerId(FileOwner) const
{
return 1;
}
QString FSEngineImpl::owner(FileOwner) const
{
return "<unknown>";
}
bool FSEngineImpl::setFileTime(const QDateTime &newDate, FileTime time)
{
Q_UNUSED(newDate)
Q_UNUSED(time)
return false;
}
QDateTime FSEngineImpl::fileTime(FileTime time) const
{
Q_UNUSED(time)
return m_filePath.lastModified();
}
void FSEngineImpl::setFileName(const QString &file)
{
close();
m_filePath = FilePath::fromString(file);
}
int FSEngineImpl::handle() const
{
return 0;
}
bool FSEngineImpl::cloneTo(QAbstractFileEngine *target)
{
return QAbstractFileEngine::cloneTo(target);
}
QAbstractFileEngine::Iterator *FSEngineImpl::beginEntryList(QDir::Filters filters,
const QStringList &filterNames)
{
FilePaths paths{m_filePath.pathAppended(".")};
m_filePath.iterateDirectory(
[&paths](const FilePath &p) {
paths.append(p);
return true;
},
{filterNames, filters});
return new DirIterator(paths);
}
QAbstractFileEngine::Iterator *FSEngineImpl::endEntryList()
{
return nullptr;
}
qint64 FSEngineImpl::read(char *data, qint64 maxlen)
{
return m_tempStorage.read(data, maxlen);
}
qint64 FSEngineImpl::readLine(char *data, qint64 maxlen)
{
return m_tempStorage.readLine(data, maxlen);
}
qint64 FSEngineImpl::write(const char *data, qint64 len)
{
qint64 bytesWritten = m_tempStorage.write(data, len);
if (bytesWritten > 0)
m_hasChangedContent = true;
return bytesWritten;
}
bool FSEngineImpl::extension(Extension extension,
const ExtensionOption *option,
ExtensionReturn *output)
{
Q_UNUSED(extension)
Q_UNUSED(option)
Q_UNUSED(output)
return false;
}
bool FSEngineImpl::supportsExtension(Extension extension) const
{
Q_UNUSED(extension)
return false;
}
} // namespace Internal
} // namespace Utils

View File

@@ -0,0 +1,98 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "../filepath.h"
#include <QtCore/private/qabstractfileengine_p.h>
#include <QTemporaryFile>
namespace Utils {
namespace Internal {
class FSEngineImpl : public QAbstractFileEngine
{
public:
FSEngineImpl(FilePath filePath);
public:
#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
bool open(QIODeviceBase::OpenMode openMode,
std::optional<QFile::Permissions> permissions = std::nullopt) override;
bool mkdir(const QString &dirName, bool createParentDirectories,
std::optional<QFile::Permissions> permissions = std::nullopt) const override;
#else
bool open(QIODevice::OpenMode openMode) override;
bool mkdir(const QString &dirName, bool createParentDirectories) const override;
#endif
bool close() override;
bool flush() override;
bool syncToDisk() override;
qint64 size() const override;
qint64 pos() const override;
bool seek(qint64 pos) override;
bool isSequential() const override;
bool remove() override;
bool copy(const QString &newName) override;
bool rename(const QString &newName) override;
bool renameOverwrite(const QString &newName) override;
bool link(const QString &newName) override;
bool rmdir(const QString &dirName, bool recurseParentDirectories) const override;
bool setSize(qint64 size) override;
bool caseSensitive() const override;
bool isRelativePath() const override;
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override;
FileFlags fileFlags(FileFlags type) const override;
bool setPermissions(uint perms) override;
QByteArray id() const override;
QString fileName(FileName file) const override;
uint ownerId(FileOwner) const override;
QString owner(FileOwner) const override;
bool setFileTime(const QDateTime &newDate, FileTime time) override;
QDateTime fileTime(FileTime time) const override;
void setFileName(const QString &file) override;
int handle() const override;
bool cloneTo(QAbstractFileEngine *target) override;
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override;
Iterator *endEntryList() override;
qint64 read(char *data, qint64 maxlen) override;
qint64 readLine(char *data, qint64 maxlen) override;
qint64 write(const char *data, qint64 len) override;
bool extension(Extension extension,
const ExtensionOption *option,
ExtensionReturn *output) override;
bool supportsExtension(Extension extension) const override;
private:
FilePath m_filePath;
QTemporaryFile m_tempStorage;
bool m_hasChangedContent{false};
};
} // namespace Internal
} // namespace Utils

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "fsenginehandler.h"
#include "fixedlistfsengine.h"
#include "fsengine_impl.h"
#include "rootinjectfsengine.h"
#include "fsengine.h"
#include "../algorithm.h"
namespace Utils {
namespace Internal {
QAbstractFileEngine *FSEngineHandler::create(const QString &fileName) const
{
if (fileName.startsWith(':'))
return nullptr;
QString fixedFileName = fileName;
if (fileName.startsWith("//")) {
fixedFileName = fixedFileName.mid(1);
}
if (fixedFileName == FilePath::specialPath(FilePath::SpecialPathComponent::RootPath)) {
const FilePaths paths
= Utils::transform(FSEngine::registeredDeviceSchemes(), [](const QString &scheme) {
return FilePath::specialFilePath(FilePath::SpecialPathComponent::RootPath)
.pathAppended(scheme);
});
return new FixedListFSEngine(FilePath::specialFilePath(
FilePath::SpecialPathComponent::RootPath),
paths);
}
if (fixedFileName.startsWith(FilePath::specialPath(FilePath::SpecialPathComponent::RootPath))) {
const QStringList deviceSchemes = FSEngine::registeredDeviceSchemes();
for (const QString &scheme : deviceSchemes) {
if (fixedFileName
== FilePath::specialFilePath(FilePath::SpecialPathComponent::RootPath)
.pathAppended(scheme)
.toString()) {
const FilePaths filteredRoots = Utils::filtered(FSEngine::deviceRoots(),
[scheme](const FilePath &root) {
return root.scheme() == scheme;
});
return new FixedListFSEngine(FilePath::specialFilePath(
FilePath::SpecialPathComponent::RootPath)
.pathAppended(scheme),
filteredRoots);
}
}
}
FilePath filePath = FilePath::fromString(fixedFileName);
if (filePath.needsDevice()) {
return new FSEngineImpl(filePath);
}
if (fixedFileName.compare(QDir::rootPath(), Qt::CaseInsensitive) == 0) {
return new RootInjectFSEngine(fixedFileName);
}
return nullptr;
}
} // namespace Internal
} // namespace Utils

View File

@@ -0,0 +1,42 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QtCore/private/qabstractfileengine_p.h>
namespace Utils {
namespace Internal {
class FSEngineHandler : public QAbstractFileEngineHandler
{
public:
QAbstractFileEngine *create(const QString &fileName) const override;
};
} // namespace Internal
} // namespace Utils

View File

@@ -0,0 +1,50 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "fileiteratordevicesappender.h"
#include <QtCore/private/qfsfileengine_p.h>
namespace Utils {
namespace Internal {
class RootInjectFSEngine : public QFSFileEngine
{
public:
using QFSFileEngine::QFSFileEngine;
public:
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override
{
std::unique_ptr<QAbstractFileEngineIterator> baseIterator(
QFSFileEngine::beginEntryList(filters, filterNames));
return new FileIteratorWrapper(std::move(baseIterator), filters, filterNames);
}
};
} // namespace Internal
} // namespace Utils

View File

@@ -49,14 +49,14 @@
#include <utils/fileutils.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QSet>
#include <QtCore/QBuffer>
#include <QtCore/QUrl>
#include <QtCore/QStack>
#include <QtCore/QDebug>
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QSet>
#include <QBuffer>
#include <QUrl>
#include <QStack>
#include <QDebug>
#include <algorithm>
#include <functional>

View File

@@ -49,12 +49,12 @@
#include "algorithm.h"
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QStandardPaths>
#include <QtCore/QBuffer>
#include <QtCore/QUrl>
#include <QtCore/QDebug>
#include <QFile>
#include <QFileInfo>
#include <QStandardPaths>
#include <QBuffer>
#include <QUrl>
#include <QDebug>
#include <algorithm>
#include <functional>

View File

@@ -33,6 +33,7 @@
#include "qtcassert.h"
#include "qtcprocess.h"
#include <QGuiApplication>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QMenu>
@@ -194,6 +195,7 @@ public:
QList<QAbstractButton *> m_buttons;
const MacroExpander *m_macroExpander = globalMacroExpander();
std::function<void()> m_openTerminal;
bool m_allowPathFromDevice = false;
};
PathChooserPrivate::PathChooserPrivate()
@@ -420,40 +422,46 @@ void PathChooser::slotBrowse()
case PathChooser::Directory:
case PathChooser::ExistingDirectory:
newPath = FileUtils::getExistingDirectory(this,
makeDialogTitle(tr("Choose Directory")), predefined);
makeDialogTitle(tr("Choose Directory")),
predefined);
break;
case PathChooser::ExistingCommand:
case PathChooser::Command:
newPath = FileUtils::getOpenFilePath(this,
makeDialogTitle(tr("Choose Executable")), predefined, d->m_dialogFilter);
makeDialogTitle(tr("Choose Executable")),
predefined,
d->m_dialogFilter,
nullptr,
{},
d->m_allowPathFromDevice);
newPath = appBundleExpandedPath(newPath);
break;
case PathChooser::File: // fall through
newPath = FileUtils::getOpenFilePath(this,
makeDialogTitle(tr("Choose File")), predefined, d->m_dialogFilter);
makeDialogTitle(tr("Choose File")),
predefined,
d->m_dialogFilter,
nullptr,
{},
d->m_allowPathFromDevice);
newPath = appBundleExpandedPath(newPath);
break;
case PathChooser::SaveFile:
newPath = FileUtils::getSaveFilePath(this,
makeDialogTitle(tr("Choose File")), predefined, d->m_dialogFilter);
makeDialogTitle(tr("Choose File")),
predefined,
d->m_dialogFilter);
break;
case PathChooser::Any: {
QFileDialog dialog(this);
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setWindowTitle(makeDialogTitle(tr("Choose File")));
if (predefined.exists())
dialog.setDirectory(predefined.absolutePath().toDir());
// FIXME: fix QFileDialog so that it filters properly: lib*.a
dialog.setNameFilter(d->m_dialogFilter);
if (dialog.exec() == QDialog::Accepted) {
// probably loop here until the *.framework dir match
QStringList paths = dialog.selectedFiles();
if (!paths.isEmpty())
newPath = FilePath::fromString(paths.at(0));
}
newPath = FileUtils::getOpenFilePath(this,
makeDialogTitle(tr("Choose File")),
predefined,
d->m_dialogFilter,
nullptr,
{},
d->m_allowPathFromDevice);
break;
}
}
default:
break;
}
@@ -758,4 +766,14 @@ void PathChooser::setCommandVersionArguments(const QStringList &arguments)
}
}
void PathChooser::setAllowPathFromDevice(bool allow)
{
d->m_allowPathFromDevice = allow;
}
bool PathChooser::allowPathFromDevice() const
{
return d->m_allowPathFromDevice;
}
} // namespace Utils

View File

@@ -158,6 +158,9 @@ public:
// setting an empty QString will disable this and clear the placeHolderText
void setDefaultValue(const QString &defaultValue);
void setAllowPathFromDevice(bool allow);
bool allowPathFromDevice() const;
private:
QString rawPath() const; // The raw unexpanded input.
bool validatePath(FancyLineEdit *edit, QString *errorMessage) const;

View File

@@ -28,6 +28,7 @@
#include "algorithm.h"
#include "hostosinfo.h"
#include "qtcassert.h"
#include "filepath.h"
#ifdef QT_WIDGETS_LIB
#include <QApplication>
@@ -119,6 +120,9 @@ QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path)
if (HostOsInfo::isWindowsHost())
return path;
if (FilePath::fromString(path).needsDevice())
return path;
static const QString homePath = QDir::homePath();
QFileInfo fi(QDir::cleanPath(path));
@@ -475,7 +479,6 @@ QTCREATOR_UTILS_EXPORT QString languageNameFromLanguageCode(const QString &langu
}
#ifdef QT_WIDGETS_LIB
QTCREATOR_UTILS_EXPORT void setClipboardAndSelection(const QString &text)
{
QClipboard *clipboard = QApplication::clipboard();
@@ -483,7 +486,14 @@ QTCREATOR_UTILS_EXPORT void setClipboardAndSelection(const QString &text)
if (clipboard->supportsSelection())
clipboard->setText(text, QClipboard::Selection);
}
#endif
QTCREATOR_UTILS_EXPORT QString chopIfEndsWith(QString str, QChar c)
{
if (str.endsWith(c))
str.chop(1);
return str;
}
} // namespace Utils

View File

@@ -130,4 +130,6 @@ QTCREATOR_UTILS_EXPORT void setClipboardAndSelection(const QString &text);
#endif
QTCREATOR_UTILS_EXPORT QString chopIfEndsWith(QString str, QChar c);
} // namespace Utils

View File

@@ -33,7 +33,7 @@ Project {
cpp.frameworks: ["Foundation", "AppKit"]
}
Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets", "xml"] }
Depends { name: "Qt"; submodules: ["concurrent", "core-private", "network", "qml", "widgets", "xml"] }
Depends { name: "Qt.macextras"; condition: Qt.core.versionMajor < 6 && qbs.targetOS.contains("macos") }
Depends { name: "app_version_header" }
@@ -133,6 +133,11 @@ Project {
"fixedsizeclicklabel.h",
"flowlayout.cpp",
"flowlayout.h",
"fsengine/fileiconprovider.cpp",
"fsengine/fileiconprovider.h",
"fsengine/qtcfsengine.cpp",
"fsengine/qtcfsengine.h",
"fsengine/qtcfsengine_p.h",
"functiontraits.h",
"futuresynchronizer.cpp",
"futuresynchronizer.h",

View File

@@ -30,10 +30,11 @@
#include "clangtoolsutils.h"
#include "diagnosticmark.h"
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <texteditor/textmark.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
@@ -58,7 +59,7 @@ QVariant FilePathItem::data(int column, int role) const
case Qt::DisplayRole:
return m_filePath.toUserOutput();
case Qt::DecorationRole:
return Core::FileIconProvider::icon(m_filePath);
return Utils::FileIconProvider::icon(m_filePath);
case Debugger::DetailedErrorView::FullTextRole:
return m_filePath.toUserOutput();
default:

View File

@@ -29,7 +29,6 @@
#include "cmakeprojectconstants.h"
#include <android/androidconstants.h>
#include <coreplugin/fileiconprovider.h>
#include <ios/iosconstants.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>

View File

@@ -41,13 +41,13 @@
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projecttree.h>
#include <texteditor/snippets/snippetprovider.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/parameteraction.h>
using namespace Core;

View File

@@ -25,10 +25,10 @@
#include "projecttreehelper.h"
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/algorithm.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/qtcassert.h>
using namespace ProjectExplorer;

View File

@@ -32,13 +32,13 @@
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/session.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/parameteraction.h>
#include <utils/utilsicons.h>
@@ -71,9 +71,9 @@ bool CompilationDatabaseProjectManagerPlugin::initialize(const QStringList &argu
d = new CompilationDatabaseProjectManagerPluginPrivate;
FileIconProvider::registerIconOverlayForFilename(Utils::Icons::PROJECT.imageFilePath().toString(),
Utils::FileIconProvider::registerIconOverlayForFilename(Utils::Icons::PROJECT.imageFilePath().toString(),
COMPILE_COMMANDS_JSON);
FileIconProvider::registerIconOverlayForFilename(
Utils::FileIconProvider::registerIconOverlayForFilename(
Utils::Icons::PROJECT.imageFilePath().toString(),
QString(COMPILE_COMMANDS_JSON) + Constants::COMPILATIONDATABASEPROJECT_FILES_SUFFIX);

View File

@@ -59,7 +59,6 @@ add_qtc_plugin(Core
fancyactionbar.qrc
fancytabwidget.cpp fancytabwidget.h
featureprovider.cpp featureprovider.h
fileiconprovider.cpp fileiconprovider.h
fileutils.cpp fileutils.h
find/basetextfind.cpp find/basetextfind.h
find/currentdocumentfind.cpp find/currentdocumentfind.h

View File

@@ -91,6 +91,7 @@ const char NEW[] = "QtCreator.New";
const char NEW_FILE[] = "QtCreator.NewFile";
const char OPEN[] = "QtCreator.Open";
const char OPEN_WITH[] = "QtCreator.OpenWith";
const char OPEN_FROM_DEVICE[] = "QtCreator.OpenFromDevice";
const char REVERTTOSAVED[] = "QtCreator.RevertToSaved";
const char SAVE[] = "QtCreator.Save";
const char SAVEAS[] = "QtCreator.SaveAs";

View File

@@ -67,8 +67,6 @@ Project {
"fancytabwidget.h",
"featureprovider.cpp",
"featureprovider.h",
"fileiconprovider.cpp",
"fileiconprovider.h",
"fileutils.cpp",
"fileutils.h",
"findplaceholder.cpp",

View File

@@ -27,7 +27,6 @@
#include "ui_readonlyfilesdialog.h"
#include <coreplugin/editormanager/editormanager_p.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/iversioncontrol.h>
@@ -35,6 +34,7 @@
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/hostosinfo.h>
#include <utils/stringutils.h>

View File

@@ -26,10 +26,10 @@
#include "saveitemsdialog.h"
#include <coreplugin/diffservice.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/idocument.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/hostosinfo.h>
#include <extensionsystem/pluginmanager.h>
@@ -78,7 +78,7 @@ SaveItemsDialog::SaveItemsDialog(QWidget *parent,
QTreeWidgetItem *item = new QTreeWidgetItem(m_ui.treeWidget, QStringList()
<< visibleName << QDir::toNativeSeparators(directory));
if (!filePath.isEmpty())
item->setIcon(0, FileIconProvider::icon(filePath));
item->setIcon(0, Utils::FileIconProvider::icon(filePath));
item->setData(0, Qt::UserRole, QVariant::fromValue(document));
}

View File

@@ -31,10 +31,10 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/editormanager_p.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
@@ -415,7 +415,7 @@ void EditorToolBar::updateDocumentStatus(IDocument *document)
if (document->filePath().isEmpty())
d->m_dragHandle->setIcon(QIcon());
else
d->m_dragHandle->setIcon(FileIconProvider::icon(document->filePath()));
d->m_dragHandle->setIcon(Utils::FileIconProvider::icon(document->filePath()));
d->m_editorList->setToolTip(document->filePath().isEmpty()
? document->displayName()

View File

@@ -32,7 +32,6 @@
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/fileutils.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
@@ -46,6 +45,7 @@
#include <utils/algorithm.h>
#include <utils/filecrumblabel.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/hostosinfo.h>
#include <utils/navigationtreeview.h>
#include <utils/qtcassert.h>
@@ -158,8 +158,26 @@ public:
protected:
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
};
bool FolderSortProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (static_cast<QFileSystemModel *>(sourceModel())->rootPath().isEmpty()) {
QModelIndex sourceIndex = sourceModel()->index(source_row, 0, source_parent);
while (sourceIndex.isValid()) {
if (sourceIndex.data().toString()
== FilePath::specialPath(FilePath::SpecialPathComponent::RootName)) {
return false;
}
sourceIndex = sourceIndex.parent();
}
}
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
FolderSortProxyModel::FolderSortProxyModel(QObject *parent)
: QSortFilterProxyModel(parent)
{
@@ -281,8 +299,9 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent
m_sortProxyModel->setSourceModel(m_fileSystemModel);
m_sortProxyModel->setSortRole(FolderNavigationModel::IsFolderRole);
m_sortProxyModel->sort(0);
m_fileSystemModel->setResolveSymlinks(false);
m_fileSystemModel->setIconProvider(Core::FileIconProvider::iconProvider());
m_fileSystemModel->setIconProvider(Utils::FileIconProvider::iconProvider());
QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot;
if (Utils::HostOsInfo::isWindowsHost()) // Symlinked directories can cause file watcher warnings on Win32.
filters |= QDir::NoSymLinks;
@@ -924,6 +943,17 @@ static FolderNavigationWidget *currentFolderNavigationWidget()
return qobject_cast<FolderNavigationWidget *>(Core::ICore::currentContextWidget());
}
void FolderNavigationWidgetFactory::addRootPath(Utils::Id id, const QString &displayName, const QIcon &icon, const Utils::FilePath &path)
{
if (path.isDir())
insertRootDirectory({id.toString(), 0, displayName, path, icon});
}
void FolderNavigationWidgetFactory::removeRootPath(Utils::Id id)
{
removeRootDirectory(id.toString());
}
void FolderNavigationWidgetFactory::registerActions()
{
Core::Context context(C_FOLDERNAVIGATIONWIDGET);

View File

@@ -80,6 +80,9 @@ public:
void saveSettings(Utils::QtcSettings *settings, int position, QWidget *widget) override;
void restoreSettings(QSettings *settings, int position, QWidget *widget) override;
void addRootPath(Utils::Id id, const QString &displayName, const QIcon &icon, const Utils::FilePath &path) override;
void removeRootPath(Utils::Id path) override;
static void insertRootDirectory(const RootDirectory &directory);
static void removeRootDirectory(const QString &id);

View File

@@ -28,6 +28,7 @@
#include "inavigationwidgetfactory.h"
#include <QIcon>
#include <QKeySequence>
/*!
@@ -171,3 +172,15 @@ void INavigationWidgetFactory::saveSettings(Utils::QtcSettings * /* settings */,
void INavigationWidgetFactory::restoreSettings(QSettings * /* settings */, int /* position */, QWidget * /* widget */)
{
}
// Registers a new root path in the factory
void INavigationWidgetFactory::addRootPath(Utils::Id /*id*/, const QString & /*displayName*/, const QIcon & /*icon*/, const Utils::FilePath & /*path*/)
{
}
// Removes a root path from the factory
void INavigationWidgetFactory::removeRootPath(Utils::Id /*path*/)
{
}

View File

@@ -27,6 +27,7 @@
#include "core_global.h"
#include <utils/filepath.h>
#include <utils/id.h>
#include <QObject>
@@ -80,6 +81,9 @@ public:
virtual void saveSettings(Utils::QtcSettings *settings, int position, QWidget *widget);
virtual void restoreSettings(QSettings *settings, int position, QWidget *widget);
virtual void addRootPath(Utils::Id id, const QString &displayName, const QIcon &icon, const Utils::FilePath &path);
virtual void removeRootPath(Utils::Id id);
private:
QString m_displayName;
int m_priority = 0;

View File

@@ -33,12 +33,12 @@
#include <coreplugin/icore.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icontext.h>
#include <coreplugin/mainwindow.h>
#include <utils/algorithm.h>
#include <utils/appmainwindow.h>
#include <utils/fancylineedit.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/highlightingitemdelegate.h>
#include <utils/hostosinfo.h>
#include <utils/itemviews.h>

View File

@@ -72,6 +72,8 @@
#include <coreplugin/settingsdatabase.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/fsengine/fsengine.h>
#include <utils/historycompleter.h>
#include <utils/hostosinfo.h>
#include <utils/mimeutils.h>
@@ -83,6 +85,7 @@
#include <utils/touchbar/touchbar.h>
#include <utils/utilsicons.h>
#include <QAbstractProxyModel>
#include <QActionGroup>
#include <QApplication>
#include <QBrush>
@@ -93,11 +96,13 @@
#include <QDialogButtonBox>
#include <QDir>
#include <QFileInfo>
#include <QFileSystemModel>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QPrinter>
#include <QSettings>
#include <QSortFilterProxyModel>
#include <QStatusBar>
#include <QStyleFactory>
#include <QSyntaxHighlighter>
@@ -114,6 +119,17 @@ using namespace Utils;
namespace Core {
namespace Internal {
static const char settingsGroup[] = "MainWindow";
static const char colorKey[] = "Color";
static const char askBeforeExitKey[] = "AskBeforeExit";
static const char windowGeometryKey[] = "WindowGeometry";
static const char windowStateKey[] = "WindowState";
static const char modeSelectorLayoutKey[] = "ModeSelectorLayout";
static const char openFromDeviceDialogKey[] = "OpenFromDeviceDialog";
static const bool askBeforeExitDefault = false;
enum { debugMainWindow = 0 };
MainWindow::MainWindow()
@@ -583,6 +599,14 @@ void MainWindow::registerDefaultActions()
mfile->addAction(cmd, Constants::G_FILE_OPEN);
connect(m_openWithAction, &QAction::triggered, this, &MainWindow::openFileWith);
if (FSEngine::isAvailable()) {
// Open From Device Action
m_openFromDeviceAction = new QAction(Tr::tr("Open From Device..."), this);
cmd = ActionManager::registerAction(m_openFromDeviceAction, Constants::OPEN_FROM_DEVICE);
mfile->addAction(cmd, Constants::G_FILE_OPEN);
connect(m_openFromDeviceAction, &QAction::triggered, this, &MainWindow::openFileFromDevice);
}
// File->Recent Files Menu
ActionContainer *ac = ActionManager::createMenu(Constants::M_FILE_RECENTFILES);
mfile->addMenu(ac, Constants::G_FILE_OPEN);
@@ -1043,6 +1067,41 @@ void MainWindow::openFileWith()
}
}
void MainWindow::openFileFromDevice()
{
QSettings *settings = PluginManager::settings();
settings->beginGroup(QLatin1String(settingsGroup));
QVariant dialogSettings = settings->value(QLatin1String(openFromDeviceDialogKey));
QFileDialog dialog;
dialog.setOption(QFileDialog::DontUseNativeDialog);
if (!dialogSettings.isNull()) {
dialog.restoreState(dialogSettings.toByteArray());
}
QList<QUrl> sideBarUrls = Utils::transform(Utils::filtered(FSEngine::registeredDeviceRoots(),
[](const auto &filePath) {
return filePath.exists();
}),
[](const auto &filePath) {
return QUrl::fromLocalFile(filePath.toFSPathString());
});
dialog.setSidebarUrls(sideBarUrls);
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setIconProvider(FileIconProvider::iconProvider());
if (dialog.exec()) {
FilePaths filePaths = Utils::transform(dialog.selectedFiles(), [](const auto &path) {
return FilePath::fromString(path);
});
openFiles(filePaths, ICore::SwitchMode);
}
settings->setValue(QLatin1String(openFromDeviceDialogKey), dialog.saveState());
settings->endGroup();
}
IContext *MainWindow::contextObject(QWidget *widget) const
{
const auto it = m_contextWidgets.find(widget);
@@ -1126,15 +1185,6 @@ void MainWindow::aboutToShutdown()
hide();
}
static const char settingsGroup[] = "MainWindow";
static const char colorKey[] = "Color";
static const char askBeforeExitKey[] = "AskBeforeExit";
static const char windowGeometryKey[] = "WindowGeometry";
static const char windowStateKey[] = "WindowState";
static const char modeSelectorLayoutKey[] = "ModeSelectorLayout";
static const bool askBeforeExitDefault = false;
void MainWindow::readSettings()
{
QSettings *settings = PluginManager::settings();

View File

@@ -116,6 +116,8 @@ public:
void restart();
void openFileFromDevice();
public slots:
static void openFileWith();
void exit();
@@ -186,6 +188,7 @@ private:
QAction *m_newAction = nullptr;
QAction *m_openAction = nullptr;
QAction *m_openWithAction = nullptr;
QAction *m_openFromDeviceAction = nullptr;
QAction *m_saveAllAction = nullptr;
QAction *m_exitAction = nullptr;
QAction *m_optionsAction = nullptr;

View File

@@ -25,10 +25,9 @@
#include "cppcheckdiagnosticsmodel.h"
#include <coreplugin/fileiconprovider.h>
#include <debugger/analyzer/diagnosticlocation.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/utilsicons.h>
namespace Cppcheck {
@@ -47,7 +46,7 @@ QVariant FilePathItem::data(int column, int role) const
case Qt::DisplayRole:
return m_filePath;
case Qt::DecorationRole:
return Core::FileIconProvider::icon(Utils::FilePath::fromString(m_filePath));
return Utils::FileIconProvider::icon(Utils::FilePath::fromString(m_filePath));
case Debugger::DetailedErrorView::FullTextRole:
return m_filePath;
default:

View File

@@ -83,7 +83,6 @@
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditorfactory.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/navigationwidget.h>
@@ -105,6 +104,7 @@
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/hostosinfo.h>
#include <utils/macroexpander.h>
#include <utils/mimeutils.h>

View File

@@ -35,7 +35,6 @@
#include "cppmodelmanager.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/find/itemviewfind.h>
#include <cplusplus/CppDocument.h>
@@ -45,6 +44,7 @@
#include <utils/delegates.h>
#include <utils/dropsupport.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/navigationtreeview.h>
#include <utils/qtcassert.h>
#include <utils/qtcsettings.h>

View File

@@ -318,6 +318,7 @@ DebuggerItemConfigWidget::DebuggerItemConfigWidget()
item.reinitializeFromFile({}, errorMessage);
return errorMessage->isEmpty();
});
m_binaryChooser->setAllowPathFromDevice(true);
m_workingDirectoryChooser = new PathChooser(this);
m_workingDirectoryChooser->setExpectedKind(PathChooser::Directory);

View File

@@ -28,14 +28,15 @@
#include "formwindoweditor.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/fsengine/fileiconprovider.h>
#include <QCoreApplication>
#include <QDebug>
using namespace Core;
using namespace Designer::Constants;
using namespace Utils;
namespace Designer {
namespace Internal {

View File

@@ -28,6 +28,7 @@
namespace Docker::Constants {
const char DOCKER[] = "docker";
const char DOCKER_DEVICE_SCHEME[] = "docker";
const char DOCKER_SETTINGS_ID[] = "Docker.Settings";
const char DOCKER_DEVICE_TYPE[] = "DockerDeviceType";

View File

@@ -641,6 +641,15 @@ QString DockerDevice::mapToDevicePath(const Utils::FilePath &globalPath) const
return path;
}
Utils::FilePath DockerDevice::rootPath() const
{
FilePath root;
root.setScheme(Constants::DOCKER_DEVICE_SCHEME);
root.setHost(d->m_data.repoAndTag());
root.setPath("/");
return root;
}
bool DockerDevice::handlesFile(const FilePath &filePath) const
{
if (filePath.scheme() == "device" && filePath.host() == id().toString())

View File

@@ -81,6 +81,8 @@ public:
Utils::FilePath mapToGlobalPath(const Utils::FilePath &pathOnDevice) const override;
QString mapToDevicePath(const Utils::FilePath &globalPath) const override;
Utils::FilePath rootPath() const override;
bool handlesFile(const Utils::FilePath &filePath) const override;
bool isExecutableFile(const Utils::FilePath &filePath) const override;
bool isReadableFile(const Utils::FilePath &filePath) const override;

View File

@@ -26,11 +26,13 @@
#include "dockerplugin.h"
#include "dockerapi.h"
#include "dockerconstants.h"
#include "dockerdevice.h"
#include "dockersettings.h"
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/fsengine/fsengine.h>
#include <utils/qtcassert.h>
using namespace Core;
@@ -57,6 +59,7 @@ static DockerPlugin *s_instance = nullptr;
DockerPlugin::DockerPlugin()
{
s_instance = this;
FSEngine::registerDeviceScheme(Constants::DOCKER_DEVICE_SCHEME);
}
DockerApi *DockerPlugin::dockerApi()
@@ -67,6 +70,7 @@ DockerApi *DockerPlugin::dockerApi()
DockerPlugin::~DockerPlugin()
{
FSEngine::unregisterDeviceScheme(Constants::DOCKER_DEVICE_SCHEME);
s_instance = nullptr;
delete d;
}

View File

@@ -38,9 +38,10 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <utils/fsengine/fileiconprovider.h>
#include <QMenu>
using namespace Core;

View File

@@ -37,13 +37,14 @@
#include "settings/tools/toolssettingsaccessor.h"
#include "settings/tools/toolssettingspage.h"
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/runcontrol.h>
#include <utils/fsengine/fileiconprovider.h>
using namespace Core;
using namespace ProjectExplorer;
using namespace Utils;

View File

@@ -25,11 +25,10 @@
#pragma once
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/projectnodes.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
namespace MesonProjectManager {
namespace Internal {

View File

@@ -43,8 +43,6 @@
#include "settings/nimsettings.h"
#include "suggest/nimsuggestcache.h"
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/runcontrol.h>
@@ -53,6 +51,8 @@
#include <texteditor/snippets/snippetprovider.h>
#include <utils/fsengine/fileiconprovider.h>
using namespace Utils;
using namespace ProjectExplorer;
@@ -128,13 +128,13 @@ bool NimPlugin::initialize(const QStringList &arguments, QString *errorMessage)
void NimPlugin::extensionsInitialized()
{
// Add MIME overlay icons (these icons displayed at Project dock panel)
const QIcon icon = Utils::Icon({{":/nim/images/settingscategory_nim.png",
Utils::Theme::PanelTextColorDark
}}, Utils::Icon::Tint).icon();
const QIcon icon = Icon({{":/nim/images/settingscategory_nim.png",
Theme::PanelTextColorDark
}}, Icon::Tint).icon();
if (!icon.isNull()) {
Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_MIMETYPE);
Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_SCRIPT_MIMETYPE);
Core::FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIMBLE_MIMETYPE);
FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_MIMETYPE);
FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIM_SCRIPT_MIMETYPE);
FileIconProvider::registerIconOverlayForMimeType(icon, Constants::C_NIMBLE_MIMETYPE);
}
TaskHub::addCategory(Constants::C_NIMPARSE_ID, "Nim");
}

View File

@@ -27,11 +27,11 @@
#include "project.h"
#include "session.h"
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <utils/detailswidget.h>
#include <utils/algorithm.h>
#include <utils/detailswidget.h>
#include <utils/fsengine/fileiconprovider.h>
#include <QDebug>
#include <QSize>
@@ -99,7 +99,7 @@ QVariant DependenciesModel::data(const QModelIndex &index, int role) const
case Qt::CheckStateRole:
return SessionManager::hasDependency(m_project, p) ? Qt::Checked : Qt::Unchecked;
case Qt::DecorationRole:
return Core::FileIconProvider::icon(p->projectFilePath());
return Utils::FileIconProvider::icon(p->projectFilePath());
default:
return QVariant();
}

View File

@@ -34,6 +34,7 @@
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fsengine.h>
#include <utils/persistentsettings.h>
#include <utils/portlist.h>
#include <utils/qtcassert.h>
@@ -304,6 +305,10 @@ void DeviceManager::addDevice(const IDevice::ConstPtr &_device)
d->devices << device;
}
emit deviceAdded(device->id());
if (FSEngine::isAvailable()) {
Utils::FSEngine::addDevice(device->rootPath());
}
}
emit updated();
@@ -323,6 +328,10 @@ void DeviceManager::removeDevice(Utils::Id id)
}
emit deviceRemoved(device->id());
if (FSEngine::isAvailable()) {
Utils::FSEngine::removeDevice(device->rootPath());
}
if (wasDefault) {
for (int i = 0; i < d->devices.count(); ++i) {
if (deviceAt(i)->type() == deviceType) {

View File

@@ -205,7 +205,7 @@ public:
MachineType machineType() const;
void setMachineType(MachineType machineType);
Utils::FilePath rootPath() const;
virtual Utils::FilePath rootPath() const;
Utils::FilePath filePath(const QString &pathOnDevice) const;
Utils::FilePath debugServerPath() const;

View File

@@ -1341,6 +1341,7 @@ GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) :
m_compilerCommand->setExpectedKind(PathChooser::ExistingCommand);
m_compilerCommand->setCommandVersionArguments(gnuVersionArgs);
m_compilerCommand->setHistoryCompleter("PE.Gcc.Command.History");
m_compilerCommand->setAllowPathFromDevice(true);
m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
m_platformCodeGenFlagsLineEdit = new QLineEdit(this);
m_platformCodeGenFlagsLineEdit->setText(ProcessArgs::joinArgs(tc->platformCodeGenFlags()));

View File

@@ -35,13 +35,13 @@
#include <app/app_version.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
#include <utils/utilsicons.h>
#include <utils/algorithm.h>
#include <utils/dropsupport.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/pathchooser.h>
#include <utils/stringutils.h>
#include <utils/theme/theme.h>

View File

@@ -32,12 +32,12 @@
#include "projecttree.h"
#include "target.h"
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/hostosinfo.h>
#include <utils/mimeutils.h>
#include <utils/pointeralgorithm.h>
@@ -257,7 +257,7 @@ QIcon FileNode::icon() const
if (hasError())
return Utils::Icons::WARNING.icon();
if (m_icon.isNull())
m_icon = Core::FileIconProvider::icon(filePath());
m_icon = Utils::FileIconProvider::icon(filePath());
return m_icon;
}
@@ -479,7 +479,7 @@ QIcon FolderNode::icon() const
} else {
auto iconPtr = Utils::get_if<QIcon>(&m_icon);
if (!iconPtr || iconPtr->isNull())
m_icon = Core::FileIconProvider::icon(QFileIconProvider::Folder);
m_icon = Utils::FileIconProvider::icon(QFileIconProvider::Folder);
}
return Utils::get<QIcon>(m_icon);
}
@@ -1089,7 +1089,7 @@ QIcon DirectoryIcon::icon() const
const auto it = m_cache.find(m_overlay);
if (it != m_cache.end())
return it.value();
const QIcon icon = Core::FileIconProvider::directoryIcon(m_overlay);
const QIcon icon = Utils::FileIconProvider::directoryIcon(m_overlay);
m_cache.insert(m_overlay, icon);
return icon;
}

View File

@@ -514,24 +514,22 @@ void RunControl::initiateFinish()
RunWorker *RunControl::createWorker(Utils::Id workerId)
{
const auto check = std::bind(&RunWorkerFactory::canRun,
std::placeholders::_1,
workerId,
DeviceTypeKitAspect::deviceTypeId(d->kit),
QString{});
RunWorkerFactory *factory = Utils::findOrDefault(g_runWorkerFactories, check);
RunWorkerFactory *factory
= Utils::findOrDefault(g_runWorkerFactories, [this, workerId](RunWorkerFactory *factory) {
return factory->canRun(workerId, DeviceTypeKitAspect::deviceTypeId(d->kit), QString{});
});
return factory ? factory->producer()(this) : nullptr;
}
bool RunControl::createMainWorker()
{
const auto canRun = std::bind(&RunWorkerFactory::canRun,
std::placeholders::_1,
d->runMode,
DeviceTypeKitAspect::deviceTypeId(d->kit),
d->runConfigId.toString());
const QList<RunWorkerFactory *> candidates
= Utils::filtered(g_runWorkerFactories, [this](RunWorkerFactory *factory) {
return factory->canRun(d->runMode,
DeviceTypeKitAspect::deviceTypeId(d->kit),
d->runConfigId.toString());
});
const QList<RunWorkerFactory *> candidates = Utils::filtered(g_runWorkerFactories, canRun);
// There might be combinations that cannot run. But that should have been checked
// with canRun below.
QTC_ASSERT(!candidates.empty(), return false);

View File

@@ -26,11 +26,11 @@
#include "selectablefilesmodel.h"
#include "projectexplorerconstants.h"
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <utils/algorithm.h>
#include <utils/fancylineedit.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/pathchooser.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h>
@@ -231,7 +231,7 @@ QVariant SelectableFilesModel::data(const QModelIndex &index, int role) const
return t->checked;
if (role == Qt::DecorationRole) {
if (t->icon.isNull())
t->icon = Core::FileIconProvider::icon(t->fullPath);
t->icon = Utils::FileIconProvider::icon(t->fullPath);
return t->icon;
}
return QVariant();

View File

@@ -31,8 +31,6 @@
#include "pythonsettings.h"
#include "pythonrunconfiguration.h"
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/localenvironmentaspect.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -40,6 +38,7 @@
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/taskhub.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/theme/theme.h>
using namespace ProjectExplorer;
@@ -100,7 +99,7 @@ void PythonPlugin::extensionsInitialized()
// Add MIME overlay icons (these icons displayed at Project dock panel)
QString imageFile = Utils::creatorTheme()->imageFile(Utils::Theme::IconOverlayPro,
::Constants::FILEOVERLAY_PY);
Core::FileIconProvider::registerIconOverlayForSuffix(imageFile, "py");
Utils::FileIconProvider::registerIconOverlayForSuffix(imageFile, "py");
TaskHub::addCategory(PythonErrorTaskCategory, "Python", true);
}

View File

@@ -32,13 +32,14 @@
#include "qbssession.h"
#include <android/androidconstants.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/idocument.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtsupportconstants.h>
#include <resourceeditor/resourcenode.h>
#include <utils/algorithm.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>

View File

@@ -46,7 +46,6 @@
#include <coreplugin/helpmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/project.h>
@@ -63,6 +62,7 @@
#include <qmljstools/qmljstoolsconstants.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
@@ -112,7 +112,7 @@ bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *
const Core::Context projectContext(::QbsProjectManager::Constants::PROJECT_ID);
Core::FileIconProvider::registerIconOverlayForSuffix(ProjectExplorer::Constants::FILEOVERLAY_QT, "qbs");
Utils::FileIconProvider::registerIconOverlayForSuffix(ProjectExplorer::Constants::FILEOVERLAY_QT, "qbs");
Core::HelpManager::registerDocumentation({Core::HelpManager::documentationPath() + "/qbs.qch"});
ProjectManager::registerProjectType<QbsProject>(QmlJSTools::Constants::QBS_MIMETYPE);

View File

@@ -32,7 +32,6 @@
#include "qmakeproject.h"
#include "qmakeprojectmanagerconstants.h"
#include <coreplugin/fileiconprovider.h>
#include <extensionsystem/pluginmanager.h>
#include <qtsupport/qtsupportconstants.h>
#include <projectexplorer/buildconfiguration.h>
@@ -41,6 +40,7 @@
#include <projectexplorer/session.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/textdocument.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/qtcassert.h>
#include <utils/theme/theme.h>
@@ -298,11 +298,11 @@ ProFileEditorFactory::ProFileEditorFactory()
setSyntaxHighlighterCreator([]() { return new ProFileHighlighter; });
const QString defaultOverlay = QLatin1String(ProjectExplorer::Constants::FILEOVERLAY_QT);
Core::FileIconProvider::registerIconOverlayForSuffix(
Utils::FileIconProvider::registerIconOverlayForSuffix(
creatorTheme()->imageFile(Theme::IconOverlayPro, defaultOverlay), "pro");
Core::FileIconProvider::registerIconOverlayForSuffix(
Utils::FileIconProvider::registerIconOverlayForSuffix(
creatorTheme()->imageFile(Theme::IconOverlayPri, defaultOverlay), "pri");
Core::FileIconProvider::registerIconOverlayForSuffix(
Utils::FileIconProvider::registerIconOverlayForSuffix(
creatorTheme()->imageFile(Theme::IconOverlayPrf, defaultOverlay), "prf");
}

View File

@@ -27,7 +27,6 @@
#include "qmakeproject.h"
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <qtsupport/baseqtversion.h>
@@ -35,6 +34,7 @@
#include <resourceeditor/resourcenode.h>
#include <utils/algorithm.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/qtcassert.h>
using namespace Core;
@@ -112,12 +112,12 @@ QmakeStaticData::QmakeStaticData()
const QString filter = QString::fromUtf8(fileType.addFileFilter);
fileTypeData.push_back(QmakeStaticData::FileTypeData(fileType.type,
desc, filter,
Core::FileIconProvider::directoryIcon(QLatin1String(fileType.icon))));
Utils::FileIconProvider::directoryIcon(QLatin1String(fileType.icon))));
}
// Project icon
projectIcon = Core::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_QT);
productIcon = Core::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_PRODUCT);
groupIcon = Core::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_GROUP);
projectIcon = Utils::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_QT);
productIcon = Utils::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_PRODUCT);
groupIcon = Utils::FileIconProvider::directoryIcon(ProjectExplorer::Constants::FILEOVERLAY_GROUP);
qAddPostRoutine(clearQmakeStaticData);
}

View File

@@ -43,7 +43,6 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
@@ -55,6 +54,7 @@
#include <texteditor/snippets/snippetprovider.h>
#include <texteditor/texteditorconstants.h>
#include <texteditor/tabsettings.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/qtcassert.h>
#include <utils/json.h>

View File

@@ -25,7 +25,7 @@
#include "qmlprojectnodes.h"
#include <coreplugin/fileiconprovider.h>
#include <utils/fsengine/fileiconprovider.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>

View File

@@ -38,7 +38,6 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/designmode.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
#include <coreplugin/modemanager.h>
@@ -62,6 +61,7 @@
#include <extensionsystem/pluginspec.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/qtcprocess.h>
#include <QAction>
@@ -286,7 +286,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
}
ProjectManager::registerProjectType<QmlProject>(QmlJSTools::Constants::QMLPROJECT_MIMETYPE);
Core::FileIconProvider::registerIconOverlayForSuffix(":/qmlproject/images/qmlproject.png",
Utils::FileIconProvider::registerIconOverlayForSuffix(":/qmlproject/images/qmlproject.png",
"qmlproject");
if (QmlProject::isQtDesignStudio()) {

View File

@@ -60,6 +60,7 @@
#include <QDialogButtonBox>
#include <QDir>
#include <QFormLayout>
#include <QGuiApplication>
#include <QHeaderView>
#include <QLabel>
#include <QMessageBox>
@@ -644,12 +645,15 @@ QtOptionsPageWidget::~QtOptionsPageWidget()
void QtOptionsPageWidget::addQtDir()
{
FilePath qtVersion = FileUtils::getOpenFilePath(this,
tr("Select a qmake Executable"),
{},
BuildableHelperLibrary::filterForQmakeFileDialog(),
0,
QFileDialog::DontResolveSymlinks);
FilePath qtVersion
= FileUtils::getOpenFilePath(this,
tr("Select a qmake Executable"),
{},
BuildableHelperLibrary::filterForQmakeFileDialog(),
nullptr,
QFileDialog::DontResolveSymlinks,
true);
if (qtVersion.isEmpty())
return;
@@ -1025,6 +1029,7 @@ void QtOptionsPageWidget::linkWithQt()
});
const Utils::optional<FilePath> currentLink = currentlyLinkedQtDir(nullptr);
pathInput->setFilePath(currentLink ? *currentLink : defaultQtInstallationPath());
pathInput->setAllowPathFromDevice(true);
auto buttons = new QDialogButtonBox;
layout->addStretch(10);
layout->addWidget(buttons);

View File

@@ -1046,6 +1046,15 @@ QString LinuxDevice::userAtHost() const
return sshParameters().userAtHost();
}
Utils::FilePath LinuxDevice::rootPath() const
{
Utils::FilePath root;
root.setScheme("ssh");
root.setHost(userAtHost());
root.setPath("/");
return root;
}
bool LinuxDevice::handlesFile(const FilePath &filePath) const
{
if (filePath.scheme() == "device" && filePath.host() == id().toString())

View File

@@ -57,6 +57,8 @@ public:
QString userAtHost() const;
Utils::FilePath rootPath() const override;
bool handlesFile(const Utils::FilePath &filePath) const override;
bool isExecutableFile(const Utils::FilePath &filePath) const override;
bool isReadableFile(const Utils::FilePath &filePath) const override;

View File

@@ -49,7 +49,10 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <utils/fsengine/fsengine.h>
using namespace ProjectExplorer;
using namespace Utils;
namespace RemoteLinux {
namespace Internal {
@@ -114,10 +117,12 @@ static RemoteLinuxPluginPrivate *dd = nullptr;
RemoteLinuxPlugin::RemoteLinuxPlugin()
{
setObjectName(QLatin1String("RemoteLinuxPlugin"));
FSEngine::registerDeviceScheme("ssh");
}
RemoteLinuxPlugin::~RemoteLinuxPlugin()
{
FSEngine::unregisterDeviceScheme("ssh");
delete dd;
}

View File

@@ -25,7 +25,6 @@
#include "resourcefile_p.h"
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/fileutils.h>
#include <coreplugin/icore.h>
#include <coreplugin/vcsmanager.h>
@@ -33,6 +32,7 @@
#include <utils/algorithm.h>
#include <utils/filepath.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/removefiledialog.h>
#include <utils/theme/theme.h>
@@ -580,7 +580,7 @@ void ResourceFile::clearPrefixList()
ResourceModel::ResourceModel(QObject *parent)
: QAbstractItemModel(parent), m_dirty(false)
{
static QIcon resourceFolderIcon = Core::FileIconProvider::directoryIcon(QLatin1String(ProjectExplorer::Constants::FILEOVERLAY_QRC));
static QIcon resourceFolderIcon = Utils::FileIconProvider::directoryIcon(QLatin1String(ProjectExplorer::Constants::FILEOVERLAY_QRC));
m_prefixIcon = resourceFolderIcon;
}
@@ -797,7 +797,7 @@ QVariant ResourceModel::data(const QModelIndex &index, int role) const
if (iconFileExtension(path))
file->icon = QIcon(path);
else
file->icon = Core::FileIconProvider::icon(Utils::FilePath::fromString(path));
file->icon = Utils::FileIconProvider::icon(Utils::FilePath::fromString(path));
}
if (!file->icon.isNull())
result = file->icon;

View File

@@ -28,9 +28,9 @@
#include "resourceeditorplugin.h"
#include "resourceeditorconstants.h"
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/fsengine/fileiconprovider.h>
#include <QCoreApplication>
#include <QFileInfo>
@@ -45,7 +45,7 @@ ResourceEditorFactory::ResourceEditorFactory(ResourceEditorPlugin *plugin)
setMimeTypes(QStringList(QLatin1String(C_RESOURCE_MIMETYPE)));
setDisplayName(QCoreApplication::translate("OpenWith::Editors", C_RESOURCEEDITOR_DISPLAY_NAME));
Core::FileIconProvider::registerIconOverlayForSuffix(
Utils::FileIconProvider::registerIconOverlayForSuffix(
ProjectExplorer::Constants::FILEOVERLAY_QRC, "qrc");
setEditorCreator([plugin] {

View File

@@ -28,12 +28,12 @@
#include "qrceditor/resourcefile_p.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/fileiconprovider.h>
#include <qmljstools/qmljstoolsconstants.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/mimeutils.h>
#include <utils/qtcassert.h>
#include <utils/threadutils.h>

View File

@@ -29,8 +29,8 @@
#include "scxmleditordata.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/fsengine/fileiconprovider.h>
#include <QGuiApplication>
#include <QFileInfo>
@@ -44,7 +44,7 @@ ScxmlEditorFactory::ScxmlEditorFactory()
setDisplayName(QCoreApplication::translate("ScxmlEditor", C_SCXMLEDITOR_DISPLAY_NAME));
addMimeType(ProjectExplorer::Constants::SCXML_MIMETYPE);
Core::FileIconProvider::registerIconOverlayForSuffix(":/projectexplorer/images/fileoverlay_scxml.png", "scxml");
Utils::FileIconProvider::registerIconOverlayForSuffix(":/projectexplorer/images/fileoverlay_scxml.png", "scxml");
setEditorCreator([this] {
if (!m_editorData) {

View File

@@ -25,8 +25,8 @@
#include "submitfilemodel.h"
#include <coreplugin/fileiconprovider.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fileiconprovider.h>
#include <utils/qtcassert.h>
#include <utils/theme/theme.h>
@@ -88,8 +88,8 @@ static QList<QStandardItem *> createFileRow(const QString &repositoryRoot,
fileItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
// For some reason, Windows (at least) requires a valid (existing) file path to the icon, so
// the repository root is needed here.
// Note: for "overlaid" icons in Core::FileIconProvider a valid file path is not required
fileItem->setIcon(Core::FileIconProvider::icon(
// Note: for "overlaid" icons in Utils::FileIconProvider a valid file path is not required
fileItem->setIcon(Utils::FileIconProvider::icon(
Utils::FilePath::fromString(repositoryRoot).pathAppended(fileName)));
const QList<QStandardItem *> row{statusItem, fileItem};
if (statusHint != SubmitFileModel::FileStatusUnknown) {

View File

@@ -0,0 +1,4 @@
add_qtc_test(tst_filesystemmodel
DEPENDS Utils
SOURCES tst_filesystemmodel.cpp ../../../src/shared/modeltest/modeltest.cpp
)

View File

@@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "../../../src/shared/modeltest/modeltest.h"
#include <utils/filesystemmodel/filesystemmodel.h>
#include <QCoreApplication>
#include <QDebug>
#include <QLocalSocket>
#include <QNetworkAccessManager>
#include <QProcess>
#include <QtTest>
#ifndef WITH_TESTS
#define WITH_TESTS
#endif
class FileSystemModelTest : public ModelTest
{
Q_OBJECT
public:
FileSystemModelTest()
: ModelTest(new Utils::FileSystemModel())
{
static_cast<Utils::FileSystemModel*>(this->model())->setRootPath("/");
}
private slots:
void qTestWithTestClass() {
Utils::FileSystemModel modelToBeTested;
modelToBeTested.setRootPath("/");
auto tester = new QAbstractItemModelTester(&modelToBeTested);
}
void testWithSortFilterProxyModel() {
Utils::FileSystemModel modelToBeTested;
QSortFilterProxyModel proxyModel;
proxyModel.setSourceModel(&modelToBeTested);
proxyModel.setSortRole(Qt::UserRole + 50);
proxyModel.sort(0);
modelToBeTested.setRootPath("/");
auto tester = new QAbstractItemModelTester(&proxyModel);
}
};
QTEST_MAIN(FileSystemModelTest)
#include "tst_filesystemmodel.moc"

View File

@@ -10,3 +10,4 @@ add_subdirectory(templateengine)
add_subdirectory(treemodel)
add_subdirectory(multicursor)
add_subdirectory(deviceshell)
add_subdirectory(fsengine)

View File

@@ -56,6 +56,10 @@ private slots:
void relativePath();
void fromToString_data();
void fromToString();
void fromString_data();
void fromString();
void toString_data();
void toString();
void comparison_data();
void comparison();
void linkFromString_data();
@@ -281,6 +285,83 @@ void tst_fileutils::relativePath()
QCOMPARE(actualPath.toString(), result);
}
void tst_fileutils::toString_data()
{
QTest::addColumn<QString>("scheme");
QTest::addColumn<QString>("host");
QTest::addColumn<QString>("path");
QTest::addColumn<QString>("result");
QTest::addColumn<QString>("userResult");
QTest::newRow("empty") << "" << "" << "" << "" << "";
QTest::newRow("scheme") << "http" << "" << "" << QDir::rootPath() + "__qtc_devices__/http//./" << "http:///./";
QTest::newRow("scheme-and-host") << "http" << "127.0.0.1" << "" << QDir::rootPath() + "__qtc_devices__/http/127.0.0.1/./" << "http://127.0.0.1/./";
QTest::newRow("root") << "http" << "127.0.0.1" << "/" << QDir::rootPath() + "__qtc_devices__/http/127.0.0.1/" << "http://127.0.0.1/";
QTest::newRow("root-folder") << "" << "" << "/" << "/" << "/";
QTest::newRow("qtc-dev-root-folder") << "" << "" << QDir::rootPath() + "__qtc_devices__" << QDir::rootPath() + "__qtc_devices__" << QDir::rootPath() + "__qtc_devices__";
QTest::newRow("qtc-dev-type-root-folder") << "" << "" << QDir::rootPath() + "__qtc_devices__/docker" << QDir::rootPath() + "__qtc_devices__/docker" << QDir::rootPath() + "__qtc_devices__/docker";
QTest::newRow("qtc-root-folder") << "docker" << "alpine:latest" << "/" << QDir::rootPath() + "__qtc_devices__/docker/alpine:latest/" << "docker://alpine:latest/";
QTest::newRow("qtc-root-folder-rel") << "docker" << "alpine:latest" << "" << QDir::rootPath() + "__qtc_devices__/docker/alpine:latest/./" << "docker://alpine:latest/./";
}
void tst_fileutils::toString()
{
QFETCH(QString, scheme);
QFETCH(QString, host);
QFETCH(QString, path);
QFETCH(QString, result);
QFETCH(QString, userResult);
FilePath filePath;
filePath.setScheme(scheme);
filePath.setHost(host);
filePath.setPath(path);
QCOMPARE(filePath.toString(), result);
QCOMPARE(filePath.toUserOutput(), userResult);
}
void tst_fileutils::fromString_data()
{
QTest::addColumn<QString>("input");
QTest::addColumn<QString>("scheme");
QTest::addColumn<QString>("host");
QTest::addColumn<QString>("path");
QTest::newRow("empty") << "" << "" << "" << "";
QTest::newRow("unix-root") << "/" << "" << "" << "/";
QTest::newRow("unix-folder") << "/tmp" << "" << "" << "/tmp";
QTest::newRow("unix-folder-with-trailing-slash") << "/tmp/" << "" << "" << "/tmp/";
QTest::newRow("windows-root") << "c:" << "" << "" << "c:";
QTest::newRow("windows-folder") << "c:\\Windows" << "" << "" << "c:\\Windows";
QTest::newRow("windows-folder-with-trailing-slash") << "c:\\Windows\\" << "" << "" << "c:\\Windows\\";
QTest::newRow("windows-folder-slash") << "C:/Windows" << "" << "" << "C:/Windows";
QTest::newRow("docker-root-url") << "docker://1234/" << "docker" << "1234" << "/";
QTest::newRow("docker-root-url-special") << QDir::rootPath() + "__qtc_devices__/docker/1234/" << "docker" << "1234" << "/";
QTest::newRow("qtc-dev") << QDir::rootPath() + "__qtc_devices__" << "" << "" << QDir::rootPath() + "__qtc_devices__";
QTest::newRow("qtc-dev-type") << QDir::rootPath() + "__qtc_devices__/docker" << "" << "" << QDir::rootPath() + "__qtc_devices__/docker";
QTest::newRow("qtc-dev-type-dev") << QDir::rootPath() + "__qtc_devices__/docker/1234" << "docker" << "1234" << "/";
}
void tst_fileutils::fromString()
{
QFETCH(QString, input);
QFETCH(QString, scheme);
QFETCH(QString, host);
QFETCH(QString, path);
FilePath filePath = FilePath::fromString(input);
QCOMPARE(filePath.scheme(), scheme);
QCOMPARE(filePath.host(), host);
QCOMPARE(filePath.path(), path);
}
void tst_fileutils::fromToString_data()
{
QTest::addColumn<QString>("scheme");
@@ -294,14 +375,14 @@ void tst_fileutils::fromToString_data()
QTest::newRow("s3") << "" << "" << "/a/b" << "/a/b";
QTest::newRow("s4")
<< "docker" << "1234abcdef" << "/bin/ls" << "docker://1234abcdef/bin/ls";
<< "docker" << "1234abcdef" << "/bin/ls" << QDir::rootPath() + "__qtc_devices__/docker/1234abcdef/bin/ls";
QTest::newRow("s5")
<< "docker" << "1234" << "/bin/ls" << "docker://1234/bin/ls";
<< "docker" << "1234" << "/bin/ls" << QDir::rootPath() + "__qtc_devices__/docker/1234/bin/ls";
// This is not a proper URL.
QTest::newRow("s6")
<< "docker" << "1234" << "somefile" << "docker://1234/./somefile";
<< "docker" << "1234" << "somefile" << QDir::rootPath() + "__qtc_devices__/docker/1234/./somefile";
// Local Windows paths:
QTest::newRow("w1") << "" << "" << "C:/data" << "C:/data";

View File

@@ -0,0 +1,4 @@
add_qtc_test(tst_utils_fsengine
DEPENDS Utils
SOURCES tst_fsengine.cpp
)

View File

@@ -0,0 +1,291 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include <utils/filepath.h>
#include <utils/fileutils.h>
#include <utils/fsengine/fsengine.h>
#include <utils/hostosinfo.h>
#include <QDebug>
#include <QFileSystemModel>
#include <QtTest>
using namespace Utils;
class tst_fsengine : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void testFilePathFromToString();
void testRootPathContainsFakeDir();
void testNotExistingFile();
void testCreateFile();
void testListDir();
void testCreateDir();
void testWindowsPaths();
void testUrl();
private:
QString makeTestPath(QString path, bool asUrl = false);
private:
FSEngine engine;
QString tempFolder;
};
template<class... Args>
using Continuation = std::function<void(Args...)>;
void tst_fsengine::initTestCase()
{
if (!FSEngine::isAvailable())
QSKIP("Utils was built without Filesystem Engine");
DeviceFileHooks deviceHooks;
deviceHooks.fileContents =
[](const FilePath &path, qint64 maxSize, qint64 offset) -> QByteArray {
return FilePath::fromString(path.path()).fileContents(maxSize, offset);
};
deviceHooks.isExecutableFile = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).isExecutableFile();
};
deviceHooks.isReadableFile = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).isReadableFile();
};
deviceHooks.isReadableDir = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).isReadableDir();
};
deviceHooks.isWritableDir = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).isWritableDir();
};
deviceHooks.isWritableFile = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).isWritableFile();
};
deviceHooks.isFile = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).isFile();
};
deviceHooks.isDir = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).isDir();
};
deviceHooks.ensureWritableDir = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).ensureWritableDir();
};
deviceHooks.ensureExistingFile = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).ensureExistingFile();
};
deviceHooks.createDir = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).createDir();
};
deviceHooks.exists = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).exists();
};
deviceHooks.removeFile = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).removeFile();
};
deviceHooks.removeRecursively = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).removeRecursively();
};
deviceHooks.copyFile = [](const FilePath &filePath, const FilePath &target) {
return FilePath::fromString(filePath.path()).copyFile(target);
};
deviceHooks.renameFile = [](const FilePath &filePath, const FilePath &target) {
return FilePath::fromString(filePath.path()).renameFile(target);
};
deviceHooks.searchInPath = [](const FilePath &filePath, const FilePaths &dirs) {
return FilePath::fromString(filePath.path()).searchInPath(dirs);
};
deviceHooks.symLinkTarget = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).symLinkTarget();
};
deviceHooks.iterateDirectory = [](const FilePath &filePath,
const std::function<bool(const FilePath &)> &callBack,
const FileFilter &filter) {
return FilePath::fromString(filePath.path())
.iterateDirectory(
[&filePath, &callBack](const FilePath &path) -> bool {
const FilePath devicePath = path.onDevice(filePath);
return callBack(devicePath);
},
filter);
};
deviceHooks.asyncFileContents = [](const Continuation<QByteArray> &cont,
const FilePath &filePath,
qint64 maxSize,
qint64 offset) {
return FilePath::fromString(filePath.path()).asyncFileContents(cont, maxSize, offset);
};
deviceHooks.writeFileContents = [](const FilePath &filePath, const QByteArray &data) {
return FilePath::fromString(filePath.path()).writeFileContents(data);
};
deviceHooks.lastModified = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).lastModified();
};
deviceHooks.permissions = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).permissions();
};
deviceHooks.setPermissions = [](const FilePath &filePath, QFile::Permissions permissions) {
return FilePath::fromString(filePath.path()).setPermissions(permissions);
};
deviceHooks.osType = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).osType();
};
// deviceHooks.environment = [](const FilePath &filePath) -> Environment {return {};};
deviceHooks.fileSize = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).fileSize();
};
deviceHooks.bytesAvailable = [](const FilePath &filePath) {
return FilePath::fromString(filePath.path()).bytesAvailable();
};
deviceHooks.mapToDevicePath = [](const FilePath &filePath) { return filePath.path(); };
FileUtils::setDeviceFileHooks(deviceHooks);
FSEngine::addDevice(FilePath::fromString("device://test"));
tempFolder = QDir::tempPath();
QDir testFolder(QString("%1/tst_fsengine").arg(tempFolder));
if (testFolder.exists())
QVERIFY(testFolder.removeRecursively());
QDir(tempFolder).mkdir("tst_fsengine");
}
void tst_fsengine::testFilePathFromToString()
{
FilePath p = FilePath::fromString("device://test/test.txt");
QCOMPARE(p.scheme(), "device");
QCOMPARE(p.host(), "test");
QCOMPARE(p.path(), "/test.txt");
QString asString = p.toString();
QCOMPARE(asString,
FilePath::specialPath(FilePath::SpecialPathComponent::DeviceRootPath)
+ "/test/test.txt");
FilePath p2 = FilePath::fromString(asString);
QCOMPARE(p.scheme(), "device");
QCOMPARE(p.host(), "test");
QCOMPARE(p.path(), "/test.txt");
}
void tst_fsengine::testRootPathContainsFakeDir()
{
QDir root(HostOsInfo::isWindowsHost() ? "c:/" : "/");
const auto rootList = root.entryList();
QVERIFY(rootList.contains(FilePath::specialPath(FilePath::SpecialPathComponent::RootName)));
QDir schemes(FilePath::specialPath(FilePath::SpecialPathComponent::RootPath));
const auto schemeList = schemes.entryList();
QVERIFY(schemeList.contains("device"));
QDir deviceRoot(FilePath::specialPath(FilePath::SpecialPathComponent::DeviceRootPath) + "/test");
const auto deviceRootList = deviceRoot.entryList();
QVERIFY(!deviceRootList.isEmpty());
}
void tst_fsengine::testNotExistingFile()
{
QFile f(makeTestPath("test-does-not-exist.txt"));
QCOMPARE(f.open(QIODevice::ReadOnly), false);
}
void tst_fsengine::testCreateFile()
{
{
QFile f(makeTestPath("test-create-file.txt"));
QCOMPARE(f.exists(), false);
QVERIFY(f.open(QIODevice::WriteOnly));
}
QFile f(makeTestPath("test-create-file.txt"));
QCOMPARE(f.exists(), true);
}
void tst_fsengine::testCreateDir()
{
QDir d(makeTestPath({}));
QCOMPARE(d.mkdir("test-create-dir"), true);
}
QString tst_fsengine::makeTestPath(QString path, bool asUrl)
{
if (asUrl) {
return QString("device://test%1/tst_fsengine/%2").arg(tempFolder, path);
}
return QString(FilePath::specialPath(FilePath::SpecialPathComponent::DeviceRootPath)
+ "/test%1/tst_fsengine/%2")
.arg(tempFolder, path);
}
void tst_fsengine::testListDir()
{
QDir dd(makeTestPath({}));
QCOMPARE(dd.mkdir("test-list-dir"), true);
QDir d(makeTestPath("test-list-dir"));
{
QFile f(makeTestPath("test-list-dir/f1.txt"));
QVERIFY(f.open(QIODevice::WriteOnly));
}
const auto list = d.entryList();
QVERIFY(list.contains("f1.txt"));
}
void tst_fsengine::testWindowsPaths()
{
if (!HostOsInfo::isWindowsHost())
QSKIP("This test is only valid on windows");
// Test upper-case "C:"
QVERIFY(FilePath::fromString("C:/__qtc_devices__/device/{cd6c7e4b-12fd-43ca-9bb2-053a38e6b7c5}")
.needsDevice());
// Test lower-case "C:"
QVERIFY(FilePath::fromString("c:/__qtc_devices__/device/{cd6c7e4b-12fd-43ca-9bb2-053a38e6b7c5}")
.needsDevice());
}
void tst_fsengine::testUrl()
{
FilePath p = FilePath::fromString(makeTestPath("", true));
QVERIFY(p.needsDevice());
}
QTEST_GUILESS_MAIN(tst_fsengine)
#include "tst_fsengine.moc"