forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/qds/dev'
Change-Id: I91d9877ef6637d21e1106d6d363275295e6b55a3
This commit is contained in:
@@ -10,7 +10,8 @@ namespace QmlProjectManager::Converters {
|
||||
using PropsPair = QPair<QString, QStringList>;
|
||||
struct FileProps
|
||||
{
|
||||
const PropsPair image{"image", QStringList{"*.jpeg", "*.jpg", "*.png", "*.svg", "*.hdr", ".ktx"}};
|
||||
const PropsPair image{"image",
|
||||
QStringList{"*.jpeg", "*.jpg", "*.png", "*.svg", "*.hdr", ".ktx"}};
|
||||
const PropsPair qml{"qml", QStringList{"*.qml"}};
|
||||
const PropsPair qmlDir{"qmldir", QStringList{"qmldir"}};
|
||||
const PropsPair javaScr{"javaScript", QStringList{"*.js", "*.ts"}};
|
||||
@@ -43,7 +44,7 @@ QString jsonToQmlProject(const QJsonObject &rootObject)
|
||||
auto appendBreak = [&ts]() { ts << Qt::endl; };
|
||||
|
||||
auto appendComment = [&ts, &indentationLevel](const QString &comment) {
|
||||
ts << QString(" ").repeated(indentationLevel * 4) << "\\\\ " << comment << Qt::endl;
|
||||
ts << QString(" ").repeated(indentationLevel * 4) << "// " << comment << Qt::endl;
|
||||
};
|
||||
|
||||
auto appendItem =
|
||||
@@ -153,10 +154,14 @@ QString jsonToQmlProject(const QJsonObject &rootObject)
|
||||
}
|
||||
|
||||
{ // append ShaderTool object
|
||||
startObject("ShaderTool");
|
||||
appendString("args", shaderConfig["args"].toVariant().toStringList().join(" "));
|
||||
appendArray("files", shaderConfig["files"].toVariant().toStringList());
|
||||
endObject();
|
||||
if (!shaderConfig["args"].toVariant().toStringList().isEmpty()) {
|
||||
startObject("ShaderTool");
|
||||
appendString("args",
|
||||
shaderConfig["args"].toVariant().toStringList().join(" ").replace(
|
||||
"\"", "\\\""));
|
||||
appendArray("files", shaderConfig["files"].toVariant().toStringList());
|
||||
endObject();
|
||||
}
|
||||
}
|
||||
|
||||
{ // append files objects
|
||||
@@ -190,7 +195,7 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
|
||||
}
|
||||
|
||||
if (rootNode->name() != QLatin1String("Project")) {
|
||||
qCritical() << "Cannot find root 'Proejct' item in the project file: " << projectFile;
|
||||
qCritical() << "Cannot find root 'Project' item in the project file: " << projectFile;
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -216,18 +221,22 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
|
||||
// convert the the non-object props
|
||||
for (const QString &propName : rootNode->propertyNames()) {
|
||||
QJsonObject *currentObj = &rootObject;
|
||||
QString objKey = propName;
|
||||
QString objKey = QString(propName).remove("QDS.", Qt::CaseInsensitive);
|
||||
QJsonValue value = rootNode->property(propName).value.toJsonValue();
|
||||
|
||||
if (propName.contains("language", Qt::CaseInsensitive)) {
|
||||
if (propName.startsWith("mcu.", Qt::CaseInsensitive)) {
|
||||
currentObj = &mcuObject;
|
||||
objKey = QString(propName).remove("MCU.");
|
||||
} else if (propName.contains("language", Qt::CaseInsensitive)) {
|
||||
currentObj = &languageObject;
|
||||
if (propName.toLower() == "multilanguagesupport") // fixing the camelcase
|
||||
if (propName.contains("multilanguagesupport", Qt::CaseInsensitive))
|
||||
// fixing the camelcase
|
||||
objKey = "multiLanguageSupport";
|
||||
} else if (propName.contains("version", Qt::CaseInsensitive)) {
|
||||
currentObj = &versionObject;
|
||||
if (propName.toLower() == "qdsversion")
|
||||
if (propName.contains("qdsversion", Qt::CaseInsensitive))
|
||||
objKey = "designStudio";
|
||||
else if (propName.toLower() == "quickversion")
|
||||
else if (propName.contains("quickversion", Qt::CaseInsensitive))
|
||||
objKey = "qtQuick";
|
||||
} else if (propName.contains("widgetapp", Qt::CaseInsensitive)
|
||||
|| propName.contains("fileselector", Qt::CaseInsensitive)
|
||||
@@ -265,7 +274,8 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
|
||||
FileProps fileProps;
|
||||
const QString childNodeName = childNode->name().toLower();
|
||||
const QmlJS::SimpleReaderNode::Property childNodeFilter = childNode->property("filter");
|
||||
const QmlJS::SimpleReaderNode::Property childNodeDirectory = childNode->property("directory");
|
||||
const QmlJS::SimpleReaderNode::Property childNodeDirectory = childNode->property(
|
||||
"directory");
|
||||
const QmlJS::SimpleReaderNode::Property childNodeFiles = childNode->property("files");
|
||||
const QString childNodeFilterValue = childNodeFilter.value.toString();
|
||||
|
||||
@@ -304,12 +314,12 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
|
||||
|
||||
// populate & update filters
|
||||
if (filters.isEmpty()) {
|
||||
filters = QJsonArray::fromStringList(propsPair.second); // populate the filters with the predefined ones
|
||||
filters = QJsonArray::fromStringList(
|
||||
propsPair.second); // populate the filters with the predefined ones
|
||||
}
|
||||
|
||||
if (childNodeFilter.isValid()) { // append filters from qmlproject (merge)
|
||||
const QStringList filtersFromProjectFile = childNodeFilterValue.split(
|
||||
";");
|
||||
const QStringList filtersFromProjectFile = childNodeFilterValue.split(";");
|
||||
for (const QString &filter : filtersFromProjectFile) {
|
||||
if (!filters.contains(QJsonValue(filter))) {
|
||||
filters.append(QJsonValue(filter));
|
||||
@@ -337,7 +347,8 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
|
||||
targetObject.insert("files", files);
|
||||
fileGroupsObject.insert(propsPair.first, targetObject);
|
||||
} else if (childNode->name().contains("shadertool", Qt::CaseInsensitive)) {
|
||||
QStringList quotedArgs = childNode->property("args").value.toString().split('\"', Qt::SkipEmptyParts);
|
||||
QStringList quotedArgs
|
||||
= childNode->property("args").value.toString().split('\"', Qt::SkipEmptyParts);
|
||||
QStringList args;
|
||||
for (int i = 0; i < quotedArgs.size(); ++i) {
|
||||
// Each odd arg in this list is a single quoted argument, which we should
|
||||
@@ -351,7 +362,8 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
|
||||
shaderToolObject.insert("args", QJsonArray::fromStringList(args));
|
||||
shaderToolObject.insert("files", childNode->property("files").value.toJsonValue());
|
||||
} else {
|
||||
rootObject.insert(toCamelCase(childNode->name()), nodeToJsonObject(childNode));
|
||||
rootObject.insert(toCamelCase(childNode->name().remove("qds.", Qt::CaseInsensitive)),
|
||||
nodeToJsonObject(childNode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +373,8 @@ QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
|
||||
rootObject.insert("runConfig", runConfigObject);
|
||||
rootObject.insert("deployment", deploymentObject);
|
||||
rootObject.insert("mcuConfig", mcuObject);
|
||||
rootObject.insert("shaderTool", shaderToolObject);
|
||||
if (!shaderToolObject.isEmpty())
|
||||
rootObject.insert("shaderTool", shaderToolObject);
|
||||
rootObject.insert("fileVersion", 1);
|
||||
return rootObject;
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
|
||||
#include <utils/environment.h>
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
#include <QSharedPointer>
|
||||
#include <QJsonObject>
|
||||
#include <QStringList>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
@@ -30,7 +30,6 @@ public:
|
||||
|
||||
bool isQt4McuProject() const;
|
||||
|
||||
|
||||
QString versionQt() const;
|
||||
void setVersionQt(const QString &version);
|
||||
|
||||
@@ -102,7 +101,7 @@ private:
|
||||
|
||||
// runtime variables
|
||||
Utils::FilePath m_projectFile; // design studio project file
|
||||
QJsonObject m_project; // root project object
|
||||
QJsonObject m_project; // root project object
|
||||
const bool m_skipRewrite;
|
||||
|
||||
// initializing functions
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "../qmlprojectconstants.h"
|
||||
#include "../qmlprojectmanagertr.h"
|
||||
#include "../qmlproject.h"
|
||||
|
||||
#include <QtCore5Compat/qtextcodec.h>
|
||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||
@@ -82,11 +83,11 @@ QmlBuildSystem::QmlBuildSystem(Target *target)
|
||||
updateDeploymentData();
|
||||
registerMenuButtons();
|
||||
|
||||
connect(target->project(), &Project::activeTargetChanged, [this](Target *target) {
|
||||
connect(target->project(), &Project::activeTargetChanged, this, [this](Target *target) {
|
||||
refresh(RefreshOptions::NoFileRefresh);
|
||||
updateMcuBuildStep(target, qtForMCUs());
|
||||
});
|
||||
connect(target->project(), &Project::projectFileIsDirty, [this]() {
|
||||
connect(target->project(), &Project::projectFileIsDirty, this, [this]() {
|
||||
refresh(RefreshOptions::Project);
|
||||
updateMcuBuildStep(project()->activeTarget(), qtForMCUs());
|
||||
});
|
||||
@@ -155,6 +156,11 @@ bool QmlBuildSystem::updateProjectFile()
|
||||
return true;
|
||||
}
|
||||
|
||||
QmlProject *QmlBuildSystem::qmlProject() const
|
||||
{
|
||||
return qobject_cast<QmlProject *>(project());
|
||||
}
|
||||
|
||||
void QmlBuildSystem::triggerParsing()
|
||||
{
|
||||
refresh(RefreshOptions::Project);
|
||||
@@ -284,14 +290,14 @@ bool QmlBuildSystem::setFileSettingInProjectFile(const QString &setting,
|
||||
const QString relativePath = mainFilePath.relativeChildPath(projectDir).path();
|
||||
|
||||
if (fileContent.indexOf(settingQmlCode) < 0) {
|
||||
QString addedText = QString("\n %1 \"%2\"\n").arg(settingQmlCode).arg(relativePath);
|
||||
QString addedText = QString("\n %1 \"%2\"\n").arg(settingQmlCode, 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));
|
||||
QString("%1\\s*\"(%2)\"").arg(settingQmlCode, originalFileName));
|
||||
|
||||
const QRegularExpressionMatch match = expression.match(fileContent);
|
||||
|
||||
@@ -315,14 +321,85 @@ void QmlBuildSystem::setBlockFilesUpdate(bool newBlockFilesUpdate)
|
||||
m_blockFilesUpdate = newBlockFilesUpdate;
|
||||
}
|
||||
|
||||
Utils::FilePath QmlBuildSystem::getStartupQmlFileWithFallback() const
|
||||
{
|
||||
const auto currentProject = project();
|
||||
|
||||
if (!currentProject)
|
||||
return {};
|
||||
|
||||
if (!target())
|
||||
return {};
|
||||
|
||||
const auto getFirstFittingFile = [](const Utils::FilePaths &files) -> Utils::FilePath {
|
||||
for (const auto &file : files) {
|
||||
if (file.exists())
|
||||
return file;
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
const QStringView uiqmlstr = u"ui.qml";
|
||||
const QStringView qmlstr = u"qml";
|
||||
|
||||
//we will check mainUiFile and mainFile twice:
|
||||
//first priority if it's ui.qml file, second if it's just a qml file
|
||||
const Utils::FilePath mainUiFile = mainUiFilePath();
|
||||
if (mainUiFile.exists() && mainUiFile.completeSuffix() == uiqmlstr)
|
||||
return mainUiFile;
|
||||
|
||||
const Utils::FilePath mainQmlFile = mainFilePath();
|
||||
if (mainQmlFile.exists() && mainQmlFile.completeSuffix() == uiqmlstr)
|
||||
return mainQmlFile;
|
||||
|
||||
const Utils::FilePaths uiFiles = currentProject->files([&](const ProjectExplorer::Node *node) {
|
||||
return node->filePath().completeSuffix() == uiqmlstr;
|
||||
});
|
||||
if (!uiFiles.isEmpty()) {
|
||||
if (const auto file = getFirstFittingFile(uiFiles); !file.isEmpty())
|
||||
return file;
|
||||
}
|
||||
|
||||
//check the suffix of mainUiFiles again, since there are no ui.qml files:
|
||||
if (mainUiFile.exists() && mainUiFile.completeSuffix() == qmlstr)
|
||||
return mainUiFile;
|
||||
|
||||
if (mainQmlFile.exists() && mainQmlFile.completeSuffix() == qmlstr)
|
||||
return mainQmlFile;
|
||||
|
||||
//maybe it's also worth priotizing qml files containing common words like "Screen"?
|
||||
const Utils::FilePaths qmlFiles = currentProject->files([&](const ProjectExplorer::Node *node) {
|
||||
return node->filePath().completeSuffix() == qmlstr;
|
||||
});
|
||||
if (!qmlFiles.isEmpty()) {
|
||||
if (const auto file = getFirstFittingFile(qmlFiles); !file.isEmpty())
|
||||
return file;
|
||||
}
|
||||
|
||||
//if no source files exist in the project, lets try to open the .qmlproject file itself
|
||||
const Utils::FilePath projectFile = projectFilePath();
|
||||
if (projectFile.exists())
|
||||
return projectFile;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Utils::FilePath QmlBuildSystem::mainFilePath() const
|
||||
{
|
||||
return projectDirectory().pathAppended(mainFile());
|
||||
const QString fileName = mainFile();
|
||||
if (fileName.isEmpty() || fileName.isNull()) {
|
||||
return {};
|
||||
}
|
||||
return projectDirectory().pathAppended(fileName);
|
||||
}
|
||||
|
||||
Utils::FilePath QmlBuildSystem::mainUiFilePath() const
|
||||
{
|
||||
return projectDirectory().pathAppended(mainUiFile());
|
||||
const QString fileName = mainUiFile();
|
||||
if (fileName.isEmpty() || fileName.isNull()) {
|
||||
return {};
|
||||
}
|
||||
return projectDirectory().pathAppended(fileName);
|
||||
}
|
||||
|
||||
bool QmlBuildSystem::setMainFileInProjectFile(const Utils::FilePath &newMainFilePath)
|
||||
|
||||
@@ -94,6 +94,8 @@ public:
|
||||
bool blockFilesUpdate() const;
|
||||
void setBlockFilesUpdate(bool newBlockFilesUpdate);
|
||||
|
||||
Utils::FilePath getStartupQmlFileWithFallback() const;
|
||||
|
||||
signals:
|
||||
void projectChanged();
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#include <qmlprojectmanager/qmlproject.h>
|
||||
#include <qmlprojectmanager/qmlprojectmanagerconstants.h>
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <extensionsystem/pluginspec.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <QAction>
|
||||
@@ -37,6 +41,27 @@ namespace QmlProjectManager {
|
||||
|
||||
namespace GenerateCmake {
|
||||
|
||||
static bool isQmlDesigner(const ExtensionSystem::PluginSpec *spec)
|
||||
{
|
||||
if (!spec)
|
||||
return false;
|
||||
|
||||
return spec->name().contains("QmlDesigner");
|
||||
}
|
||||
|
||||
static void trackUsage(const QString &id)
|
||||
{
|
||||
const auto plugins = ExtensionSystem::PluginManager::plugins();
|
||||
const auto it = std::find_if(plugins.begin(), plugins.end(), &isQmlDesigner);
|
||||
if (it != plugins.end()) {
|
||||
QObject *qmlDesignerPlugin = (*it)->plugin();
|
||||
QMetaObject::invokeMethod(qmlDesignerPlugin,
|
||||
"usageStatisticsNotifier",
|
||||
Qt::DirectConnection,
|
||||
Q_ARG(QString, id));
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const GeneratableFile &left, const GeneratableFile &right)
|
||||
{
|
||||
return (left.filePath == right.filePath && left.content == right.content);
|
||||
@@ -100,6 +125,7 @@ void generateMenuEntry(QObject *parent)
|
||||
|
||||
void onGenerateCmakeLists()
|
||||
{
|
||||
trackUsage("generateCMakeProjectDialogOpened");
|
||||
FilePath rootDir = ProjectExplorer::ProjectManager::startupProject()->projectDirectory();
|
||||
|
||||
int projectDirErrors = isProjectCorrectlyFormed(rootDir);
|
||||
@@ -122,6 +148,8 @@ void onGenerateCmakeLists()
|
||||
cmakeGen.filterFileQueue(confirmedFiles);
|
||||
cmakeGen.execute();
|
||||
}
|
||||
|
||||
trackUsage("generateCMakeProjectExecuted");
|
||||
}
|
||||
|
||||
bool isErrorFatal(int error)
|
||||
|
||||
@@ -13,7 +13,7 @@ int main(int argc, char *argv[])
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
const QUrl url(u"qrc:Main/main.qml"_qs);
|
||||
const QUrl url(u"qrc:/qt/qml/Main/main.qml"_qs);
|
||||
QObject::connect(
|
||||
&engine, &QQmlApplicationEngine::objectCreated, &app,
|
||||
[url](QObject *obj, const QUrl &objUrl) {
|
||||
|
||||
@@ -7,5 +7,6 @@ qt_add_library(%2 STATIC)
|
||||
qt6_add_qml_module(%2
|
||||
URI "%3"
|
||||
VERSION 1.0
|
||||
RESOURCE_PREFIX "/qt/qml"
|
||||
%4
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
qt6_add_qml_module(%1
|
||||
URI "Main"
|
||||
VERSION 1.0
|
||||
RESOURCE_PREFIX "/qt/qml"
|
||||
NO_PLUGIN
|
||||
QML_FILES main.qml
|
||||
)
|
||||
|
||||
@@ -67,40 +67,24 @@ void QmlProject::parsingFinished(const Target *target, bool success)
|
||||
// trigger only once
|
||||
disconnect(this, &QmlProject::anyParsingFinished, this, &QmlProject::parsingFinished);
|
||||
|
||||
// FIXME: what to do in this case?
|
||||
if (!target || !success || !activeTarget())
|
||||
return;
|
||||
|
||||
auto targetActive = activeTarget();
|
||||
auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
|
||||
targetActive->buildSystem());
|
||||
|
||||
const Utils::FilePath mainUiFile = qmlBuildSystem->mainUiFilePath();
|
||||
|
||||
if (mainUiFile.completeSuffix() == "ui.qml" && mainUiFile.exists()) {
|
||||
QTimer::singleShot(1000, [mainUiFile]() {
|
||||
Core::EditorManager::openEditor(mainUiFile, Utils::Id());
|
||||
});
|
||||
const auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
|
||||
activeTarget()->buildSystem());
|
||||
if (!qmlBuildSystem)
|
||||
return;
|
||||
}
|
||||
|
||||
Utils::FilePaths uiFiles = collectUiQmlFilesForFolder(
|
||||
projectDirectory().pathAppended("content"));
|
||||
if (uiFiles.isEmpty()) {
|
||||
uiFiles = collectUiQmlFilesForFolder(projectDirectory());
|
||||
if (uiFiles.isEmpty())
|
||||
return;
|
||||
}
|
||||
|
||||
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());
|
||||
const auto openFile = [&](const Utils::FilePath file) {
|
||||
//why is this timer needed here?
|
||||
QTimer::singleShot(1000, this, [file] {
|
||||
Core::EditorManager::openEditor(file, Utils::Id());
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const Utils::FilePath fileToOpen = qmlBuildSystem->getStartupQmlFileWithFallback();
|
||||
if (!fileToOpen.isEmpty() && fileToOpen.exists() && !fileToOpen.isDir())
|
||||
openFile(fileToOpen);
|
||||
}
|
||||
|
||||
Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
||||
@@ -175,6 +159,14 @@ Utils::FilePaths QmlProject::collectUiQmlFilesForFolder(const Utils::FilePath &f
|
||||
return uiFiles;
|
||||
}
|
||||
|
||||
Utils::FilePaths QmlProject::collectQmlFiles() const
|
||||
{
|
||||
const Utils::FilePaths qmlFiles = files([&](const Node *node) {
|
||||
return node->filePath().completeSuffix() == "qml";
|
||||
});
|
||||
return qmlFiles;
|
||||
}
|
||||
|
||||
Tasks QmlProject::projectIssues(const Kit *k) const
|
||||
{
|
||||
Tasks result = Project::projectIssues(k);
|
||||
|
||||
Reference in New Issue
Block a user