aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmlprojectmanager
diff options
context:
space:
mode:
authorhjk <hjk@qt.io>2019-10-25 09:55:32 +0200
committerhjk <hjk@qt.io>2019-11-19 11:05:52 +0000
commit27586827238ca9079860e77a7b23ae20d163143e (patch)
tree2197dc7f97a4a70524381071888336558dc0b4a3 /src/plugins/qmlprojectmanager
parent9073c46c9c431ec0e83987a5781163ca7b1f7ea7 (diff)
ProjectExplorer: Move BuildSystem owership to BuildConfiguration
... or Target. This patch moves build system from conceptually "one per project" to "one per target (i.e. per project-and-kit)" or "per BuildConfigurations" for targets where the builds differ significantly. Building requires usually items from the kit (Qt version, compiler, ...) so a target-agnostic build is practically almost always wrong. Moving the build system to the target also has the potential to solve issues caused by switching targets while parsing, that used Project::activeTarget() regularly, with potentially different results before and after the switch. This patch might create performance/size regressions when several targets are set up per project as the build system implementation's internal data are duplicated in this case. The idea is to fix that by sharing per-project pieces again in the project implementation once these problems occur. Change-Id: I87f640ce418b93175b5029124eaa55f3b8721dca Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src/plugins/qmlprojectmanager')
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp246
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.h61
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectnodes.cpp103
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectnodes.h8
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp63
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h2
6 files changed, 231 insertions, 252 deletions
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index d227db6fe5..afe577487a 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "qmlproject.h"
+
#include "fileformat/qmlprojectfileformat.h"
#include "fileformat/qmlprojectitem.h"
#include "qmlprojectrunconfiguration.h"
@@ -31,6 +32,9 @@
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectnodes.h"
+#include <coreplugin/documentmanager.h>
+#include <coreplugin/editormanager/documentmodel.h>
+#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
@@ -46,66 +50,84 @@
#include <qmljs/qmljsmodelmanagerinterface.h>
+#include <texteditor/textdocument.h>
+
#include <utils/algorithm.h>
#include <QDebug>
+#include <QRegularExpression>
+#include <QTextCodec>
using namespace Core;
using namespace ProjectExplorer;
+using namespace QmlProjectManager::Internal;
namespace QmlProjectManager {
QmlProject::QmlProject(const Utils::FilePath &fileName)
: Project(QString::fromLatin1(Constants::QMLPROJECT_MIMETYPE), fileName)
{
- const QString normalized
- = Utils::FileUtils::normalizePathName(fileName.toFileInfo().canonicalFilePath());
- m_canonicalProjectDir = Utils::FilePath::fromString(normalized).parentDir();
-
setId(QmlProjectManager::Constants::QML_PROJECT_ID);
setProjectLanguages(Context(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID));
setDisplayName(fileName.toFileInfo().completeBaseName());
setNeedsBuildConfigurations(false);
- setBuildSystemCreator([](Project *p) { return new Internal::QmlBuildSystem(p); });
+ setBuildSystemCreator([](Target *t) { return new QmlBuildSystem(t); });
+}
+
+QmlBuildSystem::QmlBuildSystem(Target *target)
+ : BuildSystem(target)
+{
+ const QString normalized
+ = Utils::FileUtils::normalizePathName(target->project()
+ ->projectFilePath().toFileInfo().canonicalFilePath());
+ m_canonicalProjectDir = Utils::FilePath::fromString(normalized).parentDir();
+
+ connect(target->project(), &Project::projectFileIsDirty,
+ this, &QmlBuildSystem::refreshProjectFile);
- connect(this, &QmlProject::projectFileIsDirty, this, &QmlProject::refreshProjectFile);
+ // refresh first - project information is used e.g. to decide the default RC's
+ refresh(Everything);
+
+// FIXME: Check. Probably bogus after the BuildSystem move.
+// // addedTarget calls updateEnabled on the runconfigurations
+// // which needs to happen after refresh
+// foreach (Target *t, targets())
+// addedTarget(t);
+
+ connect(target->project(), &Project::activeTargetChanged,
+ this, &QmlBuildSystem::onActiveTargetChanged);
+ updateDeploymentData();
}
-QmlProject::~QmlProject()
+QmlBuildSystem::~QmlBuildSystem()
{
delete m_projectItem.data();
}
-void QmlProject::addedTarget(Target *target)
+void QmlBuildSystem::triggerParsing()
{
- updateDeploymentData(target);
+ refresh(Everything);
}
-void QmlProject::onActiveTargetChanged(Target *target)
+void QmlBuildSystem::onActiveTargetChanged(Target *)
{
- if (m_activeTarget)
- disconnect(m_activeTarget, &Target::kitChanged, this, &QmlProject::onKitChanged);
- m_activeTarget = target;
- if (m_activeTarget)
- connect(target, &Target::kitChanged, this, &QmlProject::onKitChanged);
-
// make sure e.g. the default qml imports are adapted
refresh(Configuration);
}
-void QmlProject::onKitChanged()
+void QmlBuildSystem::onKitChanged()
{
// make sure e.g. the default qml imports are adapted
refresh(Configuration);
}
-Utils::FilePath QmlProject::canonicalProjectDir() const
+Utils::FilePath QmlBuildSystem::canonicalProjectDir() const
{
return m_canonicalProjectDir;
}
-void QmlProject::parseProject(RefreshOptions options)
+void QmlBuildSystem::parseProject(RefreshOptions options)
{
if (options & Files) {
if (options & ProjectFile)
@@ -115,7 +137,7 @@ void QmlProject::parseProject(RefreshOptions options)
m_projectItem = QmlProjectFileFormat::parseProjectFile(projectFilePath(), &errorMessage);
if (m_projectItem) {
connect(m_projectItem.data(), &QmlProjectItem::qmlFilesChanged,
- this, &QmlProject::refreshFiles);
+ this, &QmlBuildSystem::refreshFiles);
} else {
MessageManager::write(tr("Error while loading project file %1.")
@@ -153,7 +175,7 @@ void QmlProject::parseProject(RefreshOptions options)
}
}
-void QmlProject::refresh(RefreshOptions options)
+void QmlBuildSystem::refresh(RefreshOptions options)
{
ParseGuard guard = guardParsingRun();
parseProject(options);
@@ -166,32 +188,32 @@ void QmlProject::refresh(RefreshOptions options)
return;
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
- modelManager->defaultProjectInfoForProject(this);
+ modelManager->defaultProjectInfoForProject(project());
foreach (const QString &searchPath, makeAbsolute(canonicalProjectDir(), customImportPaths()))
projectInfo.importPaths.maybeInsert(Utils::FilePath::fromString(searchPath),
QmlJS::Dialect::Qml);
- modelManager->updateProjectInfo(projectInfo, this);
+ modelManager->updateProjectInfo(projectInfo, project());
guard.markAsSuccess();
}
-QString QmlProject::mainFile() const
+QString QmlBuildSystem::mainFile() const
{
if (m_projectItem)
return m_projectItem.data()->mainFile();
return QString();
}
-void QmlProject::setMainFile(const QString &mainFilePath)
+void QmlBuildSystem::setMainFile(const QString &mainFilePath)
{
if (m_projectItem)
m_projectItem.data()->setMainFile(mainFilePath);
}
-Utils::FilePath QmlProject::targetDirectory(const Target *target) const
+Utils::FilePath QmlBuildSystem::targetDirectory() const
{
- if (DeviceTypeKitAspect::deviceTypeId(target->kit())
+ if (DeviceTypeKitAspect::deviceTypeId(target()->kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
return canonicalProjectDir();
@@ -199,53 +221,42 @@ Utils::FilePath QmlProject::targetDirectory(const Target *target) const
: Utils::FilePath();
}
-Utils::FilePath QmlProject::targetFile(const Utils::FilePath &sourceFile,
- const Target *target) const
+Utils::FilePath QmlBuildSystem::targetFile(const Utils::FilePath &sourceFile) const
{
const QDir sourceDir(m_projectItem ? m_projectItem->sourceDirectory()
: canonicalProjectDir().toString());
- const QDir targetDir(targetDirectory(target).toString());
+ const QDir targetDir(targetDirectory().toString());
const QString relative = sourceDir.relativeFilePath(sourceFile.toString());
return Utils::FilePath::fromString(QDir::cleanPath(targetDir.absoluteFilePath(relative)));
}
-Utils::EnvironmentItems QmlProject::environment() const
+Utils::EnvironmentItems QmlBuildSystem::environment() const
{
if (m_projectItem)
return m_projectItem.data()->environment();
return {};
}
-QStringList QmlProject::customImportPaths() const
+QStringList QmlBuildSystem::customImportPaths() const
{
if (m_projectItem)
return m_projectItem.data()->importPaths();
return {};
}
-QStringList QmlProject::customFileSelectors() const
+QStringList QmlBuildSystem::customFileSelectors() const
{
if (m_projectItem)
return m_projectItem.data()->fileSelectors();
return {};
}
-bool QmlProject::addFiles(const QStringList &filePaths)
-{
- QStringList toAdd;
- foreach (const QString &filePath, filePaths) {
- if (!m_projectItem.data()->matchesFile(filePath))
- toAdd << filePaths;
- }
- return toAdd.isEmpty();
-}
-
-void QmlProject::refreshProjectFile()
+void QmlBuildSystem::refreshProjectFile()
{
- refresh(QmlProject::ProjectFile | Files);
+ refresh(QmlBuildSystem::ProjectFile | Files);
}
-QStringList QmlProject::makeAbsolute(const Utils::FilePath &path, const QStringList &relativePaths)
+QStringList QmlBuildSystem::makeAbsolute(const Utils::FilePath &path, const QStringList &relativePaths)
{
if (path.isEmpty())
return relativePaths;
@@ -256,14 +267,7 @@ QStringList QmlProject::makeAbsolute(const Utils::FilePath &path, const QStringL
});
}
-QVariant QmlProject::additionalData(Id id, const Target *) const
-{
- if (id == Constants::customFileSelectorsData)
- return customFileSelectors();
- return {};
-}
-
-void QmlProject::refreshFiles(const QSet<QString> &/*added*/, const QSet<QString> &removed)
+void QmlBuildSystem::refreshFiles(const QSet<QString> &/*added*/, const QSet<QString> &removed)
{
refresh(Files);
if (!removed.isEmpty()) {
@@ -273,11 +277,9 @@ void QmlProject::refreshFiles(const QSet<QString> &/*added*/, const QSet<QString
refreshTargetDirectory();
}
-void QmlProject::refreshTargetDirectory()
+void QmlBuildSystem::refreshTargetDirectory()
{
- const QList<Target *> targetList = targets();
- for (Target *target : targetList)
- updateDeploymentData(target);
+ updateDeploymentData();
}
Tasks QmlProject::projectIssues(const Kit *k) const
@@ -324,9 +326,6 @@ Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *erro
if (result != RestoreResult::Ok)
return result;
- // refresh first - project information is used e.g. to decide the default RC's
- refresh(Everything);
-
if (!activeTarget()) {
// find a kit that matches prerequisites (prefer default one)
const QList<Kit*> kits = Utils::filtered(KitManager::kits(), [this](const Kit *k) {
@@ -341,18 +340,6 @@ Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *erro
}
}
- // addedTarget calls updateEnabled on the runconfigurations
- // which needs to happen after refresh
- foreach (Target *t, targets())
- addedTarget(t);
-
- connect(this, &ProjectExplorer::Project::addedTarget, this, &QmlProject::addedTarget);
-
- connect(this, &ProjectExplorer::Project::activeTargetChanged,
- this, &QmlProject::onActiveTargetChanged);
-
- onActiveTargetChanged(activeTarget());
-
return RestoreResult::Ok;
}
@@ -361,12 +348,12 @@ ProjectExplorer::DeploymentKnowledge QmlProject::deploymentKnowledge() const
return DeploymentKnowledge::Perfect;
}
-void QmlProject::generateProjectTree()
+void QmlBuildSystem::generateProjectTree()
{
if (!m_projectItem)
return;
- auto newRoot = std::make_unique<Internal::QmlProjectNode>(this);
+ auto newRoot = std::make_unique<QmlProjectNode>(project());
for (const QString &f : m_projectItem.data()->files()) {
const Utils::FilePath fileName = Utils::FilePath::fromString(f);
@@ -376,16 +363,16 @@ void QmlProject::generateProjectTree()
}
newRoot->addNestedNode(std::make_unique<FileNode>(projectFilePath(), FileType::Project));
- setRootProjectNode(std::move(newRoot));
+ project()->setRootProjectNode(std::move(newRoot));
refreshTargetDirectory();
}
-void QmlProject::updateDeploymentData(ProjectExplorer::Target *target)
+void QmlBuildSystem::updateDeploymentData()
{
if (!m_projectItem)
return;
- if (DeviceTypeKitAspect::deviceTypeId(target->kit())
+ if (DeviceTypeKitAspect::deviceTypeId(target()->kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
return;
}
@@ -394,10 +381,109 @@ void QmlProject::updateDeploymentData(ProjectExplorer::Target *target)
for (const QString &file : m_projectItem->files()) {
deploymentData.addFile(
file,
- targetFile(Utils::FilePath::fromString(file), target).parentDir().toString());
+ targetFile(Utils::FilePath::fromString(file)).parentDir().toString());
+ }
+
+ setDeploymentData(deploymentData);
+}
+
+QVariant QmlBuildSystem::additionalData(Id id) const
+{
+ if (id == Constants::customFileSelectorsData)
+ return customFileSelectors();
+ return {};
+}
+
+bool QmlBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
+{
+ if (dynamic_cast<QmlProjectNode *>(context)) {
+ if (action == AddNewFile || action == EraseFile)
+ return true;
+ QTC_ASSERT(node, return false);
+
+ if (action == Rename && node->asFileNode()) {
+ const FileNode *fileNode = node->asFileNode();
+ QTC_ASSERT(fileNode, return false);
+ return fileNode->fileType() != FileType::Project;
+ }
+
+ return false;
+ }
+
+ return BuildSystem::supportsAction(context, action, node);
+}
+
+QmlProject *QmlBuildSystem::qmlProject() const
+{
+ return static_cast<QmlProject *>(BuildSystem::project());
+}
+
+bool QmlBuildSystem::addFiles(Node *context, const QStringList &filePaths, QStringList *)
+{
+ if (!dynamic_cast<QmlProjectNode *>(context))
+ return false;
+
+ QStringList toAdd;
+ foreach (const QString &filePath, filePaths) {
+ if (!m_projectItem.data()->matchesFile(filePath))
+ toAdd << filePaths;
+ }
+ return toAdd.isEmpty();
+}
+
+bool QmlBuildSystem::deleteFiles(Node *context, const QStringList &filePaths)
+{
+ if (dynamic_cast<QmlProjectNode *>(context))
+ return true;
+
+ return BuildSystem::deleteFiles(context, filePaths);
+}
+
+bool QmlBuildSystem::renameFile(Node * context, const QString &filePath, const QString &newFilePath)
+{
+ if (dynamic_cast<QmlProjectNode *>(context)) {
+ if (filePath.endsWith(mainFile())) {
+ setMainFile(newFilePath);
+
+ // make sure to change it also in the qmlproject file
+ const QString qmlProjectFilePath = project()->projectFilePath().toString();
+ Core::FileChangeBlocker fileChangeBlocker(qmlProjectFilePath);
+ const QList<Core::IEditor *> editors = Core::DocumentModel::editorsForFilePath(qmlProjectFilePath);
+ TextEditor::TextDocument *document = nullptr;
+ if (!editors.isEmpty()) {
+ document = qobject_cast<TextEditor::TextDocument*>(editors.first()->document());
+ if (document && document->isModified())
+ if (!Core::DocumentManager::saveDocument(document))
+ return false;
+ }
+
+ QString fileContent;
+ QString error;
+ Utils::TextFileFormat textFileFormat;
+ const QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // qml files are defined to be utf-8
+ if (Utils::TextFileFormat::readFile(qmlProjectFilePath, codec, &fileContent, &textFileFormat, &error)
+ != Utils::TextFileFormat::ReadSuccess) {
+ qWarning() << "Failed to read file" << qmlProjectFilePath << ":" << error;
+ }
+
+ // find the mainFile and do the file name with brackets in a capture group and mask the . with \.
+ QString originalFileName = QFileInfo(filePath).fileName();
+ originalFileName.replace(".", "\\.");
+ const QRegularExpression expression(QString("mainFile:\\s*\"(%1)\"").arg(originalFileName));
+ const QRegularExpressionMatch match = expression.match(fileContent);
+
+ fileContent.replace(match.capturedStart(1), match.capturedLength(1), QFileInfo(newFilePath).fileName());
+
+ if (!textFileFormat.writeFile(qmlProjectFilePath, fileContent, &error))
+ qWarning() << "Failed to write file" << qmlProjectFilePath << ":" << error;
+
+ refresh(Everything);
+ }
+
+ return true;
}
- target->setDeploymentData(deploymentData);
+ return BuildSystem::renameFile(context, filePath, newFilePath);
}
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index d911d7946e..2fe1d6dfd7 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -35,19 +35,18 @@
#include <QPointer>
-namespace ProjectExplorer { class RunConfiguration; }
-
namespace QmlProjectManager {
class QmlProject;
class QmlProjectItem;
-namespace Internal {
-
class QmlBuildSystem : public ProjectExplorer::BuildSystem
{
public:
- explicit QmlBuildSystem(ProjectExplorer::Project *project) : BuildSystem(project) {}
+ explicit QmlBuildSystem(ProjectExplorer::Target *target);
+ ~QmlBuildSystem();
+
+ void triggerParsing() final;
bool supportsAction(ProjectExplorer::Node *context,
ProjectExplorer::ProjectAction action,
@@ -59,20 +58,9 @@ public:
bool renameFile(ProjectExplorer::Node *context,
const QString &filePath, const QString &newFilePath) override;
- QmlProject *project() const;
-};
-
-} // Internal
+ QmlProject *qmlProject() const;
-class QMLPROJECTMANAGER_EXPORT QmlProject : public ProjectExplorer::Project
-{
- Q_OBJECT
-
-public:
- explicit QmlProject(const Utils::FilePath &filename);
- ~QmlProject() override;
-
- ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
+ QVariant additionalData(Core::Id id) const override;
enum RefreshOption {
ProjectFile = 0x01,
@@ -87,9 +75,8 @@ public:
Utils::FilePath canonicalProjectDir() const;
QString mainFile() const;
void setMainFile(const QString &mainFilePath);
- Utils::FilePath targetDirectory(const ProjectExplorer::Target *target) const;
- Utils::FilePath targetFile(const Utils::FilePath &sourceFile,
- const ProjectExplorer::Target *target) const;
+ Utils::FilePath targetDirectory() const;
+ Utils::FilePath targetFile(const Utils::FilePath &sourceFile) const;
Utils::EnvironmentItems environment() const;
QStringList customImportPaths() const;
@@ -101,31 +88,37 @@ public:
static QStringList makeAbsolute(const Utils::FilePath &path, const QStringList &relativePaths);
- QVariant additionalData(Core::Id id, const ProjectExplorer::Target *target) const override;
-
-protected:
- RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
-
-private:
- ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
-
void generateProjectTree();
- void updateDeploymentData(ProjectExplorer::Target *target);
+ void updateDeploymentData();
void refreshFiles(const QSet<QString> &added, const QSet<QString> &removed);
void refreshTargetDirectory();
- void addedTarget(ProjectExplorer::Target *target);
void onActiveTargetChanged(ProjectExplorer::Target *target);
void onKitChanged();
// plain format
void parseProject(RefreshOptions options);
- ProjectExplorer::Target *m_activeTarget = nullptr;
-
QPointer<QmlProjectItem> m_projectItem;
Utils::FilePath m_canonicalProjectDir;
};
+class QMLPROJECTMANAGER_EXPORT QmlProject : public ProjectExplorer::Project
+{
+ Q_OBJECT
+
+public:
+ explicit QmlProject(const Utils::FilePath &filename);
+
+ ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
+
+protected:
+ RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
+
+private:
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+
+};
+
} // namespace QmlProjectManager
-Q_DECLARE_OPERATORS_FOR_FLAGS(QmlProjectManager::QmlProject::RefreshOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmlProjectManager::QmlBuildSystem::RefreshOptions)
diff --git a/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp b/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
index 2d7a4daddb..cfa6c5e74e 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectnodes.cpp
@@ -24,28 +24,19 @@
****************************************************************************/
#include "qmlprojectnodes.h"
-#include "qmlproject.h"
-#include <coreplugin/idocument.h>
#include <coreplugin/fileiconprovider.h>
-#include <coreplugin/documentmanager.h>
-#include <coreplugin/editormanager/documentmodel.h>
-#include <coreplugin/editormanager/ieditor.h>
-#include <projectexplorer/projectexplorer.h>
-#include <texteditor/textdocument.h>
-#include <utils/algorithm.h>
-#include <utils/textfileformat.h>
-#include <QRegularExpression>
-#include <QTextCodec>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
using namespace ProjectExplorer;
namespace QmlProjectManager {
namespace Internal {
-QmlProjectNode::QmlProjectNode(QmlProject *project) : ProjectNode(project->projectDirectory()),
- m_project(project)
+QmlProjectNode::QmlProjectNode(Project *project)
+ : ProjectNode(project->projectDirectory())
{
setDisplayName(project->projectFilePath().toFileInfo().completeBaseName());
@@ -53,91 +44,5 @@ QmlProjectNode::QmlProjectNode(QmlProject *project) : ProjectNode(project->proje
setIcon(qmlProjectIcon);
}
-bool QmlBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
-{
- if (dynamic_cast<QmlProjectNode *>(context)) {
- if (action == AddNewFile || action == EraseFile)
- return true;
- QTC_ASSERT(node, return false);
-
- if (action == Rename && node->asFileNode()) {
- const FileNode *fileNode = node->asFileNode();
- QTC_ASSERT(fileNode, return false);
- return fileNode->fileType() != FileType::Project;
- }
-
- return false;
- }
-
- return BuildSystem::supportsAction(context, action, node);
-}
-
-QmlProject *QmlBuildSystem::project() const
-{
- return static_cast<QmlProject *>(BuildSystem::project());
-}
-
-bool QmlBuildSystem::addFiles(Node *context, const QStringList &filePaths, QStringList *notAdded)
-{
- if (dynamic_cast<QmlProjectNode *>(context))
- return project()->addFiles(filePaths);
-
- return BuildSystem::addFiles(context, filePaths, notAdded);
-}
-
-bool QmlBuildSystem::deleteFiles(Node *context, const QStringList &filePaths)
-{
- if (dynamic_cast<QmlProjectNode *>(context))
- return true;
-
- return BuildSystem::deleteFiles(context, filePaths);
-}
-
-bool QmlBuildSystem::renameFile(Node * context, const QString &filePath, const QString &newFilePath)
-{
- if (dynamic_cast<QmlProjectNode *>(context)) {
- if (filePath.endsWith(project()->mainFile())) {
- project()->setMainFile(newFilePath);
-
- // make sure to change it also in the qmlproject file
- const QString qmlProjectFilePath = project()->projectFilePath().toString();
- Core::FileChangeBlocker fileChangeBlocker(qmlProjectFilePath);
- const QList<Core::IEditor *> editors = Core::DocumentModel::editorsForFilePath(qmlProjectFilePath);
- TextEditor::TextDocument *document = nullptr;
- if (!editors.isEmpty()) {
- document = qobject_cast<TextEditor::TextDocument*>(editors.first()->document());
- if (document && document->isModified())
- if (!Core::DocumentManager::saveDocument(document))
- return false;
- }
-
- QString fileContent;
- QString error;
- Utils::TextFileFormat textFileFormat;
- const QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // qml files are defined to be utf-8
- if (Utils::TextFileFormat::readFile(qmlProjectFilePath, codec, &fileContent, &textFileFormat, &error)
- != Utils::TextFileFormat::ReadSuccess) {
- qWarning() << "Failed to read file" << qmlProjectFilePath << ":" << error;
- }
-
- // find the mainFile and do the file name with brackets in a capture group and mask the . with \.
- QString originalFileName = QFileInfo(filePath).fileName();
- originalFileName.replace(".", "\\.");
- const QRegularExpression expression(QString("mainFile:\\s*\"(%1)\"").arg(originalFileName));
- const QRegularExpressionMatch match = expression.match(fileContent);
-
- fileContent.replace(match.capturedStart(1), match.capturedLength(1), QFileInfo(newFilePath).fileName());
-
- if (!textFileFormat.writeFile(qmlProjectFilePath, fileContent, &error))
- qWarning() << "Failed to write file" << qmlProjectFilePath << ":" << error;
- project()->refresh(QmlProject::Everything);
- }
-
- return true;
- }
-
- return BuildSystem::renameFile(context, filePath, newFilePath);
-}
-
} // namespace Internal
} // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectnodes.h b/src/plugins/qmlprojectmanager/qmlprojectnodes.h
index 13c25a31a7..b400a21c69 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectnodes.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectnodes.h
@@ -28,18 +28,12 @@
#include <projectexplorer/projectnodes.h>
namespace QmlProjectManager {
-
-class QmlProject;
-
namespace Internal {
class QmlProjectNode : public ProjectExplorer::ProjectNode
{
public:
- QmlProjectNode(QmlProject *project);
-
-private:
- QmlProject *m_project;
+ explicit QmlProjectNode(ProjectExplorer::Project *project);
};
} // namespace Internal
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
index a10ac4fa57..9979249269 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp
@@ -73,7 +73,7 @@ static bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
class MainQmlFileAspect : public ProjectConfigurationAspect
{
public:
- explicit MainQmlFileAspect(QmlProject *project);
+ explicit MainQmlFileAspect(Target *target);
~MainQmlFileAspect() override { delete m_fileListCombo; }
enum MainScriptSource {
@@ -97,7 +97,12 @@ public:
bool isQmlFilePresent();
public:
- QmlProject *m_project;
+ QmlBuildSystem *qmlBuildSystem() const
+ {
+ return static_cast<QmlBuildSystem *>(m_target->buildSystem());
+ }
+
+ Target *m_target = nullptr;
QPointer<QComboBox> m_fileListCombo;
QStandardItemModel m_fileListModel;
QString m_scriptFile;
@@ -107,8 +112,8 @@ public:
QString m_mainScriptFilename;
};
-MainQmlFileAspect::MainQmlFileAspect(QmlProject *project)
- : m_project(project)
+MainQmlFileAspect::MainQmlFileAspect(Target *target)
+ : m_target(target)
, m_scriptFile(M_CURRENT_FILE)
{
connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
@@ -153,7 +158,7 @@ void MainQmlFileAspect::fromMap(const QVariantMap &map)
void MainQmlFileAspect::updateFileComboBox()
{
- QDir projectDir(m_project->projectDirectory().toString());
+ QDir projectDir(m_target->project()->projectDirectory().toString());
if (mainScriptSource() == FileInProjectFile) {
const QString mainScriptInFilePath = projectDir.relativeFilePath(mainScript());
@@ -170,7 +175,7 @@ void MainQmlFileAspect::updateFileComboBox()
m_fileListModel.appendRow(new QStandardItem(QLatin1String(CURRENT_FILE)));
QModelIndex currentIndex;
- QStringList sortedFiles = Utils::transform(m_project->files(Project::SourceFiles),
+ QStringList sortedFiles = Utils::transform(m_target->project()->files(Project::SourceFiles),
&Utils::FilePath::toString);
// make paths relative to project directory
@@ -207,7 +212,7 @@ void MainQmlFileAspect::updateFileComboBox()
MainQmlFileAspect::MainScriptSource MainQmlFileAspect::mainScriptSource() const
{
- if (!m_project->mainFile().isEmpty())
+ if (!qmlBuildSystem()->mainFile().isEmpty())
return FileInProjectFile;
if (!m_mainScriptFilename.isEmpty())
return FileInSettings;
@@ -234,7 +239,7 @@ void MainQmlFileAspect::setScriptSource(MainScriptSource source, const QString &
m_mainScriptFilename.clear();
} else { // FileInSettings
m_scriptFile = settingsPath;
- m_mainScriptFilename = m_project->projectDirectory().toString() + '/' + m_scriptFile;
+ m_mainScriptFilename = m_target->project()->projectDirectory().toString() + '/' + m_scriptFile;
}
emit changed();
@@ -246,12 +251,12 @@ void MainQmlFileAspect::setScriptSource(MainScriptSource source, const QString &
*/
QString MainQmlFileAspect::mainScript() const
{
- if (!m_project->mainFile().isEmpty()) {
- const QString pathInProject = m_project->mainFile();
+ if (!qmlBuildSystem()->mainFile().isEmpty()) {
+ const QString pathInProject = qmlBuildSystem()->mainFile();
if (QFileInfo(pathInProject).isAbsolute())
return pathInProject;
else
- return QDir(m_project->canonicalProjectDir().toString()).absoluteFilePath(pathInProject);
+ return QDir(qmlBuildSystem()->canonicalProjectDir().toString()).absoluteFilePath(pathInProject);
}
if (!m_mainScriptFilename.isEmpty())
@@ -279,9 +284,9 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id)
{
auto envAspect = addAspect<EnvironmentAspect>();
- auto envModifier = [target](Environment env) {
- if (auto project = qobject_cast<const QmlProject *>(target->project()))
- env.modify(project->environment());
+ auto envModifier = [this](Environment env) {
+ if (auto bs = dynamic_cast<const QmlBuildSystem *>(activeBuildSystem()))
+ env.modify(bs->environment());
return env;
};
@@ -311,9 +316,7 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id)
CommandLine::Raw);
});
- auto qmlProject = qobject_cast<QmlProject *>(target->project());
- QTC_ASSERT(qmlProject, return);
- m_mainQmlFileAspect = addAspect<MainQmlFileAspect>(qmlProject);
+ m_mainQmlFileAspect = addAspect<MainQmlFileAspect>(target);
connect(m_mainQmlFileAspect, &MainQmlFileAspect::changed,
this, &QmlProjectRunConfiguration::updateEnabledState);
@@ -329,7 +332,8 @@ Runnable QmlProjectRunConfiguration::runnable() const
Runnable r;
r.setCommandLine(commandLine());
r.environment = aspect<EnvironmentAspect>()->environment();
- r.workingDirectory = static_cast<QmlProject *>(project())->targetDirectory(target()).toString();
+ const QmlBuildSystem *bs = static_cast<QmlBuildSystem *>(activeBuildSystem());
+ r.workingDirectory = bs->targetDirectory().toString();
return r;
}
@@ -377,38 +381,35 @@ QString QmlProjectRunConfiguration::commandLineArguments() const
{
// arguments in .user file
QString args = aspect<ArgumentsAspect>()->arguments(macroExpander());
- const Target *currentTarget = target();
- const IDevice::ConstPtr device = DeviceKitAspect::device(currentTarget->kit());
+ const IDevice::ConstPtr device = DeviceKitAspect::device(target()->kit());
const Utils::OsType osType = device ? device->osType() : Utils::HostOsInfo::hostOs();
// arguments from .qmlproject file
- const QmlProject *project = static_cast<QmlProject *>(currentTarget->project());
+ const QmlBuildSystem *bs = static_cast<QmlBuildSystem *>(target()->buildSystem());
foreach (const QString &importPath,
- QmlProject::makeAbsolute(project->targetDirectory(currentTarget), project->customImportPaths())) {
+ QmlBuildSystem::makeAbsolute(bs->targetDirectory(), bs->customImportPaths())) {
Utils::QtcProcess::addArg(&args, QLatin1String("-I"), osType);
Utils::QtcProcess::addArg(&args, importPath, osType);
}
- for (const QString &fileSelector : project->customFileSelectors()) {
+ for (const QString &fileSelector : bs->customFileSelectors()) {
Utils::QtcProcess::addArg(&args, QLatin1String("-S"), osType);
Utils::QtcProcess::addArg(&args, fileSelector, osType);
}
- const QString main = project->targetFile(Utils::FilePath::fromString(mainScript()),
- currentTarget).toString();
+ const QString main = bs->targetFile(FilePath::fromString(mainScript())).toString();
if (!main.isEmpty())
Utils::QtcProcess::addArg(&args, main, osType);
return args;
}
-void QmlProjectRunConfiguration::updateEnabledState()
+bool QmlProjectRunConfiguration::isEnabled() const
{
- bool enabled = false;
if (m_mainQmlFileAspect->isQmlFilePresent() && !commandLine().executable().isEmpty()) {
- Project *p = target()->project();
- enabled = !p->isParsing() && p->hasParsingData();
+ BuildSystem *bs = activeBuildSystem();
+ return !bs->isParsing() && bs->hasParsingData();
}
- setEnabled(enabled);
+ return false;
}
bool MainQmlFileAspect::isQmlFilePresent()
@@ -430,7 +431,7 @@ bool MainQmlFileAspect::isQmlFilePresent()
|| mainScriptMimeType.matchesName(QLatin1String(QmlJSTools::Constants::QMLPROJECT_MIMETYPE))) {
// find a qml file with lowercase filename. This is slow, but only done
// in initialization/other border cases.
- const auto files = m_project->files(Project::SourceFiles);
+ const auto files = m_target->project()->files(Project::SourceFiles);
for (const Utils::FilePath &filename : files) {
const QFileInfo fi = filename.toFileInfo();
diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
index 8a18fd0ef9..9d810671f1 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
+++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h
@@ -44,7 +44,7 @@ public:
private:
ProjectExplorer::Runnable runnable() const final;
QString disabledReason() const final;
- void updateEnabledState() final;
+ bool isEnabled() const final;
QString mainScript() const;
QString theExecutable() const;