aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp4
-rw-r--r--src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h4
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp195
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.h10
-rw-r--r--src/plugins/qmlprojectmanager/qmlprojectplugin.cpp114
5 files changed, 276 insertions, 51 deletions
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
index ce54df3d8d..f385cc7466 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp
@@ -91,6 +91,10 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi
if (mainFileProperty.isValid())
projectItem->setMainFile(mainFileProperty.value.toString());
+ const auto mainUiFileProperty = rootNode->property(QLatin1String("mainUiFile"));
+ if (mainUiFileProperty.isValid())
+ projectItem->setMainUiFile(mainUiFileProperty.value.toString());
+
const auto importPathsProperty = rootNode->property(QLatin1String("importPaths"));
if (importPathsProperty.isValid()) {
QStringList list = importPathsProperty.value.toStringList();
diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
index 02916555a7..d437db6114 100644
--- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
+++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h
@@ -81,6 +81,9 @@ public:
QString mainFile() const { return m_mainFile; }
void setMainFile(const QString &mainFilePath) { m_mainFile = mainFilePath; }
+ QString mainUiFile() const { return m_mainUiFile; }
+ void setMainUiFile(const QString &mainUiFilePath) { m_mainUiFile = mainUiFilePath; }
+
bool widgetApp() const { return m_widgetApp; }
void setWidgetApp(bool widgetApp) { m_widgetApp = widgetApp; }
@@ -107,6 +110,7 @@ protected:
QStringList m_supportedLanguages;
QString m_primaryLanguage;
QString m_mainFile;
+ QString m_mainUiFile;
Utils::EnvironmentItems m_environment;
QVector<QmlProjectContentItem *> m_content; // content property
bool m_forceFreeType = false;
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 37fb78f033..dc58282e0d 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -135,21 +135,38 @@ QmlProject::QmlProject(const Utils::FilePath &fileName)
disconnect(m_openFileConnection);
if (target && success) {
- Utils::FilePaths uiFiles = getUiQmlFilesForFolder(projectDirectory()
- + "/content");
- if (uiFiles.isEmpty())
- uiFiles = getUiQmlFilesForFolder(projectDirectory());
-
- if (!uiFiles.isEmpty()) {
- Utils::FilePath currentFile;
- if (auto cd = Core::EditorManager::currentDocument())
- currentFile = cd->filePath();
-
- if (currentFile.isEmpty() || !isKnownFile(currentFile))
- QTimer::singleShot(1000, [uiFiles]() {
- Core::EditorManager::openEditor(uiFiles.first(),
+
+ auto target = activeTarget();
+ if (!target)
+ return;
+
+ auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
+ target->buildSystem());
+
+ const Utils::FilePath mainUiFile = qmlBuildSystem->mainUiFilePath();
+
+ if (mainUiFile.completeSuffix() == "qi.qml" && mainUiFile.exists()) {
+ QTimer::singleShot(1000, [mainUiFile]() {
+ Core::EditorManager::openEditor(mainUiFile,
Utils::Id());
- });
+ });
+ } else {
+ Utils::FilePaths uiFiles = getUiQmlFilesForFolder(projectDirectory()
+ + "/content");
+ if (uiFiles.isEmpty())
+ uiFiles = getUiQmlFilesForFolder(projectDirectory());
+
+ if (!uiFiles.isEmpty()) {
+ Utils::FilePath currentFile;
+ if (auto cd = Core::EditorManager::currentDocument())
+ currentFile = cd->filePath();
+
+ if (currentFile.isEmpty() || !isKnownFile(currentFile))
+ QTimer::singleShot(1000, [uiFiles]() {
+ Core::EditorManager::openEditor(uiFiles.first(),
+ Utils::Id());
+ });
+ }
}
}
});
@@ -253,6 +270,58 @@ void QmlBuildSystem::parseProject(RefreshOptions options)
}
}
+bool QmlBuildSystem::setFileSettingInProjectFile(const QString &setting, const Utils::FilePath &mainFilePath, const QString &oldFile)
+{
+ // make sure to change it also in the qmlproject file
+ const Utils::FilePath qmlProjectFilePath = project()->projectFilePath();
+ 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;
+ }
+
+ const QString settingQmlCode = setting + ":";
+
+ QDir projectDir = project()->projectFilePath().toDir();
+ projectDir.cdUp();
+ const QString relativePath = projectDir.relativeFilePath(mainFilePath.toString());
+
+ if (fileContent.indexOf(settingQmlCode) < 0) {
+ QString addedText = QString("\n %1 \"%2\"\n").arg(settingQmlCode).arg(relativePath);
+ auto index = fileContent.lastIndexOf("}");
+ fileContent.insert(index, addedText);
+ } else {
+ QString originalFileName = oldFile;
+ originalFileName.replace(".", "\\.");
+ const QRegularExpression expression(QString("%1\\s*\"(%2)\"").arg(settingQmlCode).arg(originalFileName));
+
+ const QRegularExpressionMatch match = expression.match(fileContent);
+
+ fileContent.replace(match.capturedStart(1),
+ match.capturedLength(1),
+ relativePath);
+ }
+
+ if (!textFileFormat.writeFile(qmlProjectFilePath, fileContent, &error))
+ qWarning() << "Failed to write file" << qmlProjectFilePath << ":" << error;
+
+ refresh(Everything);
+ return true;
+}
+
void QmlBuildSystem::refresh(RefreshOptions options)
{
ParseGuard guard = guardParsingRun();
@@ -283,11 +352,68 @@ QString QmlBuildSystem::mainFile() const
return QString();
}
+QString QmlBuildSystem::mainUiFile() const
+{
+ if (m_projectItem)
+ return m_projectItem->mainUiFile();
+ return QString();
+}
+
Utils::FilePath QmlBuildSystem::mainFilePath() const
{
return projectDirectory().pathAppended(mainFile());
}
+Utils::FilePath QmlBuildSystem::mainUiFilePath() const
+{
+ return projectDirectory().pathAppended(mainUiFile());
+}
+
+bool QmlBuildSystem::setMainFileInProjectFile(const Utils::FilePath &newMainFilePath)
+{
+
+ return setFileSettingInProjectFile("mainFile", newMainFilePath, mainFile());
+}
+
+bool QmlBuildSystem::setMainUiFileInProjectFile(const Utils::FilePath &newMainUiFilePath)
+{
+ return setMainUiFileInMainFile(newMainUiFilePath)
+ && setFileSettingInProjectFile("mainUiFile", newMainUiFilePath, mainUiFile());
+}
+
+bool QmlBuildSystem::setMainUiFileInMainFile(const Utils::FilePath &newMainUiFilePath)
+{
+ Core::FileChangeBlocker fileChangeBlocker(mainFilePath());
+ const QList<Core::IEditor *> editors = Core::DocumentModel::editorsForFilePath(mainFilePath());
+ 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(mainFilePath(), codec, &fileContent, &textFileFormat, &error)
+ != Utils::TextFileFormat::ReadSuccess) {
+ qWarning() << "Failed to read file" << mainFilePath() << ":" << error;
+ }
+
+ const QString currentMain = QString("%1 {").arg(mainUiFilePath().baseName());
+ const QString newMain = QString("%1 {").arg(newMainUiFilePath.baseName());
+
+ if (fileContent.contains(currentMain))
+ fileContent.replace(currentMain, newMain);
+
+ if (!textFileFormat.writeFile(mainFilePath(), fileContent, &error))
+ qWarning() << "Failed to write file" << mainFilePath() << ":" << error;
+
+ return true;
+}
+
bool QmlBuildSystem::qtForMCUs() const
{
if (m_projectItem)
@@ -663,43 +789,10 @@ bool QmlBuildSystem::deleteFiles(Node *context, const FilePaths &filePaths)
bool QmlBuildSystem::renameFile(Node * context, const FilePath &oldFilePath, const FilePath &newFilePath)
{
if (dynamic_cast<QmlProjectNode *>(context)) {
- if (oldFilePath.endsWith(mainFile())) {
- setMainFile(newFilePath.toString());
-
- // make sure to change it also in the qmlproject file
- const Utils::FilePath qmlProjectFilePath = project()->projectFilePath();
- 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 = oldFilePath.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), newFilePath.fileName());
-
- if (!textFileFormat.writeFile(qmlProjectFilePath, fileContent, &error))
- qWarning() << "Failed to write file" << qmlProjectFilePath << ":" << error;
-
- refresh(Everything);
- }
+ if (oldFilePath.endsWith(mainFile()))
+ return setMainFileInProjectFile(newFilePath);
+ if (oldFilePath.endsWith(mainUiFile()))
+ return setMainUiFileInProjectFile(newFilePath);
return true;
}
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index 78a30187f6..a5ce067be6 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -77,7 +77,13 @@ public:
Utils::FilePath canonicalProjectDir() const;
QString mainFile() const;
+ QString mainUiFile() const;
Utils::FilePath mainFilePath() const;
+ Utils::FilePath mainUiFilePath() const;
+
+ bool setMainFileInProjectFile(const Utils::FilePath &newMainFilePath);
+ bool setMainUiFileInProjectFile(const Utils::FilePath &newMainUiFilePath);
+ bool setMainUiFileInMainFile(const Utils::FilePath &newMainUiFilePath);
bool qtForMCUs() const;
bool qt6Project() const;
@@ -116,6 +122,10 @@ public:
void parseProject(RefreshOptions options);
private:
+ bool setFileSettingInProjectFile(const QString &setting,
+ const Utils::FilePath &mainFilePath,
+ const QString &oldFile);
+
std::unique_ptr<QmlProjectItem> m_projectItem;
Utils::FilePath m_canonicalProjectDir;
bool m_blockFilesUpdate = false;
diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
index bc7b6f3bde..ff58349dc0 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
@@ -28,14 +28,20 @@
#include "qmlprojectconstants.h"
#include "qmlprojectrunconfiguration.h"
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
+#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
+#include <projectexplorer/projectnodes.h>
+#include <projectexplorer/projecttree.h>
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/session.h>
+#include <projectexplorer/target.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
@@ -47,6 +53,7 @@
#include <utils/infobar.h>
#include <utils/qtcprocess.h>
+#include <QAction>
#include <QMessageBox>
#include <QPushButton>
#include <QTimer>
@@ -197,6 +204,23 @@ void QmlProjectPlugin::openInQDSWithProject(const Utils::FilePath &filePath)
}
}
+static QmlBuildSystem *qmlBuildSystemforFileNode(const FileNode *fileNode)
+{
+ if (!fileNode)
+ return nullptr;
+
+ if (QmlProject *qmlProject = qobject_cast<QmlProject*>(fileNode->getProject())) {
+ auto target = qmlProject->activeTarget();
+ if (!target)
+ return nullptr;
+
+ return qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
+
+ }
+
+ return nullptr;
+}
+
bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
{
Q_UNUSED(errorMessage)
@@ -206,6 +230,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
if (!qmlDesignerEnabled()) {
connect(Core::EditorManager::instance(),
&Core::EditorManager::currentEditorChanged,
+ this,
[this](Core::IEditor *editor) {
QmlJS::ModelManagerInterface *modelManager
= QmlJS::ModelManagerInterface::instance();
@@ -258,6 +283,95 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
ProjectManager::registerProjectType<QmlProject>(QmlJSTools::Constants::QMLPROJECT_MIMETYPE);
Core::FileIconProvider::registerIconOverlayForSuffix(":/qmlproject/images/qmlproject.png",
"qmlproject");
+
+ if (QmlProject::isQtDesignStudio()) {
+ Core::ActionContainer *menu = Core::ActionManager::actionContainer(
+ ProjectExplorer::Constants::M_FILECONTEXT);
+ QAction *mainfileAction = new QAction(tr("Set as main .qml file"), this);
+ mainfileAction->setEnabled(false);
+
+ connect(mainfileAction, &QAction::triggered, this, []() {
+ const Node *currentNode = ProjectTree::currentNode();
+ if (!currentNode || !currentNode->asFileNode()
+ || currentNode->asFileNode()->fileType() != FileType::QML)
+ return;
+
+ const Utils::FilePath file = currentNode->filePath();
+
+ QmlBuildSystem *buildSystem = qmlBuildSystemforFileNode(currentNode->asFileNode());
+ if (buildSystem)
+ buildSystem->setMainFileInProjectFile(file);
+ });
+
+ menu->addAction(Core::ActionManager::registerAction(
+ mainfileAction,
+ "QmlProject.setMainFile",
+ Core::Context(ProjectExplorer::Constants::C_PROJECT_TREE)),
+ ProjectExplorer::Constants::G_FILE_OTHER);
+ mainfileAction->setVisible(false);
+ connect(ProjectTree::instance(),
+ &ProjectTree::currentNodeChanged,
+ mainfileAction,
+ [mainfileAction](Node *node) {
+ const FileNode *fileNode = node ? node->asFileNode() : nullptr;
+
+ const bool isVisible = fileNode && fileNode->fileType() == FileType::QML
+ && fileNode->filePath().completeSuffix() == "qml";
+
+ mainfileAction->setVisible(isVisible);
+
+ if (!isVisible)
+ return;
+
+ QmlBuildSystem *buildSystem = qmlBuildSystemforFileNode(fileNode);
+
+ if (buildSystem)
+ mainfileAction->setEnabled(buildSystem->mainFilePath()
+ != fileNode->filePath());
+ });
+
+ QAction *mainUifileAction = new QAction(tr("Set as main .ui.qml file"), this);
+ mainUifileAction->setEnabled(false);
+
+ connect(mainUifileAction, &QAction::triggered, this, []() {
+ const Node *currentNode = ProjectTree::currentNode();
+ if (!currentNode || !currentNode->asFileNode()
+ || currentNode->asFileNode()->fileType() != FileType::QML)
+ return;
+
+ const Utils::FilePath file = currentNode->filePath();
+
+ QmlBuildSystem *buildSystem = qmlBuildSystemforFileNode(currentNode->asFileNode());
+ if (buildSystem)
+ buildSystem->setMainUiFileInProjectFile(file);
+ });
+
+ menu->addAction(Core::ActionManager::registerAction(
+ mainUifileAction,
+ "QmlProject.setMainUIFile",
+ Core::Context(ProjectExplorer::Constants::C_PROJECT_TREE)),
+ ProjectExplorer::Constants::G_FILE_OTHER);
+ mainUifileAction->setVisible(false);
+ connect(ProjectTree::instance(),
+ &ProjectTree::currentNodeChanged,
+ mainUifileAction,
+ [mainUifileAction](Node *node) {
+ const FileNode *fileNode = node ? node->asFileNode() : nullptr;
+ const bool isVisible = fileNode && fileNode->fileType() == FileType::QML
+ && fileNode->filePath().completeSuffix() == "ui.qml";
+
+ mainUifileAction->setVisible(isVisible);
+
+ if (!isVisible)
+ return;
+
+ QmlBuildSystem *buildSystem = qmlBuildSystemforFileNode(fileNode);
+ if (buildSystem)
+ mainUifileAction->setEnabled(buildSystem->mainUiFilePath()
+ != fileNode->filePath());
+ });
+ }
+
return true;
} // namespace Internal