2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
2008-12-02 16:19:05 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "projectnodes.h"
|
2008-12-09 15:25:01 +01:00
|
|
|
|
2019-10-22 14:55:51 +02:00
|
|
|
#include "buildsystem.h"
|
2017-03-27 17:51:19 +02:00
|
|
|
#include "project.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "projectexplorerconstants.h"
|
2019-10-25 09:55:32 +02:00
|
|
|
#include "target.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-11-07 21:17:11 +02:00
|
|
|
#include <coreplugin/icore.h>
|
|
|
|
|
#include <coreplugin/iversioncontrol.h>
|
|
|
|
|
#include <coreplugin/vcsmanager.h>
|
2017-02-13 17:29:06 +01:00
|
|
|
|
2015-01-10 23:40:32 +02:00
|
|
|
#include <utils/fileutils.h>
|
2022-05-31 11:16:44 +02:00
|
|
|
#include <utils/fsengine/fileiconprovider.h>
|
2017-02-13 17:29:06 +01:00
|
|
|
#include <utils/hostosinfo.h>
|
2022-02-23 17:11:20 +01:00
|
|
|
#include <utils/mimeutils.h>
|
2018-04-26 11:00:59 +02:00
|
|
|
#include <utils/pointeralgorithm.h>
|
2008-12-09 15:25:01 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2019-08-02 12:38:45 +02:00
|
|
|
#include <utils/stringutils.h>
|
2022-10-10 15:59:26 +02:00
|
|
|
#include <utils/threadutils.h>
|
2021-08-20 16:20:20 +03:00
|
|
|
#include <utils/utilsicons.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDir>
|
2021-04-08 16:31:31 +02:00
|
|
|
#include <QFileInfo>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QIcon>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2017-03-09 14:41:01 +01:00
|
|
|
#include <memory>
|
|
|
|
|
|
2021-07-14 16:49:42 +02:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
2016-04-13 15:52:14 +02:00
|
|
|
namespace ProjectExplorer {
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2021-04-08 16:31:31 +02:00
|
|
|
QHash<QString, QIcon> DirectoryIcon::m_cache;
|
|
|
|
|
|
2017-03-09 13:05:47 +01:00
|
|
|
static FolderNode *recursiveFindOrCreateFolderNode(FolderNode *folder,
|
2022-09-16 11:14:59 +02:00
|
|
|
const FilePath &directory,
|
|
|
|
|
const FilePath &overrideBaseDir,
|
2017-03-13 18:13:47 +01:00
|
|
|
const FolderNode::FolderNodeFactory &factory)
|
2017-03-09 13:05:47 +01:00
|
|
|
{
|
2019-05-28 13:49:26 +02:00
|
|
|
Utils::FilePath path = overrideBaseDir.isEmpty() ? folder->filePath() : overrideBaseDir;
|
2017-03-09 13:05:47 +01:00
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
Utils::FilePath directoryWithoutPrefix;
|
2017-03-09 13:05:47 +01:00
|
|
|
bool isRelative = false;
|
|
|
|
|
|
2022-09-16 11:14:59 +02:00
|
|
|
if (path.isEmpty() || path.isRootPath()) {
|
2017-03-09 13:05:47 +01:00
|
|
|
directoryWithoutPrefix = directory;
|
|
|
|
|
isRelative = false;
|
|
|
|
|
} else {
|
|
|
|
|
if (directory.isChildOf(path) || directory == path) {
|
|
|
|
|
isRelative = true;
|
|
|
|
|
directoryWithoutPrefix = directory.relativeChildPath(path);
|
|
|
|
|
} else {
|
|
|
|
|
isRelative = false;
|
2017-03-24 16:26:26 +01:00
|
|
|
path.clear();
|
2017-03-09 13:05:47 +01:00
|
|
|
directoryWithoutPrefix = directory;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-14 17:13:54 +02:00
|
|
|
QStringList parts = directoryWithoutPrefix.path().split('/', Qt::SkipEmptyParts);
|
|
|
|
|
if (directory.osType() != OsTypeWindows && !isRelative && !parts.isEmpty())
|
2017-03-09 13:05:47 +01:00
|
|
|
parts[0].prepend('/');
|
|
|
|
|
|
|
|
|
|
ProjectExplorer::FolderNode *parent = folder;
|
2022-10-07 14:46:06 +02:00
|
|
|
for (const QString &part : std::as_const(parts)) {
|
2019-05-17 12:32:05 +02:00
|
|
|
path = path.pathAppended(part);
|
2017-03-09 13:05:47 +01:00
|
|
|
// Find folder in subFolders
|
2019-11-14 11:35:35 +01:00
|
|
|
FolderNode *next = parent->folderNode(path);
|
2017-03-09 13:05:47 +01:00
|
|
|
if (!next) {
|
|
|
|
|
// No FolderNode yet, so create it
|
2017-03-13 18:13:47 +01:00
|
|
|
auto tmp = factory(path);
|
2017-03-09 13:05:47 +01:00
|
|
|
tmp->setDisplayName(part);
|
2018-04-26 14:57:12 +02:00
|
|
|
next = tmp.get();
|
|
|
|
|
parent->addNode(std::move(tmp));
|
2017-03-09 13:05:47 +01:00
|
|
|
}
|
|
|
|
|
parent = next;
|
|
|
|
|
}
|
|
|
|
|
return parent;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2011-04-14 12:58:14 +02:00
|
|
|
\class ProjectExplorer::Node
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The Node class is the base class of all nodes in the node hierarchy.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
The nodes are arranged in a tree where leaves are FileNodes and non-leaves are FolderNodes
|
|
|
|
|
A Project is a special Folder that manages the files and normal folders underneath it.
|
|
|
|
|
|
|
|
|
|
The Watcher emits signals for structural changes in the hierarchy.
|
|
|
|
|
A Visitor can be used to traverse all Projects and other Folders.
|
|
|
|
|
|
|
|
|
|
\sa ProjectExplorer::FileNode, ProjectExplorer::FolderNode, ProjectExplorer::ProjectNode
|
2017-03-06 18:03:43 +01:00
|
|
|
\sa ProjectExplorer::NodesWatcher
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2011-04-14 12:58:14 +02:00
|
|
|
|
2019-02-25 18:32:12 +01:00
|
|
|
Node::Node() = default;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-11-10 16:56:15 +01:00
|
|
|
void Node::setPriority(int p)
|
|
|
|
|
{
|
|
|
|
|
m_priority = p;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
void Node::setFilePath(const Utils::FilePath &filePath)
|
2019-02-25 13:06:09 +01:00
|
|
|
{
|
|
|
|
|
m_filePath = filePath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Node::setLine(int line)
|
|
|
|
|
{
|
|
|
|
|
m_line = line;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-03 13:46:02 +02:00
|
|
|
void Node::setListInProject(bool l)
|
|
|
|
|
{
|
2017-05-04 12:53:07 +02:00
|
|
|
if (l)
|
2018-04-26 10:25:19 +02:00
|
|
|
m_flags = static_cast<NodeFlag>(m_flags | FlagListInProject);
|
2017-05-04 12:53:07 +02:00
|
|
|
else
|
2018-04-26 10:25:19 +02:00
|
|
|
m_flags = static_cast<NodeFlag>(m_flags & ~FlagListInProject);
|
2017-05-03 13:46:02 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-03 12:36:44 +02:00
|
|
|
void Node::setIsGenerated(bool g)
|
|
|
|
|
{
|
2017-05-04 12:53:07 +02:00
|
|
|
if (g)
|
2018-04-26 10:25:19 +02:00
|
|
|
m_flags = static_cast<NodeFlag>(m_flags | FlagIsGenerated);
|
2017-05-04 12:53:07 +02:00
|
|
|
else
|
2018-04-26 10:25:19 +02:00
|
|
|
m_flags = static_cast<NodeFlag>(m_flags & ~FlagIsGenerated);
|
2017-05-03 12:36:44 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
void Node::setAbsoluteFilePathAndLine(const Utils::FilePath &path, int line)
|
2013-01-30 18:13:46 +01:00
|
|
|
{
|
2015-10-29 17:53:47 +01:00
|
|
|
if (m_filePath == path && m_line == line)
|
2013-02-01 12:20:15 +01:00
|
|
|
return;
|
|
|
|
|
|
2015-10-29 17:53:47 +01:00
|
|
|
m_filePath = path;
|
2014-02-18 18:06:05 +01:00
|
|
|
m_line = line;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-03 17:16:32 +01:00
|
|
|
Node::~Node() = default;
|
2017-01-19 14:54:23 +01:00
|
|
|
|
2016-11-10 16:56:15 +01:00
|
|
|
int Node::priority() const
|
|
|
|
|
{
|
|
|
|
|
return m_priority;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-03 13:46:02 +02:00
|
|
|
/*!
|
|
|
|
|
Returns \c true if the Node should be listed as part of the projects file list.
|
|
|
|
|
*/
|
|
|
|
|
bool Node::listInProject() const
|
|
|
|
|
{
|
2018-04-26 10:25:19 +02:00
|
|
|
return (m_flags & FlagListInProject) == FlagListInProject;
|
2017-05-03 13:46:02 +02:00
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2013-09-10 17:16:10 +02:00
|
|
|
The project that owns and manages the node. It is the first project in the list
|
|
|
|
|
of ancestors.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2016-11-09 13:39:59 +01:00
|
|
|
ProjectNode *Node::parentProjectNode() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2016-11-11 10:11:51 +01:00
|
|
|
if (!m_parentFolderNode)
|
|
|
|
|
return nullptr;
|
|
|
|
|
auto pn = m_parentFolderNode->asProjectNode();
|
|
|
|
|
if (pn)
|
|
|
|
|
return pn;
|
|
|
|
|
return m_parentFolderNode->parentProjectNode();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
2013-09-10 17:16:10 +02:00
|
|
|
The parent in the node hierarchy.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
|
|
|
|
FolderNode *Node::parentFolderNode() const
|
|
|
|
|
{
|
2016-11-11 10:09:29 +01:00
|
|
|
return m_parentFolderNode;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2016-11-11 10:11:51 +01:00
|
|
|
ProjectNode *Node::managingProject()
|
|
|
|
|
{
|
2017-03-27 17:51:19 +02:00
|
|
|
if (asContainerNode())
|
|
|
|
|
return asContainerNode()->rootProjectNode();
|
|
|
|
|
QTC_ASSERT(m_parentFolderNode, return nullptr);
|
2016-11-11 10:11:51 +01:00
|
|
|
ProjectNode *pn = parentProjectNode();
|
|
|
|
|
return pn ? pn : asProjectNode(); // projects manage themselves...
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ProjectNode *Node::managingProject() const
|
|
|
|
|
{
|
|
|
|
|
return const_cast<Node *>(this)->managingProject();
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:36:02 +02:00
|
|
|
Project *Node::getProject() const
|
|
|
|
|
{
|
|
|
|
|
if (const ContainerNode * const cn = asContainerNode())
|
|
|
|
|
return cn->project();
|
|
|
|
|
if (!m_parentFolderNode)
|
|
|
|
|
return nullptr;
|
|
|
|
|
return m_parentFolderNode->getProject();
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2013-09-10 17:16:10 +02:00
|
|
|
The path of the file or folder in the filesystem the node represents.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2019-05-28 13:49:26 +02:00
|
|
|
const Utils::FilePath &Node::filePath() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-10-29 17:53:47 +01:00
|
|
|
return m_filePath;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2013-01-30 18:13:46 +01:00
|
|
|
int Node::line() const
|
|
|
|
|
{
|
2014-07-22 13:15:03 +02:00
|
|
|
return m_line;
|
2013-01-30 18:13:46 +01:00
|
|
|
}
|
|
|
|
|
|
2012-05-04 11:49:37 +02:00
|
|
|
QString Node::displayName() const
|
|
|
|
|
{
|
2015-10-29 17:53:47 +01:00
|
|
|
return filePath().fileName();
|
2012-05-04 11:49:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Node::tooltip() const
|
|
|
|
|
{
|
2015-10-29 17:53:47 +01:00
|
|
|
return filePath().toUserOutput();
|
2012-05-04 11:49:37 +02:00
|
|
|
}
|
|
|
|
|
|
2013-01-16 15:27:03 +01:00
|
|
|
bool Node::isEnabled() const
|
|
|
|
|
{
|
2018-04-26 10:25:19 +02:00
|
|
|
if ((m_flags & FlagIsEnabled) == 0)
|
2016-10-31 13:55:52 +01:00
|
|
|
return false;
|
|
|
|
|
FolderNode *parent = parentFolderNode();
|
|
|
|
|
return parent ? parent->isEnabled() : true;
|
2013-01-16 15:27:03 +01:00
|
|
|
}
|
|
|
|
|
|
2021-08-20 16:20:20 +03:00
|
|
|
QIcon FileNode::icon() const
|
|
|
|
|
{
|
|
|
|
|
if (hasError())
|
|
|
|
|
return Utils::Icons::WARNING.icon();
|
|
|
|
|
if (m_icon.isNull())
|
2022-05-31 11:16:44 +02:00
|
|
|
m_icon = Utils::FileIconProvider::icon(filePath());
|
2021-08-20 16:20:20 +03:00
|
|
|
return m_icon;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileNode::setIcon(const QIcon icon)
|
|
|
|
|
{
|
|
|
|
|
m_icon = icon;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FileNode::hasError() const
|
|
|
|
|
{
|
|
|
|
|
return m_hasError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileNode::setHasError(bool error)
|
|
|
|
|
{
|
|
|
|
|
m_hasError = error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileNode::setHasError(bool error) const
|
|
|
|
|
{
|
|
|
|
|
m_hasError = error;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-03 12:36:44 +02:00
|
|
|
/*!
|
|
|
|
|
Returns \c true if the file is automatically generated by a compile step.
|
|
|
|
|
*/
|
|
|
|
|
bool Node::isGenerated() const
|
|
|
|
|
{
|
2017-05-04 12:53:07 +02:00
|
|
|
return (m_flags & FlagIsGenerated) == FlagIsGenerated;
|
2017-05-03 12:36:44 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-31 15:48:45 +02:00
|
|
|
bool Node::supportsAction(ProjectAction, const Node *) const
|
2014-02-03 14:45:28 +01:00
|
|
|
{
|
2017-03-15 15:46:48 +01:00
|
|
|
return false;
|
2014-02-03 14:45:28 +01:00
|
|
|
}
|
|
|
|
|
|
2016-10-31 13:55:52 +01:00
|
|
|
void Node::setEnabled(bool enabled)
|
|
|
|
|
{
|
2017-05-04 12:53:07 +02:00
|
|
|
if (enabled)
|
2018-04-26 10:25:19 +02:00
|
|
|
m_flags = static_cast<NodeFlag>(m_flags | FlagIsEnabled);
|
2017-05-04 12:53:07 +02:00
|
|
|
else
|
2018-04-26 10:25:19 +02:00
|
|
|
m_flags = static_cast<NodeFlag>(m_flags & ~FlagIsEnabled);
|
2013-01-16 15:27:03 +01:00
|
|
|
}
|
|
|
|
|
|
2016-12-15 12:53:37 +01:00
|
|
|
bool Node::sortByPath(const Node *a, const Node *b)
|
2016-11-01 17:08:39 +01:00
|
|
|
{
|
|
|
|
|
return a->filePath() < b->filePath();
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void Node::setParentFolderNode(FolderNode *parentFolder)
|
|
|
|
|
{
|
2016-11-11 10:09:29 +01:00
|
|
|
m_parentFolderNode = parentFolder;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-10 17:03:51 +01:00
|
|
|
FileType Node::fileTypeForMimeType(const Utils::MimeType &mt)
|
|
|
|
|
{
|
|
|
|
|
FileType type = FileType::Source;
|
|
|
|
|
if (mt.isValid()) {
|
|
|
|
|
const QString mtName = mt.name();
|
|
|
|
|
if (mtName == Constants::C_HEADER_MIMETYPE
|
|
|
|
|
|| mtName == Constants::CPP_HEADER_MIMETYPE)
|
|
|
|
|
type = FileType::Header;
|
|
|
|
|
else if (mtName == Constants::FORM_MIMETYPE)
|
|
|
|
|
type = FileType::Form;
|
|
|
|
|
else if (mtName == Constants::RESOURCE_MIMETYPE)
|
|
|
|
|
type = FileType::Resource;
|
|
|
|
|
else if (mtName == Constants::SCXML_MIMETYPE)
|
|
|
|
|
type = FileType::StateChart;
|
2017-10-17 18:53:28 +02:00
|
|
|
else if (mtName == Constants::QML_MIMETYPE
|
|
|
|
|
|| mtName == Constants::QMLUI_MIMETYPE)
|
2017-03-10 17:03:51 +01:00
|
|
|
type = FileType::QML;
|
|
|
|
|
} else {
|
|
|
|
|
type = FileType::Unknown;
|
|
|
|
|
}
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
FileType Node::fileTypeForFileName(const Utils::FilePath &file)
|
2017-03-10 17:03:51 +01:00
|
|
|
{
|
2021-05-18 14:35:07 +02:00
|
|
|
return fileTypeForMimeType(Utils::mimeTypeForFile(file, Utils::MimeMatchMode::MatchExtension));
|
2017-03-10 17:03:51 +01:00
|
|
|
}
|
|
|
|
|
|
2021-07-26 17:20:03 +02:00
|
|
|
FilePath Node::pathOrDirectory(bool dir) const
|
2019-08-02 12:38:45 +02:00
|
|
|
{
|
2021-07-26 17:20:03 +02:00
|
|
|
FilePath location;
|
2019-08-02 12:38:45 +02:00
|
|
|
const FolderNode *folder = asFolderNode();
|
|
|
|
|
if (isVirtualFolderType() && folder) {
|
|
|
|
|
// Virtual Folder case
|
|
|
|
|
// If there are files directly below or no subfolders, take the folder path
|
|
|
|
|
if (!folder->fileNodes().isEmpty() || folder->folderNodes().isEmpty()) {
|
2021-07-26 17:20:03 +02:00
|
|
|
location = m_filePath;
|
2019-08-02 12:38:45 +02:00
|
|
|
} else {
|
|
|
|
|
// Otherwise we figure out a commonPath from the subfolders
|
|
|
|
|
QStringList list;
|
2022-05-03 16:48:36 +02:00
|
|
|
const QList<FolderNode *> folders = folder->folderNodes();
|
|
|
|
|
for (FolderNode *f : folders)
|
2019-08-02 12:38:45 +02:00
|
|
|
list << f->filePath().toString() + QLatin1Char('/');
|
2021-07-26 17:20:03 +02:00
|
|
|
location = FilePath::fromString(Utils::commonPath(list));
|
2019-08-02 12:38:45 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-26 17:20:03 +02:00
|
|
|
QTC_CHECK(!location.needsDevice());
|
|
|
|
|
QFileInfo fi = location.toFileInfo();
|
2019-08-02 12:38:45 +02:00
|
|
|
while ((!fi.exists() || !fi.isDir()) && !fi.isRoot())
|
|
|
|
|
fi.setFile(fi.absolutePath());
|
2021-07-26 17:20:03 +02:00
|
|
|
location = FilePath::fromString(fi.absoluteFilePath());
|
2019-08-02 12:38:45 +02:00
|
|
|
} else if (!m_filePath.isEmpty()) {
|
2021-07-26 17:20:03 +02:00
|
|
|
QTC_CHECK(!m_filePath.needsDevice());
|
2019-08-02 12:38:45 +02:00
|
|
|
QFileInfo fi = m_filePath.toFileInfo();
|
|
|
|
|
// remove any /suffixes, which e.g. ResourceNode uses
|
|
|
|
|
// Note this could be removed again by making path() a true path again
|
|
|
|
|
// That requires changes in both the VirtualFolderNode and ResourceNode
|
|
|
|
|
while (!fi.exists() && !fi.isRoot())
|
|
|
|
|
fi.setFile(fi.absolutePath());
|
|
|
|
|
|
|
|
|
|
if (dir)
|
2021-07-26 17:20:03 +02:00
|
|
|
location = FilePath::fromString(fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath());
|
2019-08-02 12:38:45 +02:00
|
|
|
else
|
2021-07-26 17:20:03 +02:00
|
|
|
location = FilePath::fromString(fi.absoluteFilePath());
|
2019-08-02 12:38:45 +02:00
|
|
|
}
|
|
|
|
|
return location;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2011-04-14 12:58:14 +02:00
|
|
|
\class ProjectExplorer::FileNode
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-09-10 17:16:10 +02:00
|
|
|
\brief The FileNode class is an in-memory presentation of a file.
|
|
|
|
|
|
|
|
|
|
All file nodes are leaf nodes.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
\sa ProjectExplorer::FolderNode, ProjectExplorer::ProjectNode
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
FileNode::FileNode(const Utils::FilePath &filePath, const FileType fileType) :
|
2017-05-03 12:36:44 +02:00
|
|
|
m_fileType(fileType)
|
2016-11-10 16:56:15 +01:00
|
|
|
{
|
2019-02-25 13:06:09 +01:00
|
|
|
setFilePath(filePath);
|
2017-05-03 13:46:02 +02:00
|
|
|
setListInProject(true);
|
2016-11-10 16:56:15 +01:00
|
|
|
if (fileType == FileType::Project)
|
|
|
|
|
setPriority(DefaultProjectFilePriority);
|
|
|
|
|
else
|
|
|
|
|
setPriority(DefaultFilePriority);
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2017-05-03 12:20:10 +02:00
|
|
|
FileNode *FileNode::clone() const
|
|
|
|
|
{
|
2019-02-25 13:06:09 +01:00
|
|
|
auto fn = new FileNode(filePath(), fileType());
|
|
|
|
|
fn->setLine(line());
|
2019-02-25 12:08:58 +01:00
|
|
|
fn->setIsGenerated(isGenerated());
|
2017-05-03 12:20:10 +02:00
|
|
|
fn->setEnabled(isEnabled());
|
|
|
|
|
fn->setPriority(priority());
|
2017-05-03 13:46:02 +02:00
|
|
|
fn->setListInProject(listInProject());
|
2017-05-03 12:20:10 +02:00
|
|
|
return fn;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
FileType FileNode::fileType() const
|
|
|
|
|
{
|
|
|
|
|
return m_fileType;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-31 15:48:45 +02:00
|
|
|
bool FileNode::supportsAction(ProjectAction action, const Node *node) const
|
2017-03-15 15:46:48 +01:00
|
|
|
{
|
|
|
|
|
if (action == InheritedFromParent)
|
|
|
|
|
return true;
|
|
|
|
|
FolderNode *parentFolder = parentFolderNode();
|
|
|
|
|
return parentFolder && parentFolder->supportsAction(action, node);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-26 13:34:23 +01:00
|
|
|
QString FileNode::displayName() const
|
|
|
|
|
{
|
|
|
|
|
int l = line();
|
|
|
|
|
if (l < 0)
|
|
|
|
|
return Node::displayName();
|
|
|
|
|
return Node::displayName() + ':' + QString::number(l);
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2011-04-14 12:58:14 +02:00
|
|
|
\class ProjectExplorer::FolderNode
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
In-memory presentation of a folder. Note that the node itself + all children (files and folders) are "managed" by the owning project.
|
|
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
\sa ProjectExplorer::FileNode, ProjectExplorer::ProjectNode
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2019-05-28 13:49:26 +02:00
|
|
|
FolderNode::FolderNode(const Utils::FilePath &folderPath)
|
2010-02-12 12:54:12 +01:00
|
|
|
{
|
2019-02-25 13:06:09 +01:00
|
|
|
setFilePath(folderPath);
|
2016-11-10 16:56:15 +01:00
|
|
|
setPriority(DefaultFolderPriority);
|
2017-05-03 13:46:02 +02:00
|
|
|
setListInProject(false);
|
2017-05-03 12:36:44 +02:00
|
|
|
setIsGenerated(false);
|
2019-02-25 18:08:36 +01:00
|
|
|
m_displayName = folderPath.toUserOutput();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
/*!
|
2013-09-10 17:16:10 +02:00
|
|
|
Contains the display name that should be used in a view.
|
2011-04-14 12:58:14 +02:00
|
|
|
\sa setFolderName()
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2011-04-14 12:58:14 +02:00
|
|
|
|
2010-01-07 18:17:24 +01:00
|
|
|
QString FolderNode::displayName() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-02-24 15:03:54 +01:00
|
|
|
return m_displayName;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
/*!
|
2021-04-08 16:31:31 +02:00
|
|
|
Contains the icon that should be used in a view. Default is the directory icon
|
|
|
|
|
(QStyle::S_PDirIcon). Calling this method is only safe in the UI thread.
|
|
|
|
|
|
|
|
|
|
\sa setIcon()
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
|
|
|
|
QIcon FolderNode::icon() const
|
|
|
|
|
{
|
2022-10-10 15:59:26 +02:00
|
|
|
QTC_CHECK(isMainThread());
|
2021-04-08 16:31:31 +02:00
|
|
|
|
2010-07-07 12:16:09 +02:00
|
|
|
// Instantiating the Icon provider is expensive.
|
2022-08-19 14:47:59 +02:00
|
|
|
if (auto strPtr = std::get_if<QString>(&m_icon)) {
|
2021-04-08 16:31:31 +02:00
|
|
|
m_icon = QIcon(*strPtr);
|
2022-08-19 14:47:59 +02:00
|
|
|
} else if (auto directoryIconPtr = std::get_if<DirectoryIcon>(&m_icon)) {
|
2021-04-08 16:31:31 +02:00
|
|
|
m_icon = directoryIconPtr->icon();
|
2022-08-19 14:47:59 +02:00
|
|
|
} else if (auto creatorPtr = std::get_if<IconCreator>(&m_icon)) {
|
2021-04-08 16:31:31 +02:00
|
|
|
m_icon = (*creatorPtr)();
|
|
|
|
|
} else {
|
2022-08-19 14:47:59 +02:00
|
|
|
auto iconPtr = std::get_if<QIcon>(&m_icon);
|
2021-04-08 16:31:31 +02:00
|
|
|
if (!iconPtr || iconPtr->isNull())
|
2022-05-31 11:16:44 +02:00
|
|
|
m_icon = Utils::FileIconProvider::icon(QFileIconProvider::Folder);
|
2021-04-08 16:31:31 +02:00
|
|
|
}
|
2022-08-19 14:47:59 +02:00
|
|
|
return std::get<QIcon>(m_icon);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-14 16:21:33 +01:00
|
|
|
Node *FolderNode::findNode(const std::function<bool(Node *)> &filter)
|
|
|
|
|
{
|
|
|
|
|
if (filter(this))
|
|
|
|
|
return this;
|
|
|
|
|
|
2018-04-26 11:00:59 +02:00
|
|
|
for (const std::unique_ptr<Node> &n : m_nodes) {
|
|
|
|
|
if (n->asFileNode() && filter(n.get())) {
|
|
|
|
|
return n.get();
|
2017-03-14 16:21:33 +01:00
|
|
|
} else if (FolderNode *folder = n->asFolderNode()) {
|
|
|
|
|
Node *result = folder->findNode(filter);
|
|
|
|
|
if (result)
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<Node *> FolderNode::findNodes(const std::function<bool(Node *)> &filter)
|
|
|
|
|
{
|
|
|
|
|
QList<Node *> result;
|
|
|
|
|
if (filter(this))
|
|
|
|
|
result.append(this);
|
2018-04-26 11:00:59 +02:00
|
|
|
for (const std::unique_ptr<Node> &n : m_nodes) {
|
|
|
|
|
if (n->asFileNode() && filter(n.get()))
|
|
|
|
|
result.append(n.get());
|
2017-03-14 16:21:33 +01:00
|
|
|
else if (FolderNode *folder = n->asFolderNode())
|
2018-10-30 14:19:09 +01:00
|
|
|
result.append(folder->findNodes(filter));
|
2017-03-14 16:21:33 +01:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-13 12:45:23 +01:00
|
|
|
void FolderNode::forEachNode(const std::function<void(FileNode *)> &fileTask,
|
|
|
|
|
const std::function<void(FolderNode *)> &folderTask,
|
|
|
|
|
const std::function<bool(const FolderNode *)> &folderFilterTask) const
|
|
|
|
|
{
|
|
|
|
|
if (folderFilterTask) {
|
|
|
|
|
if (!folderFilterTask(this))
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (fileTask) {
|
2018-04-26 11:00:59 +02:00
|
|
|
for (const std::unique_ptr<Node> &n : m_nodes) {
|
2017-02-13 12:45:23 +01:00
|
|
|
if (FileNode *fn = n->asFileNode())
|
|
|
|
|
fileTask(fn);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-04-26 11:00:59 +02:00
|
|
|
for (const std::unique_ptr<Node> &n : m_nodes) {
|
2017-02-13 12:45:23 +01:00
|
|
|
if (FolderNode *fn = n->asFolderNode()) {
|
|
|
|
|
if (folderTask)
|
|
|
|
|
folderTask(fn);
|
|
|
|
|
fn->forEachNode(fileTask, folderTask, folderFilterTask);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FolderNode::forEachGenericNode(const std::function<void(Node *)> &genericTask) const
|
|
|
|
|
{
|
2018-04-26 11:00:59 +02:00
|
|
|
for (const std::unique_ptr<Node> &n : m_nodes) {
|
|
|
|
|
genericTask(n.get());
|
2017-02-13 12:45:23 +01:00
|
|
|
if (FolderNode *fn = n->asFolderNode())
|
2017-05-03 12:13:10 +02:00
|
|
|
fn->forEachGenericNode(genericTask);
|
2017-02-13 12:45:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-27 18:14:56 +01:00
|
|
|
void FolderNode::forEachProjectNode(const std::function<void(const ProjectNode *)> &task) const
|
|
|
|
|
{
|
|
|
|
|
if (const ProjectNode *projectNode = asProjectNode())
|
|
|
|
|
task(projectNode);
|
|
|
|
|
|
|
|
|
|
for (const std::unique_ptr<Node> &n : m_nodes) {
|
|
|
|
|
if (FolderNode *fn = n->asFolderNode())
|
|
|
|
|
fn->forEachProjectNode(task);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-05 10:29:48 +01:00
|
|
|
ProjectNode *FolderNode::findProjectNode(const std::function<bool(const ProjectNode *)> &predicate)
|
2018-12-18 14:01:36 +01:00
|
|
|
{
|
2018-12-05 10:29:48 +01:00
|
|
|
if (ProjectNode *projectNode = asProjectNode()) {
|
2018-12-18 14:01:36 +01:00
|
|
|
if (predicate(projectNode))
|
|
|
|
|
return projectNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const std::unique_ptr<Node> &n : m_nodes) {
|
|
|
|
|
if (FolderNode *fn = n->asFolderNode()) {
|
2018-12-05 10:29:48 +01:00
|
|
|
if (ProjectNode *pn = fn->findProjectNode(predicate))
|
2018-12-18 14:01:36 +01:00
|
|
|
return pn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-26 11:00:59 +02:00
|
|
|
const QList<Node *> FolderNode::nodes() const
|
|
|
|
|
{
|
|
|
|
|
return Utils::toRawPointer<QList>(m_nodes);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-30 13:13:35 +02:00
|
|
|
QList<FileNode *> FolderNode::fileNodes() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2017-02-08 14:50:43 +01:00
|
|
|
QList<FileNode *> result;
|
2018-04-26 11:00:59 +02:00
|
|
|
for (const std::unique_ptr<Node> &n : m_nodes) {
|
2017-02-08 14:50:43 +01:00
|
|
|
if (FileNode *fn = n->asFileNode())
|
|
|
|
|
result.append(fn);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
FileNode *FolderNode::fileNode(const Utils::FilePath &file) const
|
2016-11-07 12:11:26 +01:00
|
|
|
{
|
2018-04-26 11:00:59 +02:00
|
|
|
return static_cast<FileNode *>(Utils::findOrDefault(m_nodes,
|
|
|
|
|
[&file](const std::unique_ptr<Node> &n) {
|
2017-02-08 14:50:43 +01:00
|
|
|
const FileNode *fn = n->asFileNode();
|
|
|
|
|
return fn && fn->filePath() == file;
|
|
|
|
|
}));
|
2016-11-07 12:11:26 +01:00
|
|
|
}
|
|
|
|
|
|
2022-09-30 12:42:20 +02:00
|
|
|
QList<FolderNode *> FolderNode::folderNodes() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2017-02-08 14:50:43 +01:00
|
|
|
QList<FolderNode *> result;
|
2018-04-26 11:00:59 +02:00
|
|
|
for (const std::unique_ptr<Node> &n : m_nodes) {
|
2017-02-08 14:50:43 +01:00
|
|
|
if (FolderNode *fn = n->asFolderNode())
|
|
|
|
|
result.append(fn);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2019-11-14 11:35:35 +01:00
|
|
|
FolderNode *FolderNode::folderNode(const Utils::FilePath &directory) const
|
|
|
|
|
{
|
|
|
|
|
Node *node = Utils::findOrDefault(m_nodes, [directory](const std::unique_ptr<Node> &n) {
|
|
|
|
|
FolderNode *fn = n->asFolderNode();
|
|
|
|
|
return fn && fn->filePath() == directory;
|
|
|
|
|
});
|
|
|
|
|
return static_cast<FolderNode *>(node);
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-26 15:07:56 +02:00
|
|
|
void FolderNode::addNestedNode(std::unique_ptr<FileNode> &&fileNode,
|
2019-05-28 13:49:26 +02:00
|
|
|
const Utils::FilePath &overrideBaseDir,
|
2017-03-13 18:13:47 +01:00
|
|
|
const FolderNodeFactory &factory)
|
2017-03-10 17:30:40 +01:00
|
|
|
{
|
2017-03-24 16:27:41 +01:00
|
|
|
FolderNode *folder = recursiveFindOrCreateFolderNode(this, fileNode->filePath().parentDir(),
|
2017-03-13 18:13:47 +01:00
|
|
|
overrideBaseDir, factory);
|
2018-04-26 15:07:56 +02:00
|
|
|
folder->addNode(std::move(fileNode));
|
2017-03-10 17:30:40 +01:00
|
|
|
}
|
|
|
|
|
|
2018-04-26 16:39:15 +02:00
|
|
|
void FolderNode::addNestedNodes(std::vector<std::unique_ptr<FileNode> > &&files,
|
2019-05-28 13:49:26 +02:00
|
|
|
const Utils::FilePath &overrideBaseDir,
|
2018-04-26 16:39:15 +02:00
|
|
|
const FolderNode::FolderNodeFactory &factory)
|
|
|
|
|
{
|
2019-11-14 10:52:37 +01:00
|
|
|
using DirWithNodes = std::pair<Utils::FilePath, std::vector<std::unique_ptr<FileNode>>>;
|
|
|
|
|
std::vector<DirWithNodes> fileNodesPerDir;
|
|
|
|
|
for (auto &f : files) {
|
|
|
|
|
const Utils::FilePath parentDir = f->filePath().parentDir();
|
|
|
|
|
const auto it = std::lower_bound(fileNodesPerDir.begin(), fileNodesPerDir.end(), parentDir,
|
|
|
|
|
[](const DirWithNodes &nad, const Utils::FilePath &dir) { return nad.first < dir; });
|
2019-12-02 05:59:19 +02:00
|
|
|
if (it != fileNodesPerDir.end() && it->first == parentDir) {
|
|
|
|
|
it->second.emplace_back(std::move(f));
|
|
|
|
|
} else {
|
2019-11-14 10:52:37 +01:00
|
|
|
DirWithNodes dirWithNodes;
|
|
|
|
|
dirWithNodes.first = parentDir;
|
|
|
|
|
dirWithNodes.second.emplace_back(std::move(f));
|
|
|
|
|
fileNodesPerDir.insert(it, std::move(dirWithNodes));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (DirWithNodes &dirWithNodes : fileNodesPerDir) {
|
|
|
|
|
FolderNode * const folderNode = recursiveFindOrCreateFolderNode(this, dirWithNodes.first,
|
|
|
|
|
overrideBaseDir, factory);
|
|
|
|
|
for (auto &f : dirWithNodes.second)
|
|
|
|
|
folderNode->addNode(std::move(f));
|
|
|
|
|
}
|
2018-04-26 16:39:15 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-13 17:31:30 +01:00
|
|
|
// "Compress" a tree of foldernodes such that foldernodes with exactly one foldernode as a child
|
|
|
|
|
// are merged into one. This e.g. turns a sequence of FolderNodes "foo" "bar" "baz" into one
|
|
|
|
|
// FolderNode named "foo/bar/baz", saving a lot of clicks in the Project View to get to the actual
|
|
|
|
|
// files.
|
|
|
|
|
void FolderNode::compress()
|
|
|
|
|
{
|
2018-04-26 11:00:59 +02:00
|
|
|
if (auto subFolder = m_nodes.size() == 1 ? m_nodes.at(0)->asFolderNode() : nullptr) {
|
2019-03-01 10:37:14 +01:00
|
|
|
const bool sameType = (isFolderNodeType() && subFolder->isFolderNodeType())
|
|
|
|
|
|| (isProjectNodeType() && subFolder->isProjectNodeType())
|
|
|
|
|
|| (isVirtualFolderType() && subFolder->isVirtualFolderType());
|
|
|
|
|
if (!sameType)
|
2017-03-24 16:34:03 +01:00
|
|
|
return;
|
2019-03-01 10:37:14 +01:00
|
|
|
|
2017-02-13 17:31:30 +01:00
|
|
|
// Only one subfolder: Compress!
|
|
|
|
|
setDisplayName(QDir::toNativeSeparators(displayName() + "/" + subFolder->displayName()));
|
|
|
|
|
for (Node *n : subFolder->nodes()) {
|
2018-04-26 11:00:59 +02:00
|
|
|
std::unique_ptr<Node> toMove = subFolder->takeNode(n);
|
|
|
|
|
toMove->setParentFolderNode(nullptr);
|
|
|
|
|
addNode(std::move(toMove));
|
2017-02-13 17:31:30 +01:00
|
|
|
}
|
|
|
|
|
setAbsoluteFilePathAndLine(subFolder->filePath(), -1);
|
|
|
|
|
|
2018-04-26 14:50:35 +02:00
|
|
|
takeNode(subFolder);
|
2017-02-13 17:31:30 +01:00
|
|
|
|
|
|
|
|
compress();
|
|
|
|
|
} else {
|
|
|
|
|
for (FolderNode *fn : folderNodes())
|
|
|
|
|
fn->compress();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-26 15:12:44 +02:00
|
|
|
bool FolderNode::replaceSubtree(Node *oldNode, std::unique_ptr<Node> &&newNode)
|
2017-03-09 14:41:01 +01:00
|
|
|
{
|
2018-06-27 14:57:14 +02:00
|
|
|
std::unique_ptr<Node> keepAlive;
|
2017-03-09 14:41:01 +01:00
|
|
|
if (!oldNode) {
|
2018-04-26 15:12:44 +02:00
|
|
|
addNode(std::move(newNode)); // Happens e.g. when a project is registered
|
2017-03-09 14:41:01 +01:00
|
|
|
} else {
|
|
|
|
|
auto it = std::find_if(m_nodes.begin(), m_nodes.end(),
|
2018-04-26 11:00:59 +02:00
|
|
|
[oldNode](const std::unique_ptr<Node> &n) {
|
|
|
|
|
return oldNode == n.get();
|
|
|
|
|
});
|
2017-03-09 14:41:01 +01:00
|
|
|
QTC_ASSERT(it != m_nodes.end(), return false);
|
2018-04-26 15:12:44 +02:00
|
|
|
if (newNode) {
|
|
|
|
|
newNode->setParentFolderNode(this);
|
2018-06-27 14:57:14 +02:00
|
|
|
keepAlive = std::move(*it);
|
2018-04-26 15:12:44 +02:00
|
|
|
*it = std::move(newNode);
|
2017-03-09 14:41:01 +01:00
|
|
|
} else {
|
2018-06-27 14:57:14 +02:00
|
|
|
keepAlive = takeNode(oldNode); // Happens e.g. when project is shutting down
|
2017-03-09 14:41:01 +01:00
|
|
|
}
|
|
|
|
|
}
|
2018-01-19 11:55:28 +01:00
|
|
|
handleSubTreeChanged(this);
|
2017-03-09 14:41:01 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-24 15:03:54 +01:00
|
|
|
void FolderNode::setDisplayName(const QString &name)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-02-01 12:20:15 +01:00
|
|
|
if (m_displayName == name)
|
|
|
|
|
return;
|
2010-02-24 15:03:54 +01:00
|
|
|
m_displayName = name;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2021-04-08 16:31:31 +02:00
|
|
|
/*!
|
|
|
|
|
Sets the \a icon for this node. Note that creating QIcon instances is only safe in the UI thread.
|
|
|
|
|
*/
|
2008-12-02 12:01:29 +01:00
|
|
|
void FolderNode::setIcon(const QIcon &icon)
|
|
|
|
|
{
|
|
|
|
|
m_icon = icon;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-08 16:31:31 +02:00
|
|
|
/*!
|
|
|
|
|
Sets the \a directoryIcon that is used to create the icon for this node on demand.
|
|
|
|
|
*/
|
|
|
|
|
void FolderNode::setIcon(const DirectoryIcon &directoryIcon)
|
|
|
|
|
{
|
|
|
|
|
m_icon = directoryIcon;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Sets the \a path that is used to create the icon for this node on demand.
|
|
|
|
|
*/
|
|
|
|
|
void FolderNode::setIcon(const QString &path)
|
|
|
|
|
{
|
|
|
|
|
m_icon = path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Sets the \a iconCreator function that is used to create the icon for this node on demand.
|
|
|
|
|
*/
|
|
|
|
|
void FolderNode::setIcon(const IconCreator &iconCreator)
|
|
|
|
|
{
|
|
|
|
|
m_icon = iconCreator;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-26 13:52:07 +02:00
|
|
|
void FolderNode::setLocationInfo(const QVector<FolderNode::LocationInfo> &info)
|
2017-07-05 16:01:59 +02:00
|
|
|
{
|
|
|
|
|
m_locations = info;
|
2019-07-26 11:16:01 +02:00
|
|
|
Utils::sort(m_locations, &LocationInfo::priority);
|
2017-07-05 16:01:59 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-26 13:52:07 +02:00
|
|
|
const QVector<FolderNode::LocationInfo> FolderNode::locationInfo() const
|
2017-07-05 16:01:59 +02:00
|
|
|
{
|
|
|
|
|
return m_locations;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-02 17:00:46 +01:00
|
|
|
QString FolderNode::addFileFilter() const
|
|
|
|
|
{
|
2019-02-28 16:45:00 +01:00
|
|
|
if (!m_addFileFilter.isNull())
|
|
|
|
|
return m_addFileFilter;
|
|
|
|
|
|
2017-05-08 14:18:03 +02:00
|
|
|
FolderNode *fn = parentFolderNode();
|
|
|
|
|
return fn ? fn->addFileFilter() : QString();
|
2015-11-02 17:00:46 +01:00
|
|
|
}
|
|
|
|
|
|
2017-05-31 15:48:45 +02:00
|
|
|
bool FolderNode::supportsAction(ProjectAction action, const Node *node) const
|
2017-03-15 15:46:48 +01:00
|
|
|
{
|
|
|
|
|
if (action == InheritedFromParent)
|
|
|
|
|
return true;
|
|
|
|
|
FolderNode *parentFolder = parentFolderNode();
|
|
|
|
|
return parentFolder && parentFolder->supportsAction(action, node);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-14 16:49:42 +02:00
|
|
|
bool FolderNode::addFiles(const FilePaths &filePaths, FilePaths *notAdded)
|
2014-02-03 15:18:33 +01:00
|
|
|
{
|
2016-11-11 10:11:51 +01:00
|
|
|
ProjectNode *pn = managingProject();
|
|
|
|
|
if (pn)
|
|
|
|
|
return pn->addFiles(filePaths, notAdded);
|
2014-02-03 15:18:33 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-14 16:49:42 +02:00
|
|
|
RemovedFilesFromProject FolderNode::removeFiles(const FilePaths &filePaths, FilePaths *notRemoved)
|
2014-02-03 15:18:33 +01:00
|
|
|
{
|
2019-06-18 14:39:38 +03:00
|
|
|
if (ProjectNode * const pn = managingProject())
|
2016-11-11 10:11:51 +01:00
|
|
|
return pn->removeFiles(filePaths, notRemoved);
|
2019-06-18 14:39:38 +03:00
|
|
|
return RemovedFilesFromProject::Error;
|
2014-02-03 15:18:33 +01:00
|
|
|
}
|
|
|
|
|
|
2021-07-14 16:49:42 +02:00
|
|
|
bool FolderNode::deleteFiles(const FilePaths &filePaths)
|
2014-02-03 15:18:33 +01:00
|
|
|
{
|
2016-11-11 10:11:51 +01:00
|
|
|
ProjectNode *pn = managingProject();
|
|
|
|
|
if (pn)
|
|
|
|
|
return pn->deleteFiles(filePaths);
|
2014-02-03 15:18:33 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-09 14:03:54 +02:00
|
|
|
bool FolderNode::canRenameFile(const FilePath &oldFilePath, const FilePath &newFilePath)
|
2015-09-14 15:33:50 +02:00
|
|
|
{
|
2016-11-11 10:11:51 +01:00
|
|
|
ProjectNode *pn = managingProject();
|
|
|
|
|
if (pn)
|
2021-06-11 14:34:34 +02:00
|
|
|
return pn->canRenameFile(oldFilePath, newFilePath);
|
2015-09-14 15:33:50 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-09 14:03:54 +02:00
|
|
|
bool FolderNode::renameFile(const FilePath &oldFilePath, const FilePath &newFilePath)
|
2014-02-03 15:18:33 +01:00
|
|
|
{
|
2016-11-11 10:11:51 +01:00
|
|
|
ProjectNode *pn = managingProject();
|
|
|
|
|
if (pn)
|
2021-06-11 14:34:34 +02:00
|
|
|
return pn->renameFile(oldFilePath, newFilePath);
|
2014-02-03 15:18:33 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-18 15:41:27 +02:00
|
|
|
bool FolderNode::addDependencies(const QStringList &dependencies)
|
|
|
|
|
{
|
|
|
|
|
if (ProjectNode * const pn = managingProject())
|
|
|
|
|
return pn->addDependencies(dependencies);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-09 14:03:54 +02:00
|
|
|
FolderNode::AddNewInformation FolderNode::addNewInformation(const FilePaths &files, Node *context) const
|
2014-02-18 16:31:36 +01:00
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(files)
|
2015-04-08 17:01:01 +02:00
|
|
|
return AddNewInformation(displayName(), context == this ? 120 : 100);
|
2014-02-18 16:31:36 +01:00
|
|
|
}
|
|
|
|
|
|
2014-02-18 19:49:55 +01:00
|
|
|
/*!
|
2017-02-08 14:50:43 +01:00
|
|
|
Adds a node specified by \a node to the internal list of nodes.
|
2014-02-18 19:49:55 +01:00
|
|
|
*/
|
|
|
|
|
|
2018-04-26 11:00:59 +02:00
|
|
|
void FolderNode::addNode(std::unique_ptr<Node> &&node)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(node, return);
|
|
|
|
|
QTC_ASSERT(!node->parentFolderNode(), qDebug("Node has already a parent folder"));
|
2017-02-08 14:50:43 +01:00
|
|
|
node->setParentFolderNode(this);
|
2018-04-26 11:00:59 +02:00
|
|
|
m_nodes.emplace_back(std::move(node));
|
2014-02-18 19:49:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
2018-04-26 14:50:35 +02:00
|
|
|
Return a node specified by \a node from the internal list.
|
2014-02-18 19:49:55 +01:00
|
|
|
*/
|
|
|
|
|
|
2018-04-26 11:00:59 +02:00
|
|
|
std::unique_ptr<Node> FolderNode::takeNode(Node *node)
|
|
|
|
|
{
|
|
|
|
|
return Utils::takeOrDefault(m_nodes, node);
|
2017-01-19 11:32:53 +01:00
|
|
|
}
|
|
|
|
|
|
2014-03-17 11:52:45 +01:00
|
|
|
bool FolderNode::showInSimpleTree() const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-17 12:56:15 +02:00
|
|
|
bool FolderNode::showWhenEmpty() const
|
|
|
|
|
{
|
2019-03-01 17:46:45 +01:00
|
|
|
return m_showWhenEmpty;
|
2017-08-17 12:56:15 +02:00
|
|
|
}
|
|
|
|
|
|
2012-05-04 11:49:37 +02:00
|
|
|
/*!
|
|
|
|
|
\class ProjectExplorer::VirtualFolderNode
|
|
|
|
|
|
|
|
|
|
In-memory presentation of a virtual folder.
|
|
|
|
|
Note that the node itself + all children (files and folders) are "managed" by the owning project.
|
|
|
|
|
A virtual folder does not correspond to a actual folder on the file system. See for example the
|
2013-10-29 17:37:39 +01:00
|
|
|
sources, headers and forms folder the QmakeProjectManager creates
|
2012-05-04 11:49:37 +02:00
|
|
|
VirtualFolderNodes are always sorted before FolderNodes and are sorted according to their priority.
|
|
|
|
|
|
|
|
|
|
\sa ProjectExplorer::FileNode, ProjectExplorer::ProjectNode
|
|
|
|
|
*/
|
2021-08-09 14:03:54 +02:00
|
|
|
VirtualFolderNode::VirtualFolderNode(const FilePath &folderPath) :
|
2019-02-25 18:32:12 +01:00
|
|
|
FolderNode(folderPath)
|
2012-05-04 11:49:37 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2011-04-14 12:58:14 +02:00
|
|
|
\class ProjectExplorer::ProjectNode
|
|
|
|
|
|
2013-09-10 17:16:10 +02:00
|
|
|
\brief The ProjectNode class is an in-memory presentation of a Project.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-09-10 17:16:10 +02:00
|
|
|
A concrete subclass must implement the persistent data.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
\sa ProjectExplorer::FileNode, ProjectExplorer::FolderNode
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
|
|
|
|
|
2011-04-14 12:58:14 +02:00
|
|
|
/*!
|
2013-09-10 17:16:10 +02:00
|
|
|
Creates an uninitialized project node object.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
2021-08-09 14:03:54 +02:00
|
|
|
ProjectNode::ProjectNode(const FilePath &projectFilePath) :
|
2019-02-25 18:32:12 +01:00
|
|
|
FolderNode(projectFilePath)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2016-11-10 16:56:15 +01:00
|
|
|
setPriority(DefaultProjectPriority);
|
2017-05-09 08:44:19 +03:00
|
|
|
setListInProject(true);
|
2019-02-25 18:08:36 +01:00
|
|
|
setDisplayName(projectFilePath.fileName());
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2021-08-09 14:03:54 +02:00
|
|
|
bool ProjectNode::canAddSubProject(const FilePath &proFilePath) const
|
2015-09-10 17:47:57 +02:00
|
|
|
{
|
|
|
|
|
Q_UNUSED(proFilePath)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2021-08-09 14:03:54 +02:00
|
|
|
bool ProjectNode::addSubProject(const FilePath &proFilePath)
|
2015-09-10 17:47:57 +02:00
|
|
|
{
|
2017-03-15 14:45:54 +01:00
|
|
|
Q_UNUSED(proFilePath)
|
2015-09-10 17:47:57 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2019-02-19 18:06:10 +01:00
|
|
|
QStringList ProjectNode::subProjectFileNamePatterns() const
|
|
|
|
|
{
|
|
|
|
|
return QStringList();
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-09 14:03:54 +02:00
|
|
|
bool ProjectNode::removeSubProject(const FilePath &proFilePath)
|
2015-09-10 17:47:57 +02:00
|
|
|
{
|
2017-03-15 14:45:54 +01:00
|
|
|
Q_UNUSED(proFilePath)
|
2015-09-10 17:47:57 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2021-07-14 16:49:42 +02:00
|
|
|
bool ProjectNode::addFiles(const FilePaths &filePaths, FilePaths *notAdded)
|
2015-09-10 17:47:57 +02:00
|
|
|
{
|
2019-10-22 14:55:51 +02:00
|
|
|
if (BuildSystem *bs = buildSystem())
|
|
|
|
|
return bs->addFiles(this, filePaths, notAdded);
|
2015-09-10 17:47:57 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2021-07-14 16:49:42 +02:00
|
|
|
RemovedFilesFromProject ProjectNode::removeFiles(const FilePaths &filePaths, FilePaths *notRemoved)
|
2015-09-10 17:47:57 +02:00
|
|
|
{
|
2019-10-22 14:55:51 +02:00
|
|
|
if (BuildSystem *bs = buildSystem())
|
|
|
|
|
return bs->removeFiles(this, filePaths, notRemoved);
|
2019-06-18 14:39:38 +03:00
|
|
|
return RemovedFilesFromProject::Error;
|
2015-09-10 17:47:57 +02:00
|
|
|
}
|
|
|
|
|
|
2021-07-14 16:49:42 +02:00
|
|
|
bool ProjectNode::deleteFiles(const FilePaths &filePaths)
|
2015-09-10 17:47:57 +02:00
|
|
|
{
|
2019-10-22 14:55:51 +02:00
|
|
|
if (BuildSystem *bs = buildSystem())
|
|
|
|
|
return bs->deleteFiles(this, filePaths);
|
2015-09-10 17:47:57 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-11 14:34:34 +02:00
|
|
|
bool ProjectNode::canRenameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath)
|
2015-09-14 15:33:50 +02:00
|
|
|
{
|
2019-10-22 14:55:51 +02:00
|
|
|
if (BuildSystem *bs = buildSystem())
|
2021-06-11 14:34:34 +02:00
|
|
|
return bs->canRenameFile(this, oldFilePath, newFilePath);
|
2015-09-14 15:33:50 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-11 14:34:34 +02:00
|
|
|
bool ProjectNode::renameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath)
|
2015-09-10 17:47:57 +02:00
|
|
|
{
|
2019-10-22 14:55:51 +02:00
|
|
|
if (BuildSystem *bs = buildSystem())
|
2021-06-11 14:34:34 +02:00
|
|
|
return bs->renameFile(this, oldFilePath, newFilePath);
|
2015-09-10 17:47:57 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2019-06-18 15:41:27 +02:00
|
|
|
bool ProjectNode::addDependencies(const QStringList &dependencies)
|
|
|
|
|
{
|
2019-10-22 14:55:51 +02:00
|
|
|
if (BuildSystem *bs = buildSystem())
|
|
|
|
|
return bs->addDependencies(this, dependencies);
|
2019-06-18 15:41:27 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 14:55:51 +02:00
|
|
|
bool ProjectNode::supportsAction(ProjectAction action, const Node *node) const
|
2017-04-06 23:42:17 +03:00
|
|
|
{
|
2019-10-22 14:55:51 +02:00
|
|
|
if (BuildSystem *bs = buildSystem())
|
|
|
|
|
return bs->supportsAction(const_cast<ProjectNode *>(this), action, node);
|
2017-04-06 23:42:17 +03:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-24 17:17:11 +02:00
|
|
|
bool ProjectNode::deploysFolder(const QString &folder) const
|
|
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(folder)
|
2010-08-24 17:17:11 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
ProjectNode *ProjectNode::projectNode(const Utils::FilePath &file) const
|
2016-11-07 13:56:57 +01:00
|
|
|
{
|
2018-04-26 11:00:59 +02:00
|
|
|
for (const std::unique_ptr<Node> &n: m_nodes) {
|
|
|
|
|
if (ProjectNode *pnode = n->asProjectNode())
|
2017-02-07 13:49:37 +01:00
|
|
|
if (pnode->filePath() == file)
|
|
|
|
|
return pnode;
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2016-11-07 13:56:57 +01:00
|
|
|
}
|
|
|
|
|
|
2020-06-26 13:59:38 +02:00
|
|
|
QVariant ProjectNode::data(Utils::Id role) const
|
2018-12-05 10:29:48 +01:00
|
|
|
{
|
2019-08-01 11:53:26 +02:00
|
|
|
return m_fallbackData.value(role);
|
2018-12-05 10:29:48 +01:00
|
|
|
}
|
|
|
|
|
|
2020-06-26 13:59:38 +02:00
|
|
|
bool ProjectNode::setData(Utils::Id role, const QVariant &value) const
|
2018-12-05 10:29:48 +01:00
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(role)
|
|
|
|
|
Q_UNUSED(value)
|
2018-12-05 10:29:48 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-26 13:59:38 +02:00
|
|
|
void ProjectNode::setFallbackData(Utils::Id key, const QVariant &value)
|
2019-08-01 11:53:26 +02:00
|
|
|
{
|
|
|
|
|
m_fallbackData.insert(key, value);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 14:55:51 +02:00
|
|
|
BuildSystem *ProjectNode::buildSystem() const
|
|
|
|
|
{
|
|
|
|
|
Project *p = getProject();
|
2019-10-25 09:55:32 +02:00
|
|
|
Target *t = p ? p->activeTarget() : nullptr;
|
|
|
|
|
return t ? t->buildSystem() : nullptr;
|
2019-10-22 14:55:51 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-07 13:49:37 +01:00
|
|
|
bool FolderNode::isEmpty() const
|
2017-01-26 17:02:16 +01:00
|
|
|
{
|
2018-04-26 11:00:59 +02:00
|
|
|
return m_nodes.size() == 0;
|
2017-01-26 17:02:16 +01:00
|
|
|
}
|
|
|
|
|
|
2018-01-19 11:55:28 +01:00
|
|
|
void FolderNode::handleSubTreeChanged(FolderNode *node)
|
|
|
|
|
{
|
|
|
|
|
if (FolderNode *parent = parentFolderNode())
|
|
|
|
|
parent->handleSubTreeChanged(node);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-01 17:46:45 +01:00
|
|
|
void FolderNode::setShowWhenEmpty(bool showWhenEmpty)
|
|
|
|
|
{
|
|
|
|
|
m_showWhenEmpty = showWhenEmpty;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-27 17:51:19 +02:00
|
|
|
ContainerNode::ContainerNode(Project *project)
|
2019-02-25 18:32:12 +01:00
|
|
|
: FolderNode(project->projectDirectory()), m_project(project)
|
|
|
|
|
{
|
|
|
|
|
}
|
2017-03-27 17:51:19 +02:00
|
|
|
|
|
|
|
|
QString ContainerNode::displayName() const
|
|
|
|
|
{
|
|
|
|
|
QString name = m_project->displayName();
|
|
|
|
|
|
2021-07-30 16:46:27 +02:00
|
|
|
const FilePath fp = m_project->projectFilePath();
|
|
|
|
|
const FilePath dir = fp.isDir() ? fp.absoluteFilePath() : fp.absolutePath();
|
2017-03-27 17:51:19 +02:00
|
|
|
if (Core::IVersionControl *vc = Core::VcsManager::findVersionControlForDirectory(dir)) {
|
2021-07-30 16:46:27 +02:00
|
|
|
QString vcsTopic = vc->vcsTopic(dir);
|
2017-03-27 17:51:19 +02:00
|
|
|
if (!vcsTopic.isEmpty())
|
|
|
|
|
name += " [" + vcsTopic + ']';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-31 15:48:45 +02:00
|
|
|
bool ContainerNode::supportsAction(ProjectAction action, const Node *node) const
|
2017-03-27 17:51:19 +02:00
|
|
|
{
|
2017-05-31 15:48:45 +02:00
|
|
|
const Node *rootNode = m_project->rootProjectNode();
|
2017-03-15 15:46:48 +01:00
|
|
|
return rootNode && rootNode->supportsAction(action, node);
|
2017-03-27 17:51:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProjectNode *ContainerNode::rootProjectNode() const
|
|
|
|
|
{
|
|
|
|
|
return m_project->rootProjectNode();
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-15 20:46:47 +02:00
|
|
|
void ContainerNode::removeAllChildren()
|
|
|
|
|
{
|
|
|
|
|
m_nodes.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-19 11:55:28 +01:00
|
|
|
void ContainerNode::handleSubTreeChanged(FolderNode *node)
|
|
|
|
|
{
|
|
|
|
|
m_project->handleSubTreeChanged(node);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-08 16:31:31 +02:00
|
|
|
/*!
|
|
|
|
|
\class ProjectExplorer::DirectoryIcon
|
|
|
|
|
|
|
|
|
|
The DirectoryIcon class represents a directory icon with an overlay.
|
|
|
|
|
|
|
|
|
|
The QIcon is created on demand and globally cached, so other DirectoryIcon
|
|
|
|
|
instances with the same overlay share the same QIcon instance.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Creates a DirectoryIcon for the specified \a overlay.
|
|
|
|
|
*/
|
|
|
|
|
DirectoryIcon::DirectoryIcon(const QString &overlay)
|
|
|
|
|
: m_overlay(overlay)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Returns the icon for this DirectoryIcon. Calling this method is only safe in the UI thread.
|
|
|
|
|
*/
|
|
|
|
|
QIcon DirectoryIcon::icon() const
|
|
|
|
|
{
|
2022-10-10 15:59:26 +02:00
|
|
|
QTC_CHECK(isMainThread());
|
2021-04-08 16:31:31 +02:00
|
|
|
const auto it = m_cache.find(m_overlay);
|
|
|
|
|
if (it != m_cache.end())
|
|
|
|
|
return it.value();
|
2022-05-31 11:16:44 +02:00
|
|
|
const QIcon icon = Utils::FileIconProvider::directoryIcon(m_overlay);
|
2021-04-08 16:31:31 +02:00
|
|
|
m_cache.insert(m_overlay, icon);
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-14 12:34:15 +02:00
|
|
|
ResourceFileNode::ResourceFileNode(const FilePath &filePath, const QString &qrcPath, const QString &displayName)
|
|
|
|
|
: FileNode(filePath, FileNode::fileTypeForFileName(filePath))
|
|
|
|
|
, m_qrcPath(qrcPath)
|
|
|
|
|
, m_displayName(displayName)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString ResourceFileNode::displayName() const
|
|
|
|
|
{
|
|
|
|
|
return m_displayName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString ResourceFileNode::qrcPath() const
|
|
|
|
|
{
|
|
|
|
|
return m_qrcPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ResourceFileNode::supportsAction(ProjectAction action, const Node *node) const
|
|
|
|
|
{
|
|
|
|
|
if (action == HidePathActions)
|
|
|
|
|
return false;
|
|
|
|
|
return parentFolderNode()->supportsAction(action, node);
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 15:52:14 +02:00
|
|
|
} // namespace ProjectExplorer
|