QmlProject: Refactor QmlProjectManager

- feature: JSON based project manager plugin
- feature: functionality to write QmlProject file
- tests: tests for QmlProjectItem

Task-number: QDS-8810
Change-Id: I8989e54577e9cd883bd76346e22774cc7f7ed93f
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Burak Hancerli
2023-02-13 00:49:09 +01:00
parent 4871e472c4
commit 66d72433a6
230 changed files with 4464 additions and 1387 deletions

View File

@@ -1,23 +1,13 @@
add_qtc_plugin(QmlProjectManager
CONDITION TARGET Qt::QuickWidgets
CONDITION TARGET Qt5::QuickWidgets
PROPERTIES COMPILE_WARNING_AS_ERROR ON
PLUGIN_CLASS QmlProjectPlugin
DEPENDS QmlJS Qt::QuickWidgets
DEPENDS QmlJS Qt5::QuickWidgets Utils
PLUGIN_DEPENDS Core ProjectExplorer QtSupport QmlDesignerBase
SOURCES
fileformat/filefilteritems.cpp fileformat/filefilteritems.h
fileformat/qmlprojectfileformat.cpp fileformat/qmlprojectfileformat.h
fileformat/qmlprojectitem.cpp fileformat/qmlprojectitem.h
cmakegen/checkablefiletreeitem.cpp cmakegen/checkablefiletreeitem.h
cmakegen/cmakegeneratordialog.cpp cmakegen/cmakegeneratordialog.h
cmakegen/cmakegeneratordialogtreemodel.cpp cmakegen/cmakegeneratordialogtreemodel.h
cmakegen/cmakeprojectconverter.cpp cmakegen/cmakeprojectconverter.h
cmakegen/cmakeprojectconverterdialog.cpp cmakegen/cmakeprojectconverterdialog.h
cmakegen/generatecmakelists.cpp cmakegen/generatecmakelists.h
cmakegen/generatecmakelistsconstants.h
cmakegen/boilerplate.qrc
qmlprojectgen/qmlprojectgenerator.cpp qmlprojectgen/qmlprojectgenerator.h
qmlprojectgen/templates.qrc
projectfilecontenttools.cpp projectfilecontenttools.h
qdslandingpage.cpp qdslandingpage.h
qdslandingpagetheme.cpp qdslandingpagetheme.h
@@ -29,8 +19,33 @@ add_qtc_plugin(QmlProjectManager
qmlprojectmanager_global.h
qmlprojectmanagertr.h
qmlprojectmanagerconstants.h
qmlprojectnodes.cpp qmlprojectnodes.h
qmlprojectplugin.cpp qmlprojectplugin.h
qmlprojectrunconfiguration.cpp qmlprojectrunconfiguration.h
buildsystem/qmlbuildsystem.cpp buildsystem/qmlbuildsystem.h
"${PROJECT_SOURCE_DIR}/src/share/3rdparty/studiofonts/studiofonts.qrc"
)
extend_qtc_plugin(QmlProjectManager
PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/buildsystem
SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/buildsystem
SOURCES
projectitem/filefilteritems.cpp projectitem/filefilteritems.h
projectitem/qmlprojectitem.cpp projectitem/qmlprojectitem.h
projectitem/converters.h projectitem/converters.cpp
projectnode/qmlprojectnodes.cpp projectnode/qmlprojectnodes.h
)
extend_qtc_plugin(QmlProjectManager
PUBLIC_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/cmakegen
SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/cmakegen
SOURCES
checkablefiletreeitem.cpp checkablefiletreeitem.h
cmakegeneratordialog.cpp cmakegeneratordialog.h
cmakegeneratordialogtreemodel.cpp cmakegeneratordialogtreemodel.h
cmakeprojectconverter.cpp cmakeprojectconverter.h
cmakeprojectconverterdialog.cpp cmakeprojectconverterdialog.h
generatecmakelists.cpp generatecmakelists.h
generatecmakelistsconstants.h
boilerplate.qrc
)

View File

@@ -0,0 +1,362 @@
// 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
#include "converters.h"
#include <QJsonArray>
namespace QmlProjectManager::Converters {
using PropsPair = QPair<QString, QStringList>;
struct FileProps
{
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"}};
const PropsPair video{"video", QStringList{"*.mp4"}};
const PropsPair sound{"sound", QStringList{"*.mp3", "*.wav"}};
const PropsPair font{"font", QStringList{"*.ttf", "*.otf"}};
const PropsPair config{"config", QStringList{"*.conf"}};
const PropsPair styling{"styling", QStringList{"*.css"}};
const PropsPair mesh{"meshes", QStringList{"*.mesh"}};
const PropsPair
shader{"shader",
QStringList{"*.glsl", "*.glslv", "*.glslf", "*.vsh", "*.fsh", "*.vert", "*.frag"}};
};
QString jsonToQmlProject(const QJsonObject &rootObject)
{
QString qmlProjectString;
QTextStream ts{&qmlProjectString};
QJsonObject runConfig = rootObject["runConfig"].toObject();
QJsonObject languageConfig = rootObject["language"].toObject();
QJsonObject shaderConfig = rootObject["shaderTool"].toObject();
QJsonObject versionConfig = rootObject["versions"].toObject();
QJsonObject environmentConfig = rootObject["environment"].toObject();
QJsonObject deploymentConfig = rootObject["deployment"].toObject();
QJsonObject filesConfig = rootObject["fileGroups"].toObject();
int indentationLevel = 0;
auto appendBreak = [&ts]() { ts << Qt::endl; };
auto appendComment = [&ts, &indentationLevel](const QString &comment) {
ts << QString(" ").repeated(indentationLevel * 4) << "\\\\ " << comment << Qt::endl;
};
auto appendItem =
[&ts, &indentationLevel](const QString &key, const QString &value, const bool isEnclosed) {
ts << QString(" ").repeated(indentationLevel * 4) << key << ": "
<< (isEnclosed ? "\"" : "") << value << (isEnclosed ? "\"" : "") << Qt::endl;
};
auto appendString = [&appendItem](const QString &key, const QString &val) {
appendItem(key, val, true);
};
auto appendBool = [&appendItem](const QString &key, const bool &val) {
appendItem(key, QString::fromStdString(val ? "true" : "false"), false);
};
auto appendArray = [&appendItem](const QString &key, const QStringList &vals) {
QString finalString;
foreach (const QString &value, vals) {
finalString.append("\"").append(value).append("\"").append(",");
}
finalString.remove(finalString.length() - 1, 1);
finalString.prepend("[ ").append(" ]");
appendItem(key, finalString, false);
};
auto startObject = [&ts, &indentationLevel](const QString &objectName) {
ts << Qt::endl
<< QString(" ").repeated(indentationLevel * 4) << objectName << " {" << Qt::endl;
indentationLevel++;
};
auto endObject = [&ts, &indentationLevel]() {
indentationLevel--;
ts << QString(" ").repeated(indentationLevel * 4) << "}" << Qt::endl;
};
auto appendDirectories =
[&startObject, &endObject, &appendString, &filesConfig](const QString &jsonKey,
const QString &qmlKey) {
QJsonValue dirsObj = filesConfig[jsonKey].toObject()["directories"];
QStringList dirs = dirsObj.toVariant().toStringList();
foreach (const QString &directory, dirs) {
startObject(qmlKey);
appendString("directory", directory);
endObject();
}
};
auto appendFiles = [&startObject,
&endObject,
&appendString,
&appendArray,
&filesConfig](const QString &jsonKey, const QString &qmlKey) {
QJsonValue dirsObj = filesConfig[jsonKey].toObject()["directories"];
QJsonValue filesObj = filesConfig[jsonKey].toObject()["files"];
QJsonValue filtersObj = filesConfig[jsonKey].toObject()["filters"];
foreach (const QString &directory, dirsObj.toVariant().toStringList()) {
startObject(qmlKey);
appendString("directory", directory);
appendString("filters", filtersObj.toVariant().toStringList().join(";"));
if (!filesObj.toArray().isEmpty()) {
QStringList fileList;
foreach (const QJsonValue &file, filesObj.toArray()) {
fileList.append(file.toObject()["name"].toString());
}
appendArray("files", fileList);
}
endObject();
}
};
// start creating the file content
appendComment("prop: json-converted");
appendComment("prop: auto-generated");
ts << Qt::endl << "import QmlProject" << Qt::endl;
{
startObject("Project");
{ // append non-object props
appendString("mainFile", runConfig["mainFile"].toString());
appendString("mainUiFile", runConfig["mainUiFile"].toString());
appendString("targetDirectory", deploymentConfig["targetDirectory"].toString());
appendBool("widgetApp", runConfig["widgetApp"].toBool());
appendArray("importPaths", rootObject["importPaths"].toVariant().toStringList());
appendBreak();
appendString("qdsVersion", versionConfig["designStudio"].toString());
appendString("quickVersion", versionConfig["qtQuick"].toString());
appendBool("qt6Project", versionConfig["qtQuick"].toString().startsWith("6."));
appendBool("qtForMCUs", rootObject["mcuConfig"].toObject().isEmpty());
appendBreak();
appendBool("multilanguageSupport", languageConfig["multiLanguageSupport"].toBool());
appendString("primaryLanguage", languageConfig["primaryLanguage"].toString());
appendArray("supportedLanguages",
languageConfig["supportedLanguages"].toVariant().toStringList());
}
{ // append Environment object
startObject("Environment");
foreach (const QString &key, environmentConfig.keys()) {
appendItem(key, environmentConfig[key].toString(), true);
}
endObject();
}
{ // append ShaderTool object
startObject("ShaderTool");
appendString("args", shaderConfig["args"].toVariant().toStringList().join(" "));
appendArray("files", shaderConfig["files"].toVariant().toStringList());
endObject();
}
{ // append files objects
appendDirectories("qml", "QmlFiles");
appendDirectories("javaScript", "JavaScriptFiles");
appendDirectories("image", "ImageFiles");
appendFiles("config", "Files");
appendFiles("font", "Files");
appendFiles("meshes", "Files");
appendFiles("qmldir", "Files");
appendFiles("shader", "Files");
appendFiles("sound", "Files");
appendFiles("video", "Files");
}
endObject(); // Closing 'Project'
}
return qmlProjectString;
}
QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile)
{
QmlJS::SimpleReader simpleQmlJSReader;
const QmlJS::SimpleReaderNode::Ptr rootNode = simpleQmlJSReader.readFile(projectFile.toString());
if (!simpleQmlJSReader.errors().isEmpty() || !rootNode->isValid()) {
qCritical() << "Unable to parse:" << projectFile;
qCritical() << simpleQmlJSReader.errors();
return {};
}
if (rootNode->name() != QLatin1String("Project")) {
qCritical() << "Cannot find root 'Proejct' item in the project file: " << projectFile;
return {};
}
auto nodeToJsonObject = [](const QmlJS::SimpleReaderNode::Ptr &node) {
QJsonObject tObj;
foreach (const QString &childPropName, node->propertyNames()) {
tObj.insert(childPropName, node->property(childPropName).value.toJsonValue());
}
return tObj;
};
auto toCamelCase = [](const QString &s) { return QString(s).replace(0, 1, s[0].toLower()); };
QJsonObject rootObject; // root object
QJsonObject fileGroupsObject;
QJsonObject languageObject;
QJsonObject versionObject;
QJsonObject runConfigObject;
QJsonObject deploymentObject;
QJsonObject mcuObject;
QJsonObject shaderToolObject;
// convert the the non-object props
for (const QString &propName : rootNode->propertyNames()) {
QJsonObject *currentObj = &rootObject;
QString objKey = propName;
if (propName.contains("language", Qt::CaseInsensitive)) {
currentObj = &languageObject;
if (propName.toLower() == "multilanguagesupport") // fixing the camelcase
objKey = "multiLanguageSupport";
} else if (propName.contains("version", Qt::CaseInsensitive)) {
currentObj = &versionObject;
if (propName.toLower() == "qdsversion")
objKey = "designStudio";
else if (propName.toLower() == "quickversion")
objKey = "qtQuick";
} else if (propName.contains("widgetapp", Qt::CaseInsensitive)
|| propName.contains("fileselector", Qt::CaseInsensitive)
|| propName.contains("mainfile", Qt::CaseInsensitive)
|| propName.contains("mainuifile", Qt::CaseInsensitive)
|| propName.contains("forcefreetype", Qt::CaseInsensitive)) {
currentObj = &runConfigObject;
} else if (propName.contains("targetdirectory", Qt::CaseInsensitive)) {
currentObj = &deploymentObject;
} else if (propName.contains("qtformcus", Qt::CaseInsensitive)) {
currentObj = &mcuObject;
objKey = "mcuEnabled";
} else if (propName.contains("qt6project", Qt::CaseInsensitive)) {
// we are skipping these ones in the new json format
continue;
}
currentObj->insert(objKey, rootNode->property(propName).value.toJsonValue());
}
// add missing non-object props if any
if (!runConfigObject.contains("fileSelectors")) {
runConfigObject.insert("fileSelectors", QJsonArray{});
}
// convert the the object props
for (const QmlJS::SimpleReaderNode::Ptr &childNode : rootNode->children()) {
if (childNode->name().contains("files", Qt::CaseInsensitive)) {
PropsPair propsPair;
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 childNodeFiles = childNode->property("files");
const QString childNodeFilterValue = childNodeFilter.value.toString();
if (childNodeName == "qmlfiles" || childNodeFilterValue.contains("*.qml")) {
propsPair = fileProps.qml;
} else if (childNodeName == "javascriptfiles") {
propsPair = fileProps.javaScr;
} else if (childNodeName == "imagefiles") {
propsPair = fileProps.image;
} else {
if (childNodeFilter.isValid()) {
if (childNodeFilterValue.contains(".conf"))
propsPair = fileProps.config;
else if (childNodeFilterValue.contains(".ttf"))
propsPair = fileProps.font;
else if (childNodeFilterValue.contains("qmldir"))
propsPair = fileProps.qmlDir;
else if (childNodeFilterValue.contains(".wav"))
propsPair = fileProps.sound;
else if (childNodeFilterValue.contains(".mp4"))
propsPair = fileProps.video;
else if (childNodeFilterValue.contains(".mesh"))
propsPair = fileProps.mesh;
else if (childNodeFilterValue.contains(".glsl"))
propsPair = fileProps.shader;
else if (childNodeFilterValue.contains(".css"))
propsPair = fileProps.styling;
}
}
// get all objects we'll work on
QJsonObject targetObject = fileGroupsObject[propsPair.first].toObject();
QJsonArray directories = targetObject["directories"].toArray();
QJsonArray filters = targetObject["filters"].toArray();
QJsonArray files = targetObject["files"].toArray();
// populate & update filters
if (filters.isEmpty()) {
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(
";");
for (const QString &filter : filtersFromProjectFile) {
if (!filters.contains(QJsonValue(filter))) {
filters.append(QJsonValue(filter));
}
}
}
// populate & update directories
if (childNodeDirectory.isValid()) {
directories.append(childNodeDirectory.value.toJsonValue());
}
if (directories.isEmpty())
directories.append(".");
// populate & update files
if (childNodeFiles.isValid()) {
foreach (const QJsonValue &file, childNodeFiles.value.toJsonArray()) {
files.append(QJsonObject{{"name", file.toString()}});
}
}
// put everything back into the root object
targetObject.insert("directories", directories);
targetObject.insert("filters", filters);
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('\"');
QStringList args;
for (int i = 0; i < quotedArgs.size(); ++i) {
// Each odd arg in this list is a single quoted argument, which we should
// not be split further
if (i % 2 == 0)
args.append(quotedArgs[i].trimmed().split(' '));
else
args.append(quotedArgs[i].prepend("\"").append("\""));
}
shaderToolObject.insert("args", QJsonArray::fromStringList(args));
shaderToolObject.insert("files", childNode->property("files").value.toJsonValue());
} else {
rootObject.insert(toCamelCase(childNode->name()), nodeToJsonObject(childNode));
}
}
rootObject.insert("fileGroups", fileGroupsObject);
rootObject.insert("language", languageObject);
rootObject.insert("versions", versionObject);
rootObject.insert("runConfig", runConfigObject);
rootObject.insert("deployment", deploymentObject);
rootObject.insert("mcuConfig", mcuObject);
rootObject.insert("shaderTool", shaderToolObject);
rootObject.insert("fileVersion", 1);
return rootObject;
}
} // namespace QmlProjectManager::Converters

View File

@@ -0,0 +1,19 @@
// 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
#pragma once
#include <QJsonObject>
#include <QString>
#include <utils/environment.h>
#include <qmljs/qmljssimplereader.h>
#include <QJsonArray>
namespace QmlProjectManager::Converters {
QString jsonToQmlProject(const QJsonObject &rootObject);
QJsonObject qmlProjectTojson(const Utils::FilePath &projectFile);
} // namespace QmlProjectManager::Converters

View File

@@ -15,36 +15,46 @@
namespace QmlProjectManager {
FileFilterBaseItem::FileFilterBaseItem()
FileFilterItem::FileFilterItem(){
initTimer();
}
FileFilterItem::FileFilterItem(const QString &directory, const QStringList &filters)
{
setDirectory(directory);
setFilters(filters);
initTimer();
}
void FileFilterItem::initTimer(){
m_updateFileListTimer.setSingleShot(true);
m_updateFileListTimer.setInterval(50);
connect(&m_updateFileListTimer, &QTimer::timeout, this, &FileFilterBaseItem::updateFileListNow);
connect(&m_updateFileListTimer, &QTimer::timeout, this, &FileFilterItem::updateFileListNow);
}
Utils::FileSystemWatcher *FileFilterBaseItem::dirWatcher()
Utils::FileSystemWatcher *FileFilterItem::dirWatcher()
{
if (!m_dirWatcher) {
m_dirWatcher = new Utils::FileSystemWatcher(1, this); // Separate id, might exceed OS limits.
m_dirWatcher->setObjectName(QLatin1String("FileFilterBaseItemWatcher"));
connect(m_dirWatcher, &Utils::FileSystemWatcher::directoryChanged,
this, &FileFilterBaseItem::updateFileList);
this, &FileFilterItem::updateFileList);
}
return m_dirWatcher;
}
QStringList FileFilterBaseItem::watchedDirectories() const
QStringList FileFilterItem::watchedDirectories() const
{
return m_dirWatcher ? m_dirWatcher->directories() : QStringList();
}
QString FileFilterBaseItem::directory() const
QString FileFilterItem::directory() const
{
return m_rootDir;
}
void FileFilterBaseItem::setDirectory(const QString &dirPath)
void FileFilterItem::setDirectory(const QString &dirPath)
{
if (m_rootDir == dirPath)
return;
@@ -54,7 +64,7 @@ void FileFilterBaseItem::setDirectory(const QString &dirPath)
updateFileList();
}
void FileFilterBaseItem::setDefaultDirectory(const QString &dirPath)
void FileFilterItem::setDefaultDirectory(const QString &dirPath)
{
if (m_defaultDir == dirPath)
return;
@@ -63,12 +73,12 @@ void FileFilterBaseItem::setDefaultDirectory(const QString &dirPath)
updateFileListNow();
}
QString FileFilterBaseItem::filter() const
QStringList FileFilterItem::filters() const
{
return m_filter;
}
void FileFilterBaseItem::setFilter(const QString &filter)
void FileFilterItem::setFilters(const QStringList &filter)
{
if (filter == m_filter)
return;
@@ -77,7 +87,7 @@ void FileFilterBaseItem::setFilter(const QString &filter)
m_regExpList.clear();
m_fileSuffixes.clear();
for (const QString &pattern : filter.split(QLatin1Char(';'))) {
for (const QString &pattern : filter) {
if (pattern.isEmpty())
continue;
// decide if it's a canonical pattern like *.x
@@ -96,7 +106,7 @@ void FileFilterBaseItem::setFilter(const QString &filter)
updateFileList();
}
bool FileFilterBaseItem::recursive() const
bool FileFilterItem::recursive() const
{
bool recursive;
if (m_recurse == Recurse) {
@@ -112,7 +122,7 @@ bool FileFilterBaseItem::recursive() const
return recursive;
}
void FileFilterBaseItem::setRecursive(bool recurse)
void FileFilterItem::setRecursive(bool recurse)
{
bool oldRecursive = recursive();
@@ -125,18 +135,18 @@ void FileFilterBaseItem::setRecursive(bool recurse)
updateFileList();
}
QStringList FileFilterBaseItem::pathsProperty() const
QStringList FileFilterItem::pathsProperty() const
{
return m_explicitFiles;
}
void FileFilterBaseItem::setPathsProperty(const QStringList &path)
void FileFilterItem::setPathsProperty(const QStringList &path)
{
m_explicitFiles = path;
updateFileList();
}
QStringList FileFilterBaseItem::files() const
QStringList FileFilterItem::files() const
{
return Utils::toList(m_files);
}
@@ -146,7 +156,7 @@ QStringList FileFilterBaseItem::files() const
@param filePath: absolute file path
*/
bool FileFilterBaseItem::matchesFile(const QString &filePath) const
bool FileFilterItem::matchesFile(const QString &filePath) const
{
for (const QString &explicitFile : m_explicitFiles) {
if (absolutePath(explicitFile) == filePath)
@@ -167,14 +177,14 @@ bool FileFilterBaseItem::matchesFile(const QString &filePath) const
return false;
}
QString FileFilterBaseItem::absolutePath(const QString &path) const
QString FileFilterItem::absolutePath(const QString &path) const
{
if (QFileInfo(path).isAbsolute())
return path;
return QDir(absoluteDir()).absoluteFilePath(path);
}
QString FileFilterBaseItem::absoluteDir() const
QString FileFilterItem::absoluteDir() const
{
QString absoluteDir;
if (QFileInfo(m_rootDir).isAbsolute())
@@ -185,13 +195,15 @@ QString FileFilterBaseItem::absoluteDir() const
return QDir::cleanPath(absoluteDir);
}
void FileFilterBaseItem::updateFileList()
void FileFilterItem::updateFileList()
{
#ifndef TESTS_ENABLED_QMLPROJECTITEM
if (!m_updateFileListTimer.isActive())
m_updateFileListTimer.start();
#endif
}
void FileFilterBaseItem::updateFileListNow()
void FileFilterItem::updateFileListNow()
{
if (m_updateFileListTimer.isActive())
m_updateFileListTimer.stop();
@@ -233,7 +245,7 @@ void FileFilterBaseItem::updateFileListNow()
dirWatcher()->addDirectories(Utils::toList(watchDirs), Utils::FileSystemWatcher::WatchAllChanges);
}
bool FileFilterBaseItem::fileMatches(const QString &fileName) const
bool FileFilterItem::fileMatches(const QString &fileName) const
{
for (const QString &suffix : std::as_const(m_fileSuffixes)) {
if (fileName.endsWith(suffix, Qt::CaseInsensitive))
@@ -248,7 +260,7 @@ bool FileFilterBaseItem::fileMatches(const QString &fileName) const
return false;
}
QSet<QString> FileFilterBaseItem::filesInSubTree(const QDir &rootDir, const QDir &dir, QSet<QString> *parsedDirs)
QSet<QString> FileFilterItem::filesInSubTree(const QDir &rootDir, const QDir &dir, QSet<QString> *parsedDirs)
{
QSet<QString> fileSet;
@@ -270,22 +282,5 @@ QSet<QString> FileFilterBaseItem::filesInSubTree(const QDir &rootDir, const QDir
return fileSet;
}
ImageFileFilterItem::ImageFileFilterItem()
{
QString filter;
// supported image formats according to
QList<QByteArray> extensions = QImageReader::supportedImageFormats();
extensions.append("hdr");
extensions.append("ktx");
for (const QByteArray &extension : std::as_const(extensions))
filter.append(QString::fromLatin1("*.%1;").arg(QString::fromLatin1(extension)));
setFilter(filter);
}
FileFilterItem::FileFilterItem(const QString &fileFilter)
{
setFilter(fileFilter);
}
} // namespace QmlProjectManager

View File

@@ -7,6 +7,7 @@
#include <QRegularExpression>
#include <QSet>
#include <QTimer>
#include <QJsonArray>
QT_FORWARD_DECLARE_CLASS(QDir)
@@ -14,16 +15,10 @@ namespace Utils { class FileSystemWatcher; }
namespace QmlProjectManager {
class QmlProjectContentItem : public QObject
{
// base class for all elements that should be direct children of Project element
Q_OBJECT
using FileFilterItemPtr = std::unique_ptr<class FileFilterItem>;
using FileFilterItems = std::vector<FileFilterItemPtr>;
public:
QmlProjectContentItem() {}
};
class FileFilterBaseItem : public QmlProjectContentItem {
class FileFilterItem : public QObject {
Q_OBJECT
Q_PROPERTY(QString directory READ directory WRITE setDirectory NOTIFY directoryChanged)
@@ -33,15 +28,16 @@ class FileFilterBaseItem : public QmlProjectContentItem {
Q_PROPERTY(QStringList files READ files NOTIFY filesChanged DESIGNABLE false)
public:
FileFilterBaseItem();
FileFilterItem();
FileFilterItem(const QString &directory, const QStringList &filters);
QString directory() const;
void setDirectory(const QString &directoryPath);
void setDefaultDirectory(const QString &directoryPath);
QString filter() const;
void setFilter(const QString &filter);
QStringList filters() const;
void setFilters(const QStringList &filter);
bool recursive() const;
void setRecursive(bool recursive);
@@ -73,7 +69,7 @@ private:
QString m_rootDir;
QString m_defaultDir;
QString m_filter;
QStringList m_filter;
// simple "*.png" patterns are stored in m_fileSuffixes, otherwise store in m_regExpList
QList<QString> m_fileSuffixes;
QList<QRegularExpression> m_regExpList;
@@ -93,16 +89,7 @@ private:
QTimer m_updateFileListTimer;
friend class ProjectItem;
};
class FileFilterItem : public FileFilterBaseItem {
public:
FileFilterItem(const QString &fileFilter);
};
class ImageFileFilterItem : public FileFilterBaseItem {
public:
ImageFileFilterItem();
void initTimer();
};
} // namespace QmlProjectManager

View File

@@ -0,0 +1,381 @@
// 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
#include "qmlprojectitem.h"
#include <QDir>
#include <QJsonDocument>
#include "converters.h"
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <qmljs/qmljssimplereader.h>
#include <QJsonArray>
namespace QmlProjectManager {
//#define REWRITE_PROJECT_FILE_IN_JSON_FORMAT
QmlProjectItem::QmlProjectItem(const Utils::FilePath &filePath)
: m_projectFile(filePath)
{
if (initProjectObject())
setupFileFilters();
}
bool QmlProjectItem::initProjectObject()
{
auto contents = m_projectFile.fileContents();
if (!contents) {
qWarning() << "Cannot open project file. Path:" << m_projectFile.fileName();
return false;
}
QString fileContent{QString::fromUtf8(contents.value())};
QJsonObject rootObj;
QJsonParseError parseError;
if (fileContent.contains("import qmlproject", Qt::CaseInsensitive)) {
rootObj = Converters::qmlProjectTojson(m_projectFile);
#ifdef REWRITE_PROJECT_FILE_IN_JSON_FORMAT
m_projectFile.writeFileContents(QJsonDocument(rootObj).toJson());
#endif
} else {
rootObj
= QJsonDocument::fromJson(m_projectFile.fileContents()->data(), &parseError).object();
}
if (rootObj.isEmpty()) {
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "Cannot parse the json formatted project file. Error:"
<< parseError.errorString();
} else {
qWarning() << "Cannot convert QmlProject to Json.";
}
return false;
}
m_project = rootObj;
return true;
}
void QmlProjectItem::setupFileFilters()
{
auto setupFileFilterItem = [this](const QJsonObject &fileGroup) {
for (const QString &directory : fileGroup["directories"].toVariant().toStringList()) {
std::unique_ptr<FileFilterItem> fileFilterItem{new FileFilterItem};
QStringList filesArr;
for (const QJsonValue &file : fileGroup["files"].toArray()) {
filesArr.append(file["name"].toString());
}
fileFilterItem->setDirectory(directory);
fileFilterItem->setFilters(fileGroup["filters"].toVariant().toStringList());
fileFilterItem->setRecursive(fileGroup["recursive"].toBool(true));
fileFilterItem->setPathsProperty(fileGroup["directories"].toVariant().toStringList());
fileFilterItem->setPathsProperty(filesArr);
fileFilterItem->setDefaultDirectory(m_projectFile.parentDir().toString());
#ifndef TESTS_ENABLED_QMLPROJECTITEM
connect(fileFilterItem.get(),
&FileFilterItem::filesChanged,
this,
&QmlProjectItem::qmlFilesChanged);
#endif
m_content.push_back(std::move(fileFilterItem));
};
};
QJsonObject fileGroups = m_project["fileGroups"].toObject();
for (const QString &groupName : fileGroups.keys()) {
setupFileFilterItem(fileGroups[groupName].toObject());
}
}
Utils::FilePath QmlProjectItem::sourceDirectory() const
{
return m_projectFile.parentDir();
}
QString QmlProjectItem::targetDirectory() const
{
return m_project["deployment"].toObject()["targetDirectory"].toString();
}
bool QmlProjectItem::isQt4McuProject() const
{
return m_project["mcuConfig"].toObject()["mcuEnabled"].toBool();
}
Utils::EnvironmentItems QmlProjectItem::environment() const
{
Utils::EnvironmentItems envItems;
QJsonObject envVariables = m_project["environment"].toObject();
foreach (const QString &variableName, envVariables.keys()) {
envItems.append(Utils::EnvironmentItem(variableName, envVariables[variableName].toString()));
}
return envItems;
}
void QmlProjectItem::addToEnviroment(const QString &key, const QString &value)
{
QJsonObject envVariables = m_project["environment"].toObject();
envVariables.insert(key, value);
insertAndUpdateProjectFile("environment", envVariables);
}
QJsonObject QmlProjectItem::project() const
{
return m_project;
}
bool QmlProjectItem::isQt6Project() const
{
return m_project["versions"].toObject()["qtQuick"].toString().startsWith("6.");
}
QStringList QmlProjectItem::importPaths() const
{
return m_project["importPaths"].toVariant().toStringList();
}
void QmlProjectItem::setImportPaths(const QStringList &importPaths)
{
insertAndUpdateProjectFile("importPaths", QJsonArray::fromStringList(importPaths));
}
void QmlProjectItem::addImportPath(const QString &importPath)
{
QJsonArray importPaths = m_project["importPaths"].toArray();
if (importPaths.contains(importPath))
return;
importPaths.append(importPath);
insertAndUpdateProjectFile("importPaths", importPaths);
}
QStringList QmlProjectItem::fileSelectors() const
{
return m_project["runConfig"].toObject()["fileSelectors"].toVariant().toStringList();
}
void QmlProjectItem::setFileSelectors(const QStringList &selectors)
{
QJsonObject targetObj = m_project["runConfig"].toObject();
targetObj["fileSelectors"] = QJsonArray::fromStringList(selectors);
insertAndUpdateProjectFile("runConfig", targetObj);
}
void QmlProjectItem::addFileSelector(const QString &selector)
{
QJsonObject targetObj = m_project["runConfig"].toObject();
QJsonArray fileSelectors = targetObj["fileSelectors"].toArray();
if (fileSelectors.contains(selector))
return;
fileSelectors.append(selector);
targetObj["fileSelectors"] = fileSelectors;
insertAndUpdateProjectFile("runConfig", targetObj);
}
bool QmlProjectItem::multilanguageSupport() const
{
return m_project["language"].toObject()["multiLanguageSupport"].toBool();
}
void QmlProjectItem::setMultilanguageSupport(const bool &isEnabled)
{
QJsonObject targetObj = m_project["language"].toObject();
targetObj["multiLanguageSupport"] = isEnabled;
insertAndUpdateProjectFile("language", targetObj);
}
QStringList QmlProjectItem::supportedLanguages() const
{
return m_project["language"].toObject()["supportedLanguages"].toVariant().toStringList();
}
void QmlProjectItem::setSupportedLanguages(const QStringList &languages)
{
QJsonObject targetObj = m_project["language"].toObject();
targetObj["supportedLanguages"] = QJsonArray::fromStringList(languages);
insertAndUpdateProjectFile("language", targetObj);
}
void QmlProjectItem::addSupportedLanguage(const QString &language)
{
QJsonObject targetObj = m_project["language"].toObject();
QJsonArray suppLangs = targetObj["supportedLanguages"].toArray();
if (suppLangs.contains(language))
return;
suppLangs.append(language);
targetObj["supportedLanguages"] = suppLangs;
insertAndUpdateProjectFile("language", targetObj);
}
QString QmlProjectItem::primaryLanguage() const
{
return m_project["language"].toObject()["primaryLanguage"].toString();
}
void QmlProjectItem::setPrimaryLanguage(const QString &language)
{
QJsonObject targetObj = m_project["language"].toObject();
targetObj["primaryLanguage"] = language;
insertAndUpdateProjectFile("language", targetObj);
}
Utils::FilePaths QmlProjectItem::files() const
{
QSet<QString> filesSet;
for (const auto &fileFilter : m_content) {
const QStringList fileList = fileFilter->files();
for (const QString &file : fileList) {
filesSet.insert(file);
}
}
Utils::FilePaths files;
for (const auto &fileName : filesSet) {
files.append(Utils::FilePath::fromString(fileName));
}
return files;
}
/**
Check whether the project would include a file path
- regardless whether the file already exists or not.
@param filePath: absolute file path to check
*/
bool QmlProjectItem::matchesFile(const QString &filePath) const
{
return Utils::contains(m_content, [&filePath](const auto &fileFilter) {
return fileFilter->matchesFile(filePath);
});
}
bool QmlProjectItem::forceFreeType() const
{
return m_project["runConfig"].toObject()["forceFreeType"].toBool();
}
void QmlProjectItem::setForceFreeType(const bool &isForced)
{
QJsonObject runConfig = m_project["runConfig"].toObject();
runConfig["forceFreeType"] = isForced;
insertAndUpdateProjectFile("runConfig", runConfig);
}
void QmlProjectItem::setMainFile(const QString &mainFile)
{
QJsonObject runConfig = m_project["runConfig"].toObject();
runConfig["mainFile"] = mainFile;
insertAndUpdateProjectFile("runConfig", runConfig);
}
QString QmlProjectItem::mainFile() const
{
return m_project["runConfig"].toObject()["mainFile"].toString();
}
Utils::FilePath QmlProjectItem::mainFilePath() const
{
return m_projectFile;
}
void QmlProjectItem::setMainUiFile(const QString &mainUiFile)
{
QJsonObject runConfig = m_project["runConfig"].toObject();
runConfig["mainUiFile"] = mainUiFile;
insertAndUpdateProjectFile("runConfig", runConfig);
}
QString QmlProjectItem::mainUiFile() const
{
return m_project["runConfig"].toObject()["mainUiFile"].toString();
}
Utils::FilePath QmlProjectItem::mainUiFilePath() const
{
return Utils::FilePath::fromString(m_project["runConfig"].toObject()["mainUiFile"].toString());
}
bool QmlProjectItem::widgetApp() const
{
return m_project["runConfig"].toObject()["widgetApp"].toBool();
}
void QmlProjectItem::setWidgetApp(const bool &widgetApp)
{
QJsonObject runConfig = m_project["runConfig"].toObject();
runConfig["widgetApp"] = widgetApp;
insertAndUpdateProjectFile("runConfig", runConfig);
}
QStringList QmlProjectItem::shaderToolArgs() const
{
return m_project["shaderTool"].toObject()["args"].toVariant().toStringList();
}
void QmlProjectItem::setShaderToolArgs(const QStringList &args)
{
QJsonObject shaderTool = m_project["shaderTool"].toObject();
shaderTool["args"] = QJsonArray::fromStringList(args);
insertAndUpdateProjectFile("shaderTool", shaderTool);
}
void QmlProjectItem::addShaderToolArg(const QString &arg)
{
QJsonObject targetObj = m_project["shaderTool"].toObject();
QJsonArray toolArgs = targetObj["args"].toArray();
if (toolArgs.contains(arg))
return;
toolArgs.append(arg);
targetObj["args"] = toolArgs;
insertAndUpdateProjectFile("shaderTool", targetObj);
}
QStringList QmlProjectItem::shaderToolFiles() const
{
return m_project.value("shaderTool").toObject().value("files").toVariant().toStringList();
}
void QmlProjectItem::setShaderToolFiles(const QStringList &files)
{
QJsonObject shaderTool = m_project["shaderTool"].toObject();
shaderTool["files"] = QJsonArray::fromStringList(files);
insertAndUpdateProjectFile("shaderTool", shaderTool);
}
void QmlProjectItem::addShaderToolFile(const QString &file)
{
QJsonObject targetObj = m_project["shaderTool"].toObject();
QJsonArray toolArgs = targetObj["files"].toArray();
if (toolArgs.contains(file))
return;
toolArgs.append(file);
targetObj["files"] = toolArgs;
insertAndUpdateProjectFile("shaderTool", targetObj);
}
void QmlProjectItem::insertAndUpdateProjectFile(const QString &key, const QJsonValue &value)
{
m_project[key] = value;
#ifndef TESTS_ENABLED_QMLPROJECTITEM
m_projectFile.writeFileContents(Converters::jsonToQmlProject(m_project).toUtf8());
#endif
}
} // namespace QmlProjectManager

View File

@@ -0,0 +1,108 @@
// 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
#pragma once
#include "filefilteritems.h"
#include <utils/environment.h>
#include <QObject>
#include <QSet>
#include <QStringList>
#include <QSharedPointer>
#include <QJsonObject>
#include <memory>
#include <vector>
namespace QmlJS {
class SimpleReaderNode;
}
namespace QmlProjectManager {
class QmlProjectItem : public QObject
{
Q_OBJECT
public:
explicit QmlProjectItem(const Utils::FilePath &filePath);
bool isQt4McuProject() const;
bool isQt6Project() const;
Utils::FilePath sourceDirectory() const;
QString targetDirectory() const;
QStringList importPaths() const;
void setImportPaths(const QStringList &paths);
void addImportPath(const QString &importPath);
QStringList fileSelectors() const;
void setFileSelectors(const QStringList &selectors);
void addFileSelector(const QString &selector);
bool multilanguageSupport() const;
void setMultilanguageSupport(const bool &isEnabled);
QStringList supportedLanguages() const;
void setSupportedLanguages(const QStringList &languages);
void addSupportedLanguage(const QString &language);
QString primaryLanguage() const;
void setPrimaryLanguage(const QString &language);
Utils::FilePaths files() const;
bool matchesFile(const QString &filePath) const;
bool forceFreeType() const;
void setForceFreeType(const bool &isForced);
void setMainFile(const QString &mainFile);
QString mainFile() const;
Utils::FilePath mainFilePath() const;
void setMainUiFile(const QString &mainUiFile);
QString mainUiFile() const;
Utils::FilePath mainUiFilePath() const;
bool widgetApp() const;
void setWidgetApp(const bool &widgetApp);
QStringList shaderToolArgs() const;
void setShaderToolArgs(const QStringList &args);
void addShaderToolArg(const QString &arg);
QStringList shaderToolFiles() const;
void setShaderToolFiles(const QStringList &files);
void addShaderToolFile(const QString &file);
Utils::EnvironmentItems environment() const;
void addToEnviroment(const QString &key, const QString &value);
QJsonObject project() const;
signals:
void qmlFilesChanged(const QSet<QString> &, const QSet<QString> &);
private:
typedef QSharedPointer<QmlProjectItem> ShrdPtrQPI;
typedef std::unique_ptr<FileFilterItem> UnqPtrFFBI;
typedef std::unique_ptr<FileFilterItem> UnqPtrFFI;
// files & props
std::vector<std::unique_ptr<FileFilterItem>> m_content; // content property
// runtime variables
Utils::FilePath m_projectFile; // design studio project file
QJsonObject m_project; // root project object
// initializing functions
bool initProjectObject();
void setupFileFilters();
// file update functions
void insertAndUpdateProjectFile(const QString &key, const QJsonValue &value);
};
} // namespace QmlProjectManager

View File

@@ -10,8 +10,7 @@
using namespace ProjectExplorer;
namespace QmlProjectManager {
namespace Internal {
namespace QmlProjectManager::Internal {
QmlProjectNode::QmlProjectNode(Project *project)
: ProjectNode(project->projectDirectory())
@@ -21,5 +20,4 @@ QmlProjectNode::QmlProjectNode(Project *project)
setIcon(DirectoryIcon(":/projectexplorer/images/fileoverlay_qml.png"));
}
} // namespace Internal
} // namespace QmlProjectManager

View File

@@ -0,0 +1,544 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "qmlbuildsystem.h"
#include "qmlprojectconstants.h"
#include <QtCore5Compat/qtextcodec.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include "projectitem/qmlprojectitem.h"
#include "projectnode/qmlprojectnodes.h"
#include "utils/algorithm.h"
#include "utils/qtcassert.h"
#include "texteditor/textdocument.h"
using namespace ProjectExplorer;
namespace QmlProjectManager {
namespace {
Q_LOGGING_CATEGORY(infoLogger, "QmlProjectManager.QmlBuildSystem", QtInfoMsg)
}
QmlBuildSystem::QmlBuildSystem(Target *target)
: BuildSystem(target)
{
// refresh first - project information is used e.g. to decide the default RC's
refresh(RefreshOptions::Project);
updateDeploymentData();
registerMenuButtons();
connect(target->project(), &Project::activeTargetChanged, [this]() { refresh(RefreshOptions::NoFileRefresh); });
connect(target->project(), &Project::projectFileIsDirty, [this]() {
refresh(RefreshOptions::Project);
});
// 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);
}
void QmlBuildSystem::updateDeploymentData()
{
if (!m_projectItem)
return;
if (DeviceTypeKitAspect::deviceTypeId(kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
return;
}
ProjectExplorer::DeploymentData deploymentData;
for (const auto &file : m_projectItem->files()) {
deploymentData.addFile(file, targetFile(file).parentDir().toString());
}
setDeploymentData(deploymentData);
}
void QmlBuildSystem::registerMenuButtons()
{
Core::ActionContainer *menu = Core::ActionManager::actionContainer(Core::Constants::M_FILE);
// QML Project file update button
// This button saves the current configuration into the .qmlproject file
auto action = new QAction("Update QmlProject File", this);
Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.ProjectManager");
menu->addAction(cmd, Core::Constants::G_FILE_SAVE);
QObject::connect(action, &QAction::triggered, this, &QmlBuildSystem::updateProjectFile);
}
bool QmlBuildSystem::updateProjectFile()
{
qDebug() << "debug#1-mainfilepath" << mainFilePath();
QFile file(mainFilePath().fileName().append("project-test"));
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
qCritical() << "Cannot open Qml Project file for editing!";
return false;
}
QTextStream ts(&file);
// License
ts << "/* "
"File generated by Qt Creator"
"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"
"*/"
<< Qt::endl
<< Qt::endl;
// Components
ts << "import QmlProject 1.1" << Qt::endl << Qt::endl;
return true;
}
void QmlBuildSystem::triggerParsing()
{
refresh(RefreshOptions::Project);
}
Utils::FilePath QmlBuildSystem::canonicalProjectDir() const
{
return BuildSystem::target()
->project()
->projectFilePath()
.canonicalPath()
.normalizedPathName()
.parentDir();
}
void QmlBuildSystem::refresh(RefreshOptions options)
{
ParseGuard guard = guardParsingRun();
switch (options) {
case RefreshOptions::NoFileRefresh:
break;
case RefreshOptions::Project:
initProjectItem();
case RefreshOptions::Files:
parseProjectFiles();
}
auto modelManager = QmlJS::ModelManagerInterface::instance();
if (!modelManager)
return;
QmlJS::ModelManagerInterface::ProjectInfo projectInfo
= modelManager->defaultProjectInfoForProject(project(),
project()->files(Project::HiddenRccFolders));
const QStringList searchPaths = makeAbsolute(canonicalProjectDir(), customImportPaths());
for (const QString &searchPath : searchPaths)
projectInfo.importPaths.maybeInsert(Utils::FilePath::fromString(searchPath),
QmlJS::Dialect::Qml);
modelManager->updateProjectInfo(projectInfo, project());
guard.markAsSuccess();
emit projectChanged();
}
void QmlBuildSystem::initProjectItem()
{
m_projectItem.reset(new QmlProjectItem{projectFilePath()});
connect(m_projectItem.get(),
&QmlProjectItem::qmlFilesChanged,
this,
&QmlBuildSystem::refreshFiles);
}
void QmlBuildSystem::parseProjectFiles()
{
if (auto modelManager = QmlJS::ModelManagerInterface::instance()) {
modelManager->updateSourceFiles(m_projectItem->files(), true);
}
Utils::FilePath mainFilePath{Utils::FilePath::fromString(m_projectItem->mainFile())};
if (!mainFilePath.isEmpty()) {
mainFilePath = canonicalProjectDir().resolvePath(m_projectItem->mainFile());
Utils::FileReader reader;
QString errorMessage;
if (!reader.fetch(mainFilePath, &errorMessage)) {
Core::MessageManager::writeFlashing(
tr("Warning while loading project file %1.").arg(projectFilePath().toUserOutput()));
Core::MessageManager::writeSilently(errorMessage);
}
}
generateProjectTree();
}
void QmlBuildSystem::generateProjectTree()
{
auto newRoot = std::make_unique<Internal::QmlProjectNode>(project());
for (const auto &file : m_projectItem->files()) {
const FileType fileType = (file == projectFilePath())
? FileType::Project
: FileNode::fileTypeForFileName(file);
newRoot->addNestedNode(std::make_unique<FileNode>(file, fileType));
}
newRoot->addNestedNode(std::make_unique<FileNode>(projectFilePath(), FileType::Project));
setRootProjectNode(std::move(newRoot));
updateDeploymentData();
}
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
Utils::TextFileFormat::ReadResult readResult = Utils::TextFileFormat::readFile(qmlProjectFilePath,
codec,
&fileContent,
&textFileFormat,
&error);
if (readResult != Utils::TextFileFormat::ReadSuccess) {
qWarning() << "Failed to read file" << qmlProjectFilePath << ":" << error;
}
const QString settingQmlCode = setting + ":";
const Utils::FilePath projectDir = project()->projectFilePath().parentDir();
const QString relativePath = mainFilePath.relativeChildPath(projectDir).path();
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(RefreshOptions::Project);
return true;
}
bool QmlBuildSystem::blockFilesUpdate() const
{
return m_blockFilesUpdate;
}
void QmlBuildSystem::setBlockFilesUpdate(bool newBlockFilesUpdate)
{
m_blockFilesUpdate = newBlockFilesUpdate;
}
Utils::FilePath QmlBuildSystem::mainFilePath() const
{
return projectDirectory().pathAppended(mainFile());
}
Utils::FilePath QmlBuildSystem::mainUiFilePath() const
{
return m_projectItem->mainUiFilePath();
}
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, m_projectItem->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;
}
Utils::FilePath QmlBuildSystem::targetDirectory() const
{
if (DeviceTypeKitAspect::deviceTypeId(kit()) == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
return canonicalProjectDir();
return m_projectItem ? Utils::FilePath::fromString(m_projectItem->targetDirectory())
: Utils::FilePath();
}
Utils::FilePath QmlBuildSystem::targetFile(const Utils::FilePath &sourceFile) const
{
const QDir sourceDir(m_projectItem ? m_projectItem->sourceDirectory().path()
: canonicalProjectDir().toString());
const QDir targetDir(targetDirectory().toString());
const QString relative = sourceDir.relativeFilePath(sourceFile.toString());
return Utils::FilePath::fromString(QDir::cleanPath(targetDir.absoluteFilePath(relative)));
}
void QmlBuildSystem::setSupportedLanguages(QStringList languages)
{
m_projectItem->setSupportedLanguages(languages);
}
void QmlBuildSystem::setPrimaryLanguage(QString language)
{
m_projectItem->setPrimaryLanguage(language);
}
QStringList QmlBuildSystem::makeAbsolute(const Utils::FilePath &path,
const QStringList &relativePaths)
{
if (path.isEmpty())
return relativePaths;
const QDir baseDir(path.toString());
return Utils::transform(relativePaths, [&baseDir](const QString &path) {
return QDir::cleanPath(baseDir.absoluteFilePath(path));
});
}
void QmlBuildSystem::refreshFiles(const QSet<QString> & /*added*/, const QSet<QString> &removed)
{
if (m_blockFilesUpdate) {
qCDebug(infoLogger) << "Auto files refresh blocked.";
return;
}
refresh(RefreshOptions::Files);
if (!removed.isEmpty()) {
if (auto modelManager = QmlJS::ModelManagerInterface::instance()) {
modelManager->removeFiles(
Utils::transform<QList<Utils::FilePath>>(removed, [](const QString &s) {
return Utils::FilePath::fromString(s);
}));
}
}
updateDeploymentData();
}
QVariant QmlBuildSystem::additionalData(Utils::Id id) const
{
if (id == Constants::customFileSelectorsData)
return customFileSelectors();
if (id == Constants::supportedLanguagesData)
return supportedLanguages();
if (id == Constants::primaryLanguageData)
return primaryLanguage();
if (id == Constants::customForceFreeTypeData)
return forceFreeType();
if (id == Constants::customQtForMCUs)
return qtForMCUs();
if (id == Constants::customQt6Project)
return qt6Project();
if (id == Constants::mainFilePath)
return mainFilePath().toString();
if (id == Constants::customImportPaths)
return customImportPaths();
if (id == Constants::canonicalProjectDir)
return canonicalProjectDir().toString();
return {};
}
bool QmlBuildSystem::supportsAction(Node *context, ProjectAction action, const Node *node) const
{
if (dynamic_cast<Internal::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);
}
bool QmlBuildSystem::addFiles(Node *context, const Utils::FilePaths &filePaths, Utils::FilePaths *)
{
if (!dynamic_cast<Internal::QmlProjectNode *>(context))
return false;
Utils::FilePaths toAdd;
for (const Utils::FilePath &filePath : filePaths) {
if (!m_projectItem->matchesFile(filePath.toString()))
toAdd << filePaths;
}
return toAdd.isEmpty();
}
bool QmlBuildSystem::deleteFiles(Node *context, const Utils::FilePaths &filePaths)
{
if (dynamic_cast<Internal::QmlProjectNode *>(context))
return true;
return BuildSystem::deleteFiles(context, filePaths);
}
bool QmlBuildSystem::renameFile(Node *context,
const Utils::FilePath &oldFilePath,
const Utils::FilePath &newFilePath)
{
if (dynamic_cast<Internal::QmlProjectNode *>(context)) {
if (oldFilePath.endsWith(mainFile()))
return setMainFileInProjectFile(newFilePath);
if (oldFilePath.endsWith(m_projectItem->mainUiFile()))
return setMainUiFileInProjectFile(newFilePath);
return true;
}
return BuildSystem::renameFile(context, oldFilePath, newFilePath);
}
QString QmlBuildSystem::mainFile() const
{
return m_projectItem->mainFile();
}
bool QmlBuildSystem::qtForMCUs() const
{
return m_projectItem->isQt4McuProject();
}
bool QmlBuildSystem::qt6Project() const
{
return m_projectItem->isQt6Project();
}
Utils::EnvironmentItems QmlBuildSystem::environment() const
{
return m_projectItem->environment();
}
QStringList QmlBuildSystem::customImportPaths() const
{
return m_projectItem->importPaths();
}
QStringList QmlBuildSystem::customFileSelectors() const
{
return m_projectItem->fileSelectors();
}
bool QmlBuildSystem::multilanguageSupport() const
{
return m_projectItem->multilanguageSupport();
}
QStringList QmlBuildSystem::supportedLanguages() const
{
return m_projectItem->supportedLanguages();
}
QString QmlBuildSystem::primaryLanguage() const
{
return m_projectItem->primaryLanguage();
}
bool QmlBuildSystem::forceFreeType() const
{
return m_projectItem->forceFreeType();
}
bool QmlBuildSystem::widgetApp() const
{
return m_projectItem->widgetApp();
}
QStringList QmlBuildSystem::shaderToolArgs() const
{
return m_projectItem->shaderToolArgs();
}
QStringList QmlBuildSystem::shaderToolFiles() const
{
return m_projectItem->shaderToolFiles();
}
QStringList QmlBuildSystem::importPaths() const
{
return m_projectItem->importPaths();
}
Utils::FilePaths QmlBuildSystem::files() const
{
return m_projectItem->files();
}
} // namespace QmlProjectManager

View File

@@ -0,0 +1,115 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once
#include "../qmlprojectmanager_global.h"
#include <projectexplorer/buildsystem.h>
namespace QmlProjectManager {
class QmlProject;
class QmlProjectItem;
class QmlProjectFile;
class QMLPROJECTMANAGER_EXPORT QmlBuildSystem : public ProjectExplorer::BuildSystem
{
Q_OBJECT
public:
explicit QmlBuildSystem(ProjectExplorer::Target *target);
~QmlBuildSystem() = default;
void triggerParsing() final;
bool supportsAction(ProjectExplorer::Node *context,
ProjectExplorer::ProjectAction action,
const ProjectExplorer::Node *node) const override;
bool addFiles(ProjectExplorer::Node *context,
const Utils::FilePaths &filePaths,
Utils::FilePaths *notAdded = nullptr) override;
bool deleteFiles(ProjectExplorer::Node *context, const Utils::FilePaths &filePaths) override;
bool renameFile(ProjectExplorer::Node *context,
const Utils::FilePath &oldFilePath,
const Utils::FilePath &newFilePath) override;
bool updateProjectFile();
QString name() const override { return QLatin1String("qml"); }
QmlProject *qmlProject() const;
QVariant additionalData(Utils::Id id) const override;
enum class RefreshOptions {
NoFileRefresh,
Files,
Project,
};
void refresh(RefreshOptions options);
bool setMainFileInProjectFile(const Utils::FilePath &newMainFilePath);
bool setMainUiFileInProjectFile(const Utils::FilePath &newMainUiFilePath);
bool setMainUiFileInMainFile(const Utils::FilePath &newMainUiFilePath);
Utils::FilePath canonicalProjectDir() const;
QString mainFile() const;
Utils::FilePath mainFilePath() const;
Utils::FilePath mainUiFilePath() const;
bool qtForMCUs() const;
bool qt6Project() const;
Utils::FilePath targetDirectory() const;
Utils::FilePath targetFile(const Utils::FilePath &sourceFile) const;
Utils::EnvironmentItems environment() const;
QStringList customImportPaths() const;
QStringList customFileSelectors() const;
bool multilanguageSupport() const;
QStringList supportedLanguages() const;
void setSupportedLanguages(QStringList languages);
QString primaryLanguage() const;
void setPrimaryLanguage(QString language);
bool forceFreeType() const;
bool widgetApp() const;
QStringList shaderToolArgs() const;
QStringList shaderToolFiles() const;
QStringList importPaths() const;
Utils::FilePaths files() const;
bool addFiles(const QStringList &filePaths);
void refreshProjectFile();
static Utils::FilePath activeMainFilePath();
static QStringList makeAbsolute(const Utils::FilePath &path, const QStringList &relativePaths);
void refreshFiles(const QSet<QString> &added, const QSet<QString> &removed);
bool blockFilesUpdate() const;
void setBlockFilesUpdate(bool newBlockFilesUpdate);
signals:
void projectChanged();
private:
bool setFileSettingInProjectFile(const QString &setting,
const Utils::FilePath &mainFilePath,
const QString &oldFile);
QSharedPointer<QmlProjectItem> m_projectItem;
bool m_blockFilesUpdate = false;
void initProjectItem();
void parseProjectFiles();
void generateProjectTree();
void registerMenuButtons();
void updateDeploymentData();
friend class FilesUpdateBlocker;
};
} // namespace QmlProjectManager

View File

@@ -1,198 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qmlprojectfileformat.h"
#include "filefilteritems.h"
#include "qmlprojectitem.h"
#include "../qmlprojectmanagertr.h"
#include <qmljs/qmljssimplereader.h>
#include <utils/filepath.h>
#include <QDebug>
#include <QVariant>
#include <memory>
using namespace Utils;
enum {
debug = false
};
namespace {
std::unique_ptr<QmlProjectManager::FileFilterBaseItem> setupFileFilterItem(
std::unique_ptr<QmlProjectManager::FileFilterBaseItem> fileFilterItem,
const QmlJS::SimpleReaderNode::Ptr &node)
{
const auto directoryProperty = node->property(QLatin1String("directory"));
if (directoryProperty.isValid())
fileFilterItem->setDirectory(directoryProperty.value.toString());
const auto recursiveProperty = node->property(QLatin1String("recursive"));
if (recursiveProperty.isValid())
fileFilterItem->setRecursive(recursiveProperty.value.toBool());
const auto pathsProperty = node->property(QLatin1String("paths"));
if (pathsProperty.isValid())
fileFilterItem->setPathsProperty(pathsProperty.value.toStringList());
// "paths" and "files" have the same functionality
const auto filesProperty = node->property(QLatin1String("files"));
if (filesProperty.isValid())
fileFilterItem->setPathsProperty(filesProperty.value.toStringList());
const auto filterProperty = node->property(QLatin1String("filter"));
if (filterProperty.isValid())
fileFilterItem->setFilter(filterProperty.value.toString());
if (debug)
qDebug() << "directory:" << directoryProperty.value << "recursive" << recursiveProperty.value
<< "paths" << pathsProperty.value << "files" << filesProperty.value;
return fileFilterItem;
}
} //namespace
namespace QmlProjectManager {
std::unique_ptr<QmlProjectItem> QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fileName,
QString *errorMessage)
{
QmlJS::SimpleReader simpleQmlJSReader;
const QmlJS::SimpleReaderNode::Ptr rootNode = simpleQmlJSReader.readFile(fileName.toString());
if (!simpleQmlJSReader.errors().isEmpty() || !rootNode->isValid()) {
qWarning() << "unable to parse:" << fileName;
qWarning() << simpleQmlJSReader.errors();
if (errorMessage)
*errorMessage = simpleQmlJSReader.errors().join(QLatin1String(", "));
return nullptr;
}
if (rootNode->name() == QLatin1String("Project")) {
auto projectItem = std::make_unique<QmlProjectItem>();
const auto mainFileProperty = rootNode->property(QLatin1String("mainFile"));
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();
list.removeAll(".");
projectItem->setImportPaths(list);
}
const auto fileSelectorsProperty = rootNode->property(QLatin1String("fileSelectors"));
if (fileSelectorsProperty.isValid())
projectItem->setFileSelectors(fileSelectorsProperty.value.toStringList());
const auto multilanguageSupportProperty = rootNode->property(
QLatin1String("multilanguageSupport"));
if (multilanguageSupportProperty.isValid())
projectItem->setMultilanguageSupport(multilanguageSupportProperty.value.toBool());
const auto languagesProperty = rootNode->property(QLatin1String("supportedLanguages"));
if (languagesProperty.isValid())
projectItem->setSupportedLanguages(languagesProperty.value.toStringList());
const auto primaryLanguageProperty = rootNode->property(QLatin1String("primaryLanguage"));
if (primaryLanguageProperty.isValid())
projectItem->setPrimaryLanguage(primaryLanguageProperty.value.toString());
const auto forceFreeTypeProperty = rootNode->property("forceFreeType");
if (forceFreeTypeProperty.isValid())
projectItem->setForceFreeType(forceFreeTypeProperty.value.toBool());
const auto targetDirectoryPropery = rootNode->property("targetDirectory");
if (targetDirectoryPropery.isValid())
projectItem->setTargetDirectory(FilePath::fromSettings(targetDirectoryPropery.value));
const auto qtForMCUProperty = rootNode->property("qtForMCUs");
if (qtForMCUProperty.isValid() && qtForMCUProperty.value.toBool())
projectItem->setQtForMCUs(qtForMCUProperty.value.toBool());
const auto qt6ProjectProperty = rootNode->property("qt6Project");
if (qt6ProjectProperty.isValid() && qt6ProjectProperty.value.toBool())
projectItem->setQt6Project(qt6ProjectProperty.value.toBool());
const auto widgetAppProperty = rootNode->property("widgetApp");
if (widgetAppProperty.isValid())
projectItem->setWidgetApp(widgetAppProperty.value.toBool());
if (debug)
qDebug() << "importPath:" << importPathsProperty.value << "mainFile:" << mainFileProperty.value;
const QList<QmlJS::SimpleReaderNode::Ptr> childNodes = rootNode->children();
for (const QmlJS::SimpleReaderNode::Ptr &childNode : childNodes) {
if (debug)
qDebug() << "reading type:" << childNode->name();
if (childNode->name() == QLatin1String("QmlFiles")) {
projectItem->appendContent(
setupFileFilterItem(std::make_unique<FileFilterItem>("*.qml"), childNode));
} else if (childNode->name() == QLatin1String("JavaScriptFiles")) {
projectItem->appendContent(
setupFileFilterItem(std::make_unique<FileFilterItem>("*.js"), childNode));
} else if (childNode->name() == QLatin1String("ImageFiles")) {
projectItem->appendContent(
setupFileFilterItem(std::make_unique<ImageFileFilterItem>(), childNode));
} else if (childNode->name() == QLatin1String("CssFiles")) {
projectItem->appendContent(
setupFileFilterItem(std::make_unique<FileFilterItem>("*.css"), childNode));
} else if (childNode->name() == QLatin1String("FontFiles")) {
projectItem->appendContent(
setupFileFilterItem(std::make_unique<FileFilterItem>("*.ttf;*.otf"), childNode));
} else if (childNode->name() == QLatin1String("Files")) {
projectItem->appendContent(
setupFileFilterItem(std::make_unique<FileFilterBaseItem>(), childNode));
} else if (childNode->name() == "Environment") {
const auto properties = childNode->properties();
auto i = properties.constBegin();
while (i != properties.constEnd()) {
projectItem->addToEnviroment(i.key(), i.value().value.toString());
++i;
}
} else if (childNode->name() == "ShaderTool") {
QmlJS::SimpleReaderNode::Property commandLine = childNode->property("args");
if (commandLine.isValid()) {
const QStringList quotedArgs = commandLine.value.toString().split('\"');
QStringList args;
for (int i = 0; i < quotedArgs.size(); ++i) {
// Each odd arg in this list is a single quoted argument, which we should
// not be split further
if (i % 2 == 0)
args.append(quotedArgs[i].trimmed().split(' '));
else
args.append(quotedArgs[i]);
}
args.removeAll({});
args.append("-o"); // Prepare for adding output file as next arg
projectItem->setShaderToolArgs(args);
}
QmlJS::SimpleReaderNode::Property files = childNode->property("files");
if (files.isValid())
projectItem->setShaderToolFiles(files.value.toStringList());
} else {
qWarning() << "Unknown type:" << childNode->name();
}
}
return projectItem;
}
if (errorMessage)
*errorMessage = Tr::tr("Invalid root element: %1").arg(rootNode->name());
return nullptr;
}
} // namespace QmlProjectManager

View File

@@ -1,22 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <utils/fileutils.h>
#include <QCoreApplication>
#include <QString>
namespace QmlProjectManager {
class QmlProjectItem;
class QmlProjectFileFormat
{
public:
static std::unique_ptr<QmlProjectItem> parseProjectFile(const Utils::FilePath &fileName,
QString *errorMessage = nullptr);
};
} // namespace QmlProjectManager

View File

@@ -1,118 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "qmlprojectitem.h"
#include "filefilteritems.h"
#include <utils/algorithm.h>
#include <QDir>
using namespace Utils;
namespace QmlProjectManager {
// kind of initialization
void QmlProjectItem::setSourceDirectory(const FilePath &directoryPath)
{
if (m_sourceDirectory == directoryPath)
return;
m_sourceDirectory = directoryPath;
for (auto &fileFilter : m_content) {
fileFilter->setDefaultDirectory(directoryPath.toFSPathString());
connect(fileFilter.get(),
&FileFilterBaseItem::filesChanged,
this,
&QmlProjectItem::qmlFilesChanged);
}
}
void QmlProjectItem::setTargetDirectory(const FilePath &directoryPath)
{
m_targetDirectory = directoryPath;
}
void QmlProjectItem::setQtForMCUs(bool b)
{
m_qtForMCUs = b;
}
void QmlProjectItem::setQt6Project(bool qt6Project)
{
m_qt6Project = qt6Project;
}
void QmlProjectItem::setImportPaths(const QStringList &importPaths)
{
if (m_importPaths != importPaths)
m_importPaths = importPaths;
}
void QmlProjectItem::setFileSelectors(const QStringList &selectors)
{
if (m_fileSelectors != selectors)
m_fileSelectors = selectors;
}
void QmlProjectItem::setMultilanguageSupport(const bool isEnabled)
{
m_multilanguageSupport = isEnabled;
}
void QmlProjectItem::setSupportedLanguages(const QStringList &languages)
{
if (m_supportedLanguages != languages)
m_supportedLanguages = languages;
}
void QmlProjectItem::setPrimaryLanguage(const QString &language)
{
if (m_primaryLanguage != language)
m_primaryLanguage = language;
}
/* Returns list of absolute paths */
QStringList QmlProjectItem::files() const
{
QSet<QString> files;
for (const auto &fileFilter : m_content) {
const QStringList fileList = fileFilter->files();
for (const QString &file : fileList) {
files.insert(file);
}
}
return Utils::toList(files);
}
/**
Check whether the project would include a file path
- regardless whether the file already exists or not.
@param filePath: absolute file path to check
*/
bool QmlProjectItem::matchesFile(const QString &filePath) const
{
return Utils::contains(m_content, [&filePath](const auto &fileFilter) {
return fileFilter->matchesFile(filePath);
});
}
void QmlProjectItem::setForceFreeType(bool b)
{
m_forceFreeType = b;
}
Utils::EnvironmentItems QmlProjectItem::environment() const
{
return m_environment;
}
void QmlProjectItem::addToEnviroment(const QString &key, const QString &value)
{
m_environment.append(Utils::EnvironmentItem(key, value));
}
} // namespace QmlProjectManager

View File

@@ -1,103 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include "filefilteritems.h"
#include <utils/environment.h>
#include <utils/filepath.h>
#include <QObject>
#include <QSet>
#include <QStringList>
#include <memory>
#include <vector>
namespace QmlProjectManager {
class QmlProjectItem : public QObject
{
Q_OBJECT
public:
const Utils::FilePath &sourceDirectory() const { return m_sourceDirectory; }
void setSourceDirectory(const Utils::FilePath &directoryPath);
const Utils::FilePath &targetDirectory() const { return m_targetDirectory; }
void setTargetDirectory(const Utils::FilePath &directoryPath);
bool qtForMCUs() const { return m_qtForMCUs; }
void setQtForMCUs(bool qtForMCUs);
bool qt6Project() const { return m_qt6Project; }
void setQt6Project(bool qt6Project);
QStringList importPaths() const { return m_importPaths; }
void setImportPaths(const QStringList &paths);
QStringList fileSelectors() const { return m_fileSelectors; }
void setFileSelectors(const QStringList &selectors);
bool multilanguageSupport() const { return m_multilanguageSupport; }
void setMultilanguageSupport(const bool isEnabled);
QStringList supportedLanguages() const { return m_supportedLanguages; }
void setSupportedLanguages(const QStringList &languages);
QString primaryLanguage() const { return m_primaryLanguage; }
void setPrimaryLanguage(const QString &language);
QStringList files() const;
bool matchesFile(const QString &filePath) const;
bool forceFreeType() const { return m_forceFreeType; };
void setForceFreeType(bool);
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; }
QStringList shaderToolArgs() const { return m_shaderToolArgs; }
void setShaderToolArgs(const QStringList &args) {m_shaderToolArgs = args; }
QStringList shaderToolFiles() const { return m_shaderToolFiles; }
void setShaderToolFiles(const QStringList &files) { m_shaderToolFiles = files; }
void appendContent(std::unique_ptr<FileFilterBaseItem> item)
{
m_content.push_back(std::move(item));
}
Utils::EnvironmentItems environment() const;
void addToEnviroment(const QString &key, const QString &value);
signals:
void qmlFilesChanged(const QSet<QString> &, const QSet<QString> &);
protected:
Utils::FilePath m_sourceDirectory;
Utils::FilePath m_targetDirectory;
QStringList m_importPaths;
QStringList m_fileSelectors;
bool m_multilanguageSupport;
QStringList m_supportedLanguages;
QString m_primaryLanguage;
QString m_mainFile;
QString m_mainUiFile;
Utils::EnvironmentItems m_environment;
std::vector<std::unique_ptr<FileFilterBaseItem>> m_content; // content property
bool m_forceFreeType = false;
bool m_qtForMCUs = false;
bool m_qt6Project = false;
bool m_widgetApp = false;
QStringList m_shaderToolArgs;
QStringList m_shaderToolFiles;
};
} // namespace QmlProjectManager

View File

@@ -181,7 +181,7 @@ void QmlMainFileAspect::setScriptSource(MainScriptSource source, const QString &
FilePath QmlMainFileAspect::mainScript() const
{
if (!qmlBuildSystem()->mainFile().isEmpty()) {
const FilePath pathInProject = qmlBuildSystem()->mainFile();
const FilePath pathInProject = qmlBuildSystem()->mainFilePath();
return qmlBuildSystem()->canonicalProjectDir().resolvePath(pathInProject);
}

View File

@@ -1,554 +1,163 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "qmlproject.h"
#include "fileformat/qmlprojectfileformat.h"
#include "fileformat/qmlprojectitem.h"
#include "qmlprojectconstants.h"
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectmanagertr.h"
#include "qmlprojectnodes.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/modemanager.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtsupportconstants.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <texteditor/textdocument.h>
#include <utils/algorithm.h>
#include <utils/infobar.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <QDebug>
#include <QLoggingCategory>
#include <QMessageBox>
#include <QRegularExpression>
#include <QTextCodec>
#include <QTimer>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include "projectexplorer/devicesupport/idevice.h"
#include "qmlprojectconstants.h"
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectmanagertr.h"
#include "utils/algorithm.h"
using namespace Core;
using namespace ProjectExplorer;
using namespace QmlProjectManager::Internal;
using namespace Utils;
namespace {
Q_LOGGING_CATEGORY(infoLogger, "QmlProjectManager.QmlBuildSystem", QtInfoMsg)
}
namespace QmlProjectManager {
static int preferedQtTarget(Target *target)
{
if (target) {
const QmlBuildSystem *buildSystem = qobject_cast<QmlBuildSystem *>(target->buildSystem());
if (buildSystem && buildSystem->qt6Project())
return 6;
}
return 5;
}
static bool allowOnlySingleProject()
{
QSettings *settings = Core::ICore::settings();
const QString qdsAllowMultipleProjects = "QML/Designer/AllowMultipleProjects";
return !settings->value(qdsAllowMultipleProjects, false).toBool();
}
Utils::FilePaths QmlProject::collectUiQmlFilesForFolder(const Utils::FilePath &folder) const
{
const Utils::FilePaths uiFiles = files([&](const ProjectExplorer::Node *node) {
return node->filePath().completeSuffix() == "ui.qml"
&& node->filePath().parentDir() == folder;
});
return uiFiles;
}
FilePaths QmlProject::collectQmlFiles() const
{
return files([](const Node *node) { return node->filePath().suffix() == "qml"; });
}
QmlProject::QmlProject(const Utils::FilePath &fileName)
: Project(QString::fromLatin1(Constants::QMLPROJECT_MIMETYPE), fileName)
{
setId(QmlProjectManager::Constants::QML_PROJECT_ID);
setProjectLanguages(Context(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID));
setProjectLanguages(Core::Context(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID));
setDisplayName(fileName.completeBaseName());
setNeedsBuildConfigurations(false);
setBuildSystemCreator([](Target *t) { return new QmlBuildSystem(t); });
if (QmlProject::isQtDesignStudio()) {
// FIXME: why checking this?
// this should not even be the case. if that's possible, then what?
// what are the follow-up actions?
if (!QmlProject::isQtDesignStudio())
return;
if (allowOnlySingleProject()) {
EditorManager::closeAllDocuments();
Core::EditorManager::closeAllDocuments();
SessionManager::closeAllProjects();
}
m_openFileConnection
= connect(this,
&QmlProject::anyParsingFinished,
this,
[this](Target *target, bool success) {
if (m_openFileConnection)
disconnect(m_openFileConnection);
connect(this, &QmlProject::anyParsingFinished, this, &QmlProject::parsingFinished);
}
if (target && success) {
void QmlProject::parsingFinished(const Target *target, bool success)
{
// trigger only once
disconnect(this, &QmlProject::anyParsingFinished, this, &QmlProject::parsingFinished);
auto target = activeTarget();
if (!target)
// FIXME: what to do in this case?
if (!target || !success || !activeTarget())
return;
auto targetActive = activeTarget();
auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
target->buildSystem());
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());
Core::EditorManager::openEditor(mainUiFile, Utils::Id());
});
} else {
return;
}
Utils::FilePaths uiFiles = collectUiQmlFilesForFolder(
projectDirectory().pathAppended("content"));
if (uiFiles.isEmpty())
if (uiFiles.isEmpty()) {
uiFiles = collectUiQmlFilesForFolder(projectDirectory());
if (uiFiles.isEmpty())
uiFiles = collectQmlFiles();
return;
}
if (!uiFiles.isEmpty()) {
Utils::FilePath currentFile;
if (auto cd = Core::EditorManager::currentDocument())
currentFile = cd->filePath();
if (currentFile.isEmpty() || !isKnownFile(currentFile))
if (currentFile.isEmpty() || !isKnownFile(currentFile)) {
QTimer::singleShot(1000, [uiFiles]() {
Core::EditorManager::openEditor(uiFiles.first(),
Utils::Id());
Core::ModeManager::activateMode(
Core::Constants::MODE_DESIGN);
});
}
}
}
Core::EditorManager::openEditor(uiFiles.first(), Utils::Id());
});
}
}
QmlBuildSystem::QmlBuildSystem(Target *target)
: BuildSystem(target)
Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *errorMessage)
{
m_canonicalProjectDir =
target->project()->projectFilePath().canonicalPath().normalizedPathName().parentDir();
RestoreResult result = Project::fromMap(map, errorMessage);
if (result != RestoreResult::Ok)
return result;
connect(target->project(), &Project::projectFileIsDirty,
this, &QmlBuildSystem::refreshProjectFile);
if (activeTarget())
return RestoreResult::Ok;
// refresh first - project information is used e.g. to decide the default RC's
refresh(Everything);
// find a kit that matches prerequisites (prefer default one)
const QList<Kit *> kits = Utils::filtered(KitManager::kits(), [this](const Kit *k) {
return !containsType(projectIssues(k), Task::TaskType::Error)
&& DeviceTypeKitAspect::deviceTypeId(k)
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
});
// FIXME: Check. Probably bogus after the BuildSystem move.
// // addedTarget calls updateEnabled on the runconfigurations
// // which needs to happen after refresh
// const QLis<Target> targetList = targets();
// for (Target *t : targetList)
// addedTarget(t);
if (!kits.isEmpty()) {
if (kits.contains(KitManager::defaultKit()))
addTargetForDefaultKit();
else
addTargetForKit(kits.first());
}
connect(target->project(), &Project::activeTargetChanged,
this, &QmlBuildSystem::onActiveTargetChanged);
updateDeploymentData();
// FIXME: are there any other way?
// What if it's not a Design Studio project? What should we do then?
if (QmlProject::isQtDesignStudio()) {
int preferedVersion = preferedQtTarget(activeTarget());
// if (activeTarget())
// removeTarget(activeTarget());
setKitWithVersion(preferedVersion, kits);
}
return RestoreResult::Ok;
}
QmlBuildSystem::~QmlBuildSystem() = default;
void QmlBuildSystem::triggerParsing()
bool QmlProject::setKitWithVersion(const int qtMajorVersion, const QList<Kit *> kits)
{
refresh(Everything);
}
void QmlBuildSystem::onActiveTargetChanged(Target *)
{
// make sure e.g. the default qml imports are adapted
refresh(Configuration);
}
void QmlBuildSystem::onKitChanged()
{
// make sure e.g. the default qml imports are adapted
refresh(Configuration);
}
Utils::FilePath QmlBuildSystem::canonicalProjectDir() const
{
return m_canonicalProjectDir;
}
void QmlBuildSystem::parseProject(RefreshOptions options)
{
if (options & Files) {
if (options & ProjectFile)
m_projectItem.reset();
if (!m_projectItem) {
QString errorMessage;
m_projectItem = QmlProjectFileFormat::parseProjectFile(projectFilePath(), &errorMessage);
if (m_projectItem) {
connect(m_projectItem.get(),
&QmlProjectItem::qmlFilesChanged,
this,
&QmlBuildSystem::refreshFiles);
} else {
MessageManager::writeFlashing(
Tr::tr("Error while loading project file %1.").arg(projectFilePath().toUserOutput()));
MessageManager::writeSilently(errorMessage);
}
}
if (m_projectItem) {
m_projectItem->setSourceDirectory(canonicalProjectDir());
if (m_projectItem->targetDirectory().isEmpty())
m_projectItem->setTargetDirectory(canonicalProjectDir());
if (auto modelManager = QmlJS::ModelManagerInterface::instance()) {
QStringList files = m_projectItem->files();
modelManager
->updateSourceFiles(Utils::transform(files,
[](const QString &p) {
return Utils::FilePath::fromString(p);
}),
true);
}
QString mainFilePath = m_projectItem->mainFile();
if (!mainFilePath.isEmpty()) {
mainFilePath
= QDir(canonicalProjectDir().toString()).absoluteFilePath(mainFilePath);
Utils::FileReader reader;
QString errorMessage;
if (!reader.fetch(Utils::FilePath::fromString(mainFilePath), &errorMessage)) {
MessageManager::writeFlashing(Tr::tr("Warning while loading project file %1.")
.arg(projectFilePath().toUserOutput()));
MessageManager::writeSilently(errorMessage);
}
}
}
generateProjectTree();
}
if (options & Configuration) {
// update configuration
}
}
bool QmlBuildSystem::setFileSettingInProjectFile(const QString &setting,
const FilePath &mainFilePath,
const FilePath &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))
const QList<Kit *> qtVersionkits = Utils::filtered(kits, [qtMajorVersion](const Kit *k) {
if (!k->isAutoDetected())
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 + ":";
const Utils::FilePath projectDir = project()->projectFilePath().parentDir();
const QString relativePath = mainFilePath.relativeChildPath(projectDir).path();
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.path();
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();
parseProject(options);
if (options & Files)
generateProjectTree();
auto modelManager = QmlJS::ModelManagerInterface::instance();
if (!modelManager)
return;
QmlJS::ModelManagerInterface::ProjectInfo projectInfo
= modelManager->defaultProjectInfoForProject(project(),
project()->files(Project::HiddenRccFolders));
const QStringList searchPaths = makeAbsolute(canonicalProjectDir(), customImportPaths());
for (const QString &searchPath : searchPaths)
projectInfo.importPaths.maybeInsert(Utils::FilePath::fromString(searchPath),
QmlJS::Dialect::Qml);
modelManager->updateProjectInfo(projectInfo, project());
guard.markAsSuccess();
emit projectChanged();
}
FilePath QmlBuildSystem::mainFile() const
{
if (m_projectItem)
return FilePath::fromString(m_projectItem->mainFile());
return {};
}
FilePath QmlBuildSystem::mainUiFile() const
{
if (m_projectItem)
return FilePath::fromString(m_projectItem->mainUiFile());
return {};
}
FilePath QmlBuildSystem::mainFilePath() const
{
const auto mainFileString = mainFile();
if (mainFileString.isEmpty())
return {};
return projectDirectory().resolvePath(mainFileString);
}
FilePath QmlBuildSystem::mainUiFilePath() const
{
const auto mainUiFileString = mainUiFile();
if (mainUiFileString.isEmpty())
return {};
return projectDirectory().resolvePath(mainUiFileString);
}
bool QmlBuildSystem::setMainFileInProjectFile(const FilePath &newMainFilePath)
{
return setFileSettingInProjectFile("mainFile", newMainFilePath, mainFile());
}
bool QmlBuildSystem::setMainUiFileInProjectFile(const FilePath &newMainUiFilePath)
{
return setMainUiFileInMainFile(newMainUiFilePath)
&& setFileSettingInProjectFile("mainUiFile", newMainUiFilePath, mainUiFile());
}
bool QmlBuildSystem::setMainUiFileInMainFile(const 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))
if (k->isReplacementKit())
return false;
QtSupport::QtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
return (version && version->qtVersion().majorVersion() == qtMajorVersion);
});
if (!qtVersionkits.isEmpty()) {
if (qtVersionkits.contains(KitManager::defaultKit()))
addTargetForDefaultKit();
else
addTargetForKit(qtVersionkits.first());
}
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
Utils::FilePaths QmlProject::collectUiQmlFilesForFolder(const Utils::FilePath &folder) const
{
if (m_projectItem)
return m_projectItem->qtForMCUs();
return false;
}
bool QmlBuildSystem::qt6Project() const
{
if (m_projectItem)
return m_projectItem->qt6Project();
return false;
}
void QmlBuildSystem::setMainFile(const QString &mainFilePath)
{
if (m_projectItem)
m_projectItem->setMainFile(mainFilePath);
}
FilePath QmlBuildSystem::targetDirectory() const
{
if (DeviceTypeKitAspect::deviceTypeId(kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)
return canonicalProjectDir();
return m_projectItem ? m_projectItem->targetDirectory() : FilePath();
}
FilePath QmlBuildSystem::targetFile(const FilePath &sourceFile) const
{
const FilePath sourceDir = m_projectItem ? m_projectItem->sourceDirectory()
: canonicalProjectDir();
const FilePath targetDir = targetDirectory();
const FilePath relative = sourceFile.relativePathFrom(sourceDir);
return targetDir.resolvePath(relative);
}
Utils::EnvironmentItems QmlBuildSystem::environment() const
{
if (m_projectItem)
return m_projectItem->environment();
return {};
}
QStringList QmlBuildSystem::customImportPaths() const
{
if (m_projectItem)
return m_projectItem->importPaths();
return {};
}
QStringList QmlBuildSystem::customFileSelectors() const
{
if (m_projectItem)
return m_projectItem->fileSelectors();
return {};
}
bool QmlBuildSystem::multilanguageSupport() const
{
if (m_projectItem)
return m_projectItem->multilanguageSupport();
return false;
}
QStringList QmlBuildSystem::supportedLanguages() const
{
if (m_projectItem)
return m_projectItem->supportedLanguages();
return {};
}
void QmlBuildSystem::setSupportedLanguages(QStringList languages)
{
if (m_projectItem)
m_projectItem->setSupportedLanguages(languages);
}
QString QmlBuildSystem::primaryLanguage() const
{
if (m_projectItem)
return m_projectItem->primaryLanguage();
return {};
}
void QmlBuildSystem::setPrimaryLanguage(QString language)
{
if (m_projectItem)
m_projectItem->setPrimaryLanguage(language);
}
void QmlBuildSystem::refreshProjectFile()
{
refresh(QmlBuildSystem::ProjectFile | Files);
}
QStringList QmlBuildSystem::makeAbsolute(const Utils::FilePath &path, const QStringList &relativePaths)
{
if (path.isEmpty())
return relativePaths;
const QDir baseDir(path.toString());
return Utils::transform(relativePaths, [&baseDir](const QString &path) {
return QDir::cleanPath(baseDir.absoluteFilePath(path));
const Utils::FilePaths uiFiles = files([&](const Node *node) {
return node->filePath().completeSuffix() == "ui.qml"
&& node->filePath().parentDir() == folder;
});
}
void QmlBuildSystem::refreshFiles(const QSet<QString> &/*added*/, const QSet<QString> &removed)
{
if (m_blockFilesUpdate) {
qCDebug(infoLogger) << "Auto files refresh blocked.";
return;
}
refresh(Files);
if (!removed.isEmpty()) {
if (auto modelManager = QmlJS::ModelManagerInterface::instance()) {
modelManager->removeFiles(
Utils::transform<QList<Utils::FilePath>>(removed, [](const QString &s) {
return Utils::FilePath::fromString(s);
}));
}
}
refreshTargetDirectory();
}
void QmlBuildSystem::refreshTargetDirectory()
{
updateDeploymentData();
return uiFiles;
}
Tasks QmlProject::projectIssues(const Kit *k) const
@@ -572,8 +181,8 @@ Tasks QmlProject::projectIssues(const Kit *k) const
if (dev->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
if (version->type() == QtSupport::Constants::DESKTOPQT) {
if (version->qmlRuntimeFilePath().isEmpty()) {
result.append(createProjectTask(Task::TaskType::Error,
Tr::tr("Qt version has no QML utility.")));
result.append(
createProjectTask(Task::TaskType::Error, tr("Qt version has no QML utility.")));
}
} else {
// Non-desktop Qt on a desktop device? We don't support that.
@@ -589,68 +198,10 @@ Tasks QmlProject::projectIssues(const Kit *k) const
return result;
}
bool QmlProject::isEditModePreferred() const
{
return !isQtDesignStudio();
}
Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *errorMessage)
{
RestoreResult result = Project::fromMap(map, errorMessage);
if (result != RestoreResult::Ok)
return result;
if (!activeTarget()) {
// find a kit that matches prerequisites (prefer default one)
const QList<Kit *> kits = Utils::filtered(KitManager::kits(), [this](const Kit *k) {
return !containsType(projectIssues(k), Task::TaskType::Error)
&& DeviceTypeKitAspect::deviceTypeId(k)
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
});
if (!kits.isEmpty()) {
if (kits.contains(KitManager::defaultKit()))
addTargetForDefaultKit();
else
addTargetForKit(kits.first());
}
if (QmlProject::isQtDesignStudio()) {
auto setKitWithVersion = [&](int qtMajorVersion) {
const QList<Kit *> qtVersionkits
= Utils::filtered(kits, [qtMajorVersion](const Kit *k) {
if (!k->isAutoDetected())
return false;
if (k->isReplacementKit())
return false;
QtSupport::QtVersion *version = QtSupport::QtKitAspect::qtVersion(k);
return (version && version->qtVersion().majorVersion() == qtMajorVersion);
});
if (!qtVersionkits.isEmpty()) {
if (qtVersionkits.contains(KitManager::defaultKit()))
addTargetForDefaultKit();
else
addTargetForKit(qtVersionkits.first());
}
};
int preferedVersion = preferedQtTarget(activeTarget());
if (activeTarget())
removeTarget(activeTarget());
setKitWithVersion(preferedVersion);
}
}
return RestoreResult::Ok;
}
bool QmlProject::isQtDesignStudio()
{
QSettings *settings = Core::ICore::settings();
const QString qdsStandaloneEntry = "QML/Designer/StandAloneMode";
return settings->value(qdsStandaloneEntry, false).toBool();
}
@@ -659,172 +210,30 @@ bool QmlProject::isQtDesignStudioStartedFromQtC()
return qEnvironmentVariableIsSet(Constants::enviromentLaunchedQDS);
}
ProjectExplorer::DeploymentKnowledge QmlProject::deploymentKnowledge() const
DeploymentKnowledge QmlProject::deploymentKnowledge() const
{
return DeploymentKnowledge::Perfect;
}
void QmlBuildSystem::generateProjectTree()
bool QmlProject::isEditModePreferred() const
{
if (!m_projectItem)
return;
auto newRoot = std::make_unique<QmlProjectNode>(project());
for (const QString &f : m_projectItem->files()) {
const Utils::FilePath fileName = Utils::FilePath::fromString(f);
const FileType fileType = (fileName == projectFilePath())
? FileType::Project : FileNode::fileTypeForFileName(fileName);
newRoot->addNestedNode(std::make_unique<FileNode>(fileName, fileType));
}
newRoot->addNestedNode(std::make_unique<FileNode>(projectFilePath(), FileType::Project));
setRootProjectNode(std::move(newRoot));
refreshTargetDirectory();
return !isQtDesignStudio();
}
void QmlBuildSystem::updateDeploymentData()
int QmlProject::preferedQtTarget(Target *target)
{
if (!m_projectItem)
return;
if (!target)
return -1;
if (DeviceTypeKitAspect::deviceTypeId(kit())
== ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
return;
}
ProjectExplorer::DeploymentData deploymentData;
for (const QString &file : m_projectItem->files()) {
deploymentData.addFile(
FilePath::fromString(file),
targetFile(Utils::FilePath::fromString(file)).parentDir().toString());
}
setDeploymentData(deploymentData);
auto buildSystem = qobject_cast<QmlBuildSystem *>(target->buildSystem());
return (buildSystem && buildSystem->qt6Project()) ? 6 : 5;
}
QVariant QmlBuildSystem::additionalData(Id id) const
bool QmlProject::allowOnlySingleProject()
{
if (id == Constants::customFileSelectorsData)
return customFileSelectors();
if (id == Constants::supportedLanguagesData)
return supportedLanguages();
if (id == Constants::primaryLanguageData)
return primaryLanguage();
if (id == Constants::customForceFreeTypeData)
return forceFreeType();
if (id == Constants::customQtForMCUs)
return qtForMCUs();
if (id == Constants::customQt6Project)
return qt6Project();
if (id == Constants::mainFilePath)
return mainFilePath().toString();
if (id == Constants::customImportPaths)
return customImportPaths();
if (id == Constants::canonicalProjectDir)
return canonicalProjectDir().toString();
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::forceFreeType() const
{
if (m_projectItem)
return m_projectItem->forceFreeType();
return false;
}
bool QmlBuildSystem::widgetApp() const
{
if (m_projectItem)
return m_projectItem->widgetApp();
return false;
}
QStringList QmlBuildSystem::shaderToolArgs() const
{
if (m_projectItem)
return m_projectItem->shaderToolArgs();
return {};
}
QStringList QmlBuildSystem::shaderToolFiles() const
{
if (m_projectItem)
return m_projectItem->shaderToolFiles();
return {};
}
QStringList QmlBuildSystem::importPaths() const
{
if (m_projectItem)
return m_projectItem->importPaths();
return {};
}
QStringList QmlBuildSystem::files() const
{
if (m_projectItem)
return m_projectItem->files();
return {};
}
bool QmlBuildSystem::addFiles(Node *context, const FilePaths &filePaths, FilePaths *)
{
if (!dynamic_cast<QmlProjectNode *>(context))
return false;
FilePaths toAdd;
for (const FilePath &filePath : filePaths) {
if (!m_projectItem->matchesFile(filePath.toString()))
toAdd << filePaths;
}
return toAdd.isEmpty();
}
bool QmlBuildSystem::deleteFiles(Node *context, const FilePaths &filePaths)
{
if (dynamic_cast<QmlProjectNode *>(context))
return true;
return BuildSystem::deleteFiles(context, filePaths);
}
bool QmlBuildSystem::renameFile(Node * context, const FilePath &oldFilePath, const FilePath &newFilePath)
{
if (dynamic_cast<QmlProjectNode *>(context)) {
if (oldFilePath.endsWith(mainFile().path()))
return setMainFileInProjectFile(newFilePath);
if (oldFilePath.endsWith(mainUiFile().path()))
return setMainUiFileInProjectFile(newFilePath);
return true;
}
return BuildSystem::renameFile(context, oldFilePath, newFilePath);
QSettings *settings = Core::ICore::settings();
auto key = "QML/Designer/AllowMultipleProjects";
return !settings->value(key, false).toBool();
}
} // namespace QmlProjectManager

View File

@@ -1,150 +1,31 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once
#include "buildsystem/qmlbuildsystem.h" // IWYU pragma: keep
#include "qmlprojectmanager_global.h"
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/project.h>
#include <utils/environment.h>
#include <QPointer>
namespace QmlProjectManager {
class QmlProject;
class QmlProjectItem;
class QMLPROJECTMANAGER_EXPORT QmlBuildSystem : public ProjectExplorer::BuildSystem
{
Q_OBJECT
public:
explicit QmlBuildSystem(ProjectExplorer::Target *target);
~QmlBuildSystem();
void triggerParsing() final;
bool supportsAction(ProjectExplorer::Node *context,
ProjectExplorer::ProjectAction action,
const ProjectExplorer::Node *node) const override;
bool addFiles(ProjectExplorer::Node *context,
const Utils::FilePaths &filePaths, Utils::FilePaths *notAdded = nullptr) override;
bool deleteFiles(ProjectExplorer::Node *context,
const Utils::FilePaths &filePaths) override;
bool renameFile(ProjectExplorer::Node *context,
const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) override;
QString name() const override { return QLatin1String("qml"); }
QmlProject *qmlProject() const;
QVariant additionalData(Utils::Id id) const override;
enum RefreshOption {
ProjectFile = 0x01,
Files = 0x02,
Configuration = 0x04,
Everything = ProjectFile | Files | Configuration
};
Q_DECLARE_FLAGS(RefreshOptions,RefreshOption)
void refresh(RefreshOptions options);
Utils::FilePath canonicalProjectDir() const;
Utils::FilePath mainFile() const;
Utils::FilePath 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;
void setMainFile(const QString &mainFilePath);
Utils::FilePath targetDirectory() const;
Utils::FilePath targetFile(const Utils::FilePath &sourceFile) const;
Utils::EnvironmentItems environment() const;
QStringList customImportPaths() const;
QStringList customFileSelectors() const;
bool multilanguageSupport() const;
QStringList supportedLanguages() const;
void setSupportedLanguages(QStringList languages);
QString primaryLanguage() const;
void setPrimaryLanguage(QString language);
bool forceFreeType() const;
bool widgetApp() const;
QStringList shaderToolArgs() const;
QStringList shaderToolFiles() const;
QStringList importPaths() const;
QStringList files() const;
bool addFiles(const QStringList &filePaths);
void refreshProjectFile();
static Utils::FilePath activeMainFilePath();
static QStringList makeAbsolute(const Utils::FilePath &path, const QStringList &relativePaths);
void generateProjectTree();
void updateDeploymentData();
void refreshFiles(const QSet<QString> &added, const QSet<QString> &removed);
void refreshTargetDirectory();
void onActiveTargetChanged(ProjectExplorer::Target *target);
void onKitChanged();
// plain format
void parseProject(RefreshOptions options);
signals:
void projectChanged();
private:
bool setFileSettingInProjectFile(const QString &setting,
const Utils::FilePath &mainFilePath,
const Utils::FilePath &oldFile);
std::unique_ptr<QmlProjectItem> m_projectItem;
Utils::FilePath m_canonicalProjectDir;
bool m_blockFilesUpdate = false;
friend class FilesUpdateBlocker;
};
class FilesUpdateBlocker {
public:
FilesUpdateBlocker(QmlBuildSystem* bs): m_bs(bs) {
if (m_bs)
m_bs->m_blockFilesUpdate = true;
}
~FilesUpdateBlocker() {
if (m_bs) {
m_bs->m_blockFilesUpdate = false;
m_bs->refresh(QmlBuildSystem::Everything);
}
}
private:
QPointer<QmlBuildSystem> m_bs;
};
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;
~QmlProject(){
qDebug() << "Closing the project";
};
static bool isQtDesignStudio();
static bool isQtDesignStudioStartedFromQtC();
bool isEditModePreferred() const override;
ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
@@ -153,9 +34,35 @@ private:
Utils::FilePaths collectUiQmlFilesForFolder(const Utils::FilePath &folder) const;
Utils::FilePaths collectQmlFiles() const;
QMetaObject::Connection m_openFileConnection;
bool setKitWithVersion(const int qtMajorVersion, const QList<ProjectExplorer::Kit *> kits);
bool allowOnlySingleProject();
int preferedQtTarget(ProjectExplorer::Target *target);
private slots:
void parsingFinished(const ProjectExplorer::Target *target, bool success);
};
class FilesUpdateBlocker
{
public:
FilesUpdateBlocker(QmlBuildSystem *bs)
: m_bs(bs)
{
if (m_bs)
m_bs->m_blockFilesUpdate = true;
}
~FilesUpdateBlocker()
{
if (m_bs) {
m_bs->m_blockFilesUpdate = false;
m_bs->refresh(QmlBuildSystem::RefreshOptions::Project);
}
}
private:
QPointer<QmlBuildSystem> m_bs;
};
} // namespace QmlProjectManager
Q_DECLARE_OPERATORS_FOR_FLAGS(QmlProjectManager::QmlBuildSystem::RefreshOptions)

View File

@@ -33,12 +33,14 @@ QtcPlugin {
}
Group {
name: "File Format"
prefix: "fileformat/"
name: "Build System"
prefix: "buildsystem/"
files: [
"filefilteritems.cpp", "filefilteritems.h",
"qmlprojectfileformat.cpp", "qmlprojectfileformat.h",
"qmlprojectitem.cpp", "qmlprojectitem.h",
"qmlbuildsystem.cpp", "qmlbuildsystem.h",
"projectitem/filefilteritems.cpp", "projectitem/filefilteritems.h",
"projectitem/qmlprojectitem.cpp", "projectitem/qmlprojectitem.h",
"projectitem/converters.h",
"projectnode/qmlprojectnodes.cpp", "projectnode/qmlprojectnodes.h"
]
}

View File

@@ -10,7 +10,6 @@
#include "projectfilecontenttools.h"
#include "cmakegen/cmakeprojectconverter.h"
#include "cmakegen/generatecmakelists.h"
#include "qmlprojectgen/qmlprojectgenerator.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>

View File

@@ -1 +1,2 @@
add_subdirectory(fileformat)
add_subdirectory(projectitem)

View File

@@ -9,11 +9,12 @@ foreach(source IN LISTS QmlProjectManagerSources)
endif()
endforeach()
add_qtc_test(tst_qml_fileformat
DEPENDS QmlJS Utils
INCLUDES "${PROJECT_SOURCE_DIR}/src/plugins/qmlprojectmanager/fileformat"
DEFINES
QT_CREATOR
SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
SOURCES tst_fileformat.cpp ${fileformat_sources}
)
#add_qtc_test(tst_qml_fileformat
# DEPENDS QmlJS Utils
# INCLUDES "${PROJECT_SOURCE_DIR}/src/plugins/qmlprojectmanager/fileformat"
# DEFINES
# QT_CREATOR
# SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
# SOURCES tst_fileformat.cpp ${fileformat_sources}
#)

View File

@@ -0,0 +1,25 @@
set(WITH_TESTS ON)
find_package(Googletest MODULE)
set(QmlProjectItemDir "${PROJECT_SOURCE_DIR}/src/plugins/qmlprojectmanager/buildsystem/projectitem")
add_qtc_test(tst_qml_projectitem
DEPENDS QmlProjectManager Utils QmlJS Googletest
INCLUDES "${QmlProjectItemDir}"
DEFINES
QT_CREATOR
SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}"
TESTDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
TESTS_ENABLED_QMLPROJECTITEM
SOURCES
tst_projectitem.cpp
test-getters.cpp
test-setters.cpp
test-converters.cpp
test-filefilters.cpp
common.h
"${QmlProjectItemDir}/qmlprojectitem.cpp"
"${QmlProjectItemDir}/converters.cpp"
"${QmlProjectItemDir}/filefilteritems.cpp"
)

View File

@@ -0,0 +1,46 @@
# QmlProject ProjectItem Tests
## Content
This test bundle covers following functionalities of QmlProjectItem class;
* **Getter Functions**: Tests if getter functions are returning correct types with correct values
* **Setter Functions**: Tests if setter functions are updating the internal JSON object as expected
* **Converter Functions:** Tests if QmlProjectToJson and JsonToQmlProject functions are working as expected
* **File Filter Functions:** Tests if file filters are initialized properly
## Data set folder structure
The current folder hierarchy is as following;
```text
| data
| -> converter
| | -> test-set-1
| | | -> testfile.qmlproject
| | | -> testfile.qmltojson
| | | -> testfile.jsontoqml
| | -> test-set-2
| | | -> testfile.qmlproject
| | | -> testfile.qmltojson
| | | -> testfile.jsontoqml
| | -> test-set-..
| | -> test-set-..
| -> getter-setter
| | -> testfile-1.qmlproject
| | -> testfile-2.qmlproject
| -> file-filters
| | -> test-set-1
| | -> test-set-...
```
## Further information
Please see [data/README.md](data/README.md) for more information on the test set content.
## Contribution
Please update;
* This README whenever you change the test content
* [data/README.md](data/README.md) whenever you update the `data` folder

View File

@@ -0,0 +1,20 @@
// 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
#pragma once
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <gtest/gtest-matchers.h>
#include <gtest/gtest.h>
#include <QDir>
static QDir testDataRootDir(QLatin1String(TESTDATA_DIR));
inline void PrintTo(const QString &qString, ::std::ostream *os)
{
*os << qUtf8Printable(qString);
}

View File

@@ -0,0 +1,47 @@
# Test Set Information
This document contains information about the purpose of each test sets.
## Getter/Setter test data
* **testfile-1.qmlproject**: QmlProject file with properly filled out object
* **testfile-2.qmlproject**: QmlProject file with empty objects
## Converter test data
Test functions iterate over the "test-set-*" folders and run the tests by using the files inside them.
* **testfile.qmlproject**: Original QmlProject file that'll be converted
* **testfile.qmltojson**: JSON-converted version of the .qmlproject file
* **testfile.jsontoqml**: QmlProject-converted version of the .qmltojson file
### test-set-1
* **purpose**: testing complex qmlproject file convertion
* **origin**: custom project
### test-set-2
* **purpose**: testing complex qmlproject file convertion
* **origin**: material bundle example
### test-set-3
* **purpose**: testing complex qmlproject file convertion
* **origin**: robot arm example
### test-set-4
* **purpose**: testing complex qmlproject file convertion
* **origin**: outrun hvac example
### test-set-5
* **purpose**: testing fileselectors
* **origin**: file selectors example from playground
## File Filters test data
Test data contains an example project folders that file filters will be initialized and tested.
* **filelist.txt**: List of the files need to be found by the file filters.

View File

@@ -0,0 +1,98 @@
\\ prop: json-converted
\\ prop: auto-generated
import QmlProject
Project {
mainFile: "content/App.qml"
mainUiFile: "content/Screen01.ui.qml"
targetDirectory: "/opt/UntitledProject13"
widgetApp: true
importPaths: [ "imports","asset_imports" ]
qdsVersion: "4.0"
quickVersion: "6.2"
qt6Project: true
qtForMCUs: true
multilanguageSupport: true
primaryLanguage: "en"
supportedLanguages: [ "en" ]
Environment {
QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT: "1"
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QT_ENABLE_HIGHDPI_SCALING: "0"
QT_LOGGING_RULES: "qt.qml.connections=false"
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
}
ShaderTool {
args: "-s --glsl "100 es,120,150" --hlsl 50 --msl 12"
files: [ "content/shaders/*" ]
}
QmlFiles {
directory: "content"
}
QmlFiles {
directory: "imports"
}
QmlFiles {
directory: "asset_imports"
}
JavaScriptFiles {
directory: "content"
}
JavaScriptFiles {
directory: "imports"
}
ImageFiles {
directory: "content"
}
ImageFiles {
directory: "asset_imports"
}
Files {
directory: "."
filters: "*.conf"
files: [ "qtquickcontrols2.conf" ]
}
Files {
directory: "."
filters: "*.ttf;*.otf;*.ctf"
}
Files {
directory: "asset_imports"
filters: "*.mesh"
}
Files {
directory: "."
filters: "qmldir"
}
Files {
directory: "."
filters: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag;*.trag"
}
Files {
directory: "."
filters: "*.mp3;*.wav"
}
Files {
directory: "."
filters: "*.mp4"
}
}

View File

@@ -0,0 +1,110 @@
import QmlProject
Project {
mainFile: "content/App.qml"
mainUiFile: "content/Screen01.ui.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "content"
}
QmlFiles {
directory: "imports"
}
JavaScriptFiles {
directory: "content"
}
JavaScriptFiles {
directory: "imports"
}
ImageFiles {
directory: "content"
}
ImageFiles {
directory: "asset_imports"
}
Files {
filter: "*.conf"
files: ["qtquickcontrols2.conf"]
}
Files {
filter: "qmldir"
directory: "."
}
Files {
filter: "*.ttf;*.otf;*.ctf"
}
Files {
filter: "*.wav;*.mp3"
}
Files {
filter: "*.mp4"
}
Files {
filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag;*.trag"
}
Files {
filter: "*.mesh"
directory: "asset_imports"
}
Files {
filter: "*.qml"
directory: "asset_imports"
}
Environment {
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT: "1"
QT_LOGGING_RULES: "qt.qml.connections=false"
QT_ENABLE_HIGHDPI_SCALING: "0"
/* Useful for debugging
QSG_VISUALIZE=batches
QSG_VISUALIZE=clip
QSG_VISUALIZE=changes
QSG_VISUALIZE=overdraw
*/
}
qt6Project: true
/* List of plugin directories passed to QML runtime */
importPaths: [ "imports", "asset_imports" ]
/* Required for deployment */
targetDirectory: "/opt/UntitledProject13"
qdsVersion: "4.0"
quickVersion: "6.2"
/* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */
widgetApp: true
/* args: Specifies command line arguments for qsb tool to generate shaders.
files: Specifies target files for qsb tool. If path is included, it must be relative to this file.
Wildcard '*' can be used in the file name part of the path.
e.g. files: [ "content/shaders/*.vert", "*.frag" ] */
ShaderTool {
args: "-s --glsl \"100 es,120,150\" --hlsl 50 --msl 12"
files: [ "content/shaders/*" ]
}
multilanguageSupport: true
supportedLanguages: ["en"]
primaryLanguage: "en"
}

View File

@@ -0,0 +1,176 @@
{
"deployment": {
"targetDirectory": "/opt/UntitledProject13"
},
"environment": {
"QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT": "1",
"QT_AUTO_SCREEN_SCALE_FACTOR": "1",
"QT_ENABLE_HIGHDPI_SCALING": "0",
"QT_LOGGING_RULES": "qt.qml.connections=false",
"QT_QUICK_CONTROLS_CONF": "qtquickcontrols2.conf"
},
"fileGroups": {
"config": {
"directories": [
"."
],
"files": [
{
"name": "qtquickcontrols2.conf"
}
],
"filters": [
"*.conf"
]
},
"font": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.ttf",
"*.otf",
"*.ctf"
]
},
"image": {
"directories": [
"content",
"asset_imports"
],
"files": [
],
"filters": [
"*.jpeg",
"*.jpg",
"*.png",
"*.svg",
"*.hdr",
".ktx"
]
},
"javaScript": {
"directories": [
"content",
"imports"
],
"files": [
],
"filters": [
"*.js",
"*.ts"
]
},
"meshes": {
"directories": [
"asset_imports"
],
"files": [
],
"filters": [
"*.mesh"
]
},
"qml": {
"directories": [
"content",
"imports",
"asset_imports"
],
"files": [
],
"filters": [
"*.qml"
]
},
"qmldir": {
"directories": [
"."
],
"files": [
],
"filters": [
"qmldir"
]
},
"shader": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.glsl",
"*.glslv",
"*.glslf",
"*.vsh",
"*.fsh",
"*.vert",
"*.frag",
"*.trag"
]
},
"sound": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.mp3",
"*.wav"
]
},
"video": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.mp4"
]
}
},
"fileVersion": 1,
"importPaths": [
"imports",
"asset_imports"
],
"language": {
"multiLanguageSupport": true,
"primaryLanguage": "en",
"supportedLanguages": [
"en"
]
},
"mcuConfig": {
},
"runConfig": {
"fileSelectors": [
],
"mainFile": "content/App.qml",
"mainUiFile": "content/Screen01.ui.qml",
"widgetApp": true
},
"shaderTool": {
"args": [
"-s",
"--glsl",
"\"100 es,120,150\"",
"--hlsl",
"50",
"--msl",
"12"
],
"files": [
"content/shaders/*"
]
},
"versions": {
"designStudio": "4.0",
"qtQuick": "6.2"
}
}

View File

@@ -0,0 +1,102 @@
\\ prop: json-converted
\\ prop: auto-generated
import QmlProject
Project {
mainFile: "content/App.qml"
mainUiFile: "Screen01.ui.qml"
targetDirectory: "/opt/MaterialLibrary"
widgetApp: true
importPaths: [ "imports","asset_imports" ]
qdsVersion: "3.9"
quickVersion: ""
qt6Project: false
qtForMCUs: true
multilanguageSupport: true
primaryLanguage: "en"
supportedLanguages: [ "en" ]
Environment {
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QT_ENABLE_HIGHDPI_SCALING: "0"
QT_LOGGING_RULES: "qt.qml.connections=false"
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
}
ShaderTool {
args: "-s --glsl "100 es,120,150" --hlsl 50 --msl 12"
files: [ "content/shaders/*" ]
}
QmlFiles {
directory: "content"
}
QmlFiles {
directory: "imports"
}
QmlFiles {
directory: "asset_imports"
}
JavaScriptFiles {
directory: "content"
}
JavaScriptFiles {
directory: "imports"
}
ImageFiles {
directory: "content"
}
ImageFiles {
directory: "asset_imports"
}
Files {
directory: "."
filters: "*.conf"
files: [ "qtquickcontrols2.conf" ]
}
Files {
directory: "."
filters: "*.ttf;*.otf"
}
Files {
directory: "asset_imports"
filters: "*.mesh"
}
Files {
directory: "content"
filters: "*.mesh"
}
Files {
directory: "."
filters: "qmldir"
}
Files {
directory: "."
filters: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag"
}
Files {
directory: "."
filters: "*.mp3;*.wav"
}
Files {
directory: "."
filters: "*.mp4"
}
}

View File

@@ -0,0 +1,112 @@
import QmlProject
Project {
mainFile: "content/App.qml"
mainUiFile: "Screen01.ui.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "content"
}
QmlFiles {
directory: "imports"
}
JavaScriptFiles {
directory: "content"
}
JavaScriptFiles {
directory: "imports"
}
ImageFiles {
directory: "content"
}
Files {
filter: "*.conf"
files: ["qtquickcontrols2.conf"]
}
Files {
filter: "qmldir"
directory: "."
}
Files {
filter: "*.ttf;*.otf"
}
Files {
filter: "*.wav;*.mp3"
}
Files {
filter: "*.mp4"
}
Files {
filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag"
}
Files {
filter: "*.mesh"
directory: "asset_imports"
}
Files {
filter: "*.mesh"
directory: "content"
}
Files {
filter: "*.qml"
directory: "asset_imports"
}
ImageFiles {
directory: "asset_imports"
}
Environment {
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QT_LOGGING_RULES: "qt.qml.connections=false"
QT_ENABLE_HIGHDPI_SCALING: "0"
/* Useful for debugging
QSG_VISUALIZE=batches
QSG_VISUALIZE=clip
QSG_VISUALIZE=changes
QSG_VISUALIZE=overdraw
*/
}
qt6Project: true
/* List of plugin directories passed to QML runtime */
importPaths: [ "imports", "asset_imports" ]
/* Required for deployment */
targetDirectory: "/opt/MaterialLibrary"
qdsVersion: "3.9"
/* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */
widgetApp: true
/* args: Specifies command line arguments for qsb tool to generate shaders.
files: Specifies target files for qsb tool. If path is included, it must be relative to this file.
Wildcard '*' can be used in the file name part of the path.
e.g. files: [ "content/shaders/*.vert", "*.frag" ] */
ShaderTool {
args: "-s --glsl \"100 es,120,150\" --hlsl 50 --msl 12"
files: [ "content/shaders/*" ]
}
multilanguageSupport: true
supportedLanguages: ["en"]
primaryLanguage: "en"
}

View File

@@ -0,0 +1,173 @@
{
"deployment": {
"targetDirectory": "/opt/MaterialLibrary"
},
"environment": {
"QT_AUTO_SCREEN_SCALE_FACTOR": "1",
"QT_ENABLE_HIGHDPI_SCALING": "0",
"QT_LOGGING_RULES": "qt.qml.connections=false",
"QT_QUICK_CONTROLS_CONF": "qtquickcontrols2.conf"
},
"fileGroups": {
"config": {
"directories": [
"."
],
"files": [
{
"name": "qtquickcontrols2.conf"
}
],
"filters": [
"*.conf"
]
},
"font": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.ttf",
"*.otf"
]
},
"image": {
"directories": [
"content",
"asset_imports"
],
"files": [
],
"filters": [
"*.jpeg",
"*.jpg",
"*.png",
"*.svg",
"*.hdr",
".ktx"
]
},
"javaScript": {
"directories": [
"content",
"imports"
],
"files": [
],
"filters": [
"*.js",
"*.ts"
]
},
"meshes": {
"directories": [
"asset_imports",
"content"
],
"files": [
],
"filters": [
"*.mesh"
]
},
"qml": {
"directories": [
"content",
"imports",
"asset_imports"
],
"files": [
],
"filters": [
"*.qml"
]
},
"qmldir": {
"directories": [
"."
],
"files": [
],
"filters": [
"qmldir"
]
},
"shader": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.glsl",
"*.glslv",
"*.glslf",
"*.vsh",
"*.fsh",
"*.vert",
"*.frag"
]
},
"sound": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.mp3",
"*.wav"
]
},
"video": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.mp4"
]
}
},
"fileVersion": 1,
"importPaths": [
"imports",
"asset_imports"
],
"language": {
"multiLanguageSupport": true,
"primaryLanguage": "en",
"supportedLanguages": [
"en"
]
},
"mcuConfig": {
},
"runConfig": {
"fileSelectors": [
],
"mainFile": "content/App.qml",
"mainUiFile": "Screen01.ui.qml",
"widgetApp": true
},
"shaderTool": {
"args": [
"-s",
"--glsl",
"\"100 es,120,150\"",
"--hlsl",
"50",
"--msl",
"12"
],
"files": [
"content/shaders/*"
]
},
"versions": {
"designStudio": "3.9"
}
}

View File

@@ -0,0 +1,93 @@
\\ prop: json-converted
\\ prop: auto-generated
import QmlProject
Project {
mainFile: "content/App.qml"
mainUiFile: "content/MainScreen.ui.qml"
targetDirectory: "/opt/RobotArm"
widgetApp: true
importPaths: [ "imports","asset_imports","backend_mock" ]
qdsVersion: "3.0"
quickVersion: ""
qt6Project: false
qtForMCUs: true
multilanguageSupport: true
primaryLanguage: "en"
supportedLanguages: [ "en" ]
Environment {
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QT_ENABLE_HIGHDPI_SCALING: "0"
QT_LOGGING_RULES: "qt.qml.connections=false"
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
}
ShaderTool {
args: ""
files: [ ]
}
QmlFiles {
directory: "content"
}
QmlFiles {
directory: "imports"
}
QmlFiles {
directory: "backend_mock"
}
JavaScriptFiles {
directory: "content"
}
JavaScriptFiles {
directory: "imports"
}
ImageFiles {
directory: "content"
}
Files {
directory: "."
filters: "*.conf"
files: [ "qtquickcontrols2.conf" ]
}
Files {
directory: "."
filters: "*.ttf;*.otf"
}
Files {
directory: "content"
filters: "*.mesh"
}
Files {
directory: "."
filters: "qmldir"
}
Files {
directory: "."
filters: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag"
}
Files {
directory: "."
filters: "*.mp3;*.wav"
}
Files {
directory: "."
filters: "*.mp4"
}
}

View File

@@ -0,0 +1,93 @@
import QmlProject
Project {
mainFile: "content/App.qml"
mainUiFile: "content/MainScreen.ui.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "content"
}
QmlFiles {
directory: "imports"
}
QmlFiles {
directory: "backend_mock"
}
JavaScriptFiles {
directory: "content"
}
JavaScriptFiles {
directory: "imports"
}
ImageFiles {
directory: "content"
}
Files {
filter: "*.conf"
files: ["qtquickcontrols2.conf"]
}
Files {
filter: "qmldir"
directory: "."
}
Files {
filter: "*.ttf;*.otf"
}
Files {
filter: "*.wav;*.mp3"
}
Files {
filter: "*.mp4"
}
Files {
filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag"
}
Files {
filter: "*.mesh"
directory: "content"
}
Environment {
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QT_LOGGING_RULES: "qt.qml.connections=false"
QT_ENABLE_HIGHDPI_SCALING: "0"
/* Useful for debugging
QSG_VISUALIZE=batches
QSG_VISUALIZE=clip
QSG_VISUALIZE=changes
QSG_VISUALIZE=overdraw
*/
}
qt6Project: true
/* List of plugin directories passed to QML runtime */
importPaths: [ "imports", "asset_imports", "backend_mock" ]
/* Required for deployment */
targetDirectory: "/opt/RobotArm"
qdsVersion: "3.0"
/* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */
widgetApp: true
multilanguageSupport: true
supportedLanguages: ["en"]
primaryLanguage: "en"
}

View File

@@ -0,0 +1,160 @@
{
"deployment": {
"targetDirectory": "/opt/RobotArm"
},
"environment": {
"QT_AUTO_SCREEN_SCALE_FACTOR": "1",
"QT_ENABLE_HIGHDPI_SCALING": "0",
"QT_LOGGING_RULES": "qt.qml.connections=false",
"QT_QUICK_CONTROLS_CONF": "qtquickcontrols2.conf"
},
"fileGroups": {
"config": {
"directories": [
"."
],
"files": [
{
"name": "qtquickcontrols2.conf"
}
],
"filters": [
"*.conf"
]
},
"font": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.ttf",
"*.otf"
]
},
"image": {
"directories": [
"content"
],
"files": [
],
"filters": [
"*.jpeg",
"*.jpg",
"*.png",
"*.svg",
"*.hdr",
".ktx"
]
},
"javaScript": {
"directories": [
"content",
"imports"
],
"files": [
],
"filters": [
"*.js",
"*.ts"
]
},
"meshes": {
"directories": [
"content"
],
"files": [
],
"filters": [
"*.mesh"
]
},
"qml": {
"directories": [
"content",
"imports",
"backend_mock"
],
"files": [
],
"filters": [
"*.qml"
]
},
"qmldir": {
"directories": [
"."
],
"files": [
],
"filters": [
"qmldir"
]
},
"shader": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.glsl",
"*.glslv",
"*.glslf",
"*.vsh",
"*.fsh",
"*.vert",
"*.frag"
]
},
"sound": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.mp3",
"*.wav"
]
},
"video": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.mp4"
]
}
},
"fileVersion": 1,
"importPaths": [
"imports",
"asset_imports",
"backend_mock"
],
"language": {
"multiLanguageSupport": true,
"primaryLanguage": "en",
"supportedLanguages": [
"en"
]
},
"mcuConfig": {
},
"runConfig": {
"fileSelectors": [
],
"mainFile": "content/App.qml",
"mainUiFile": "content/MainScreen.ui.qml",
"widgetApp": true
},
"shaderTool": {
},
"versions": {
"designStudio": "3.0"
}
}

View File

@@ -0,0 +1,65 @@
\\ prop: json-converted
\\ prop: auto-generated
import QmlProject
Project {
mainFile: "OutrunHVAC.qml"
mainUiFile: "Screen01.ui.qml"
targetDirectory: "/opt/OutrunHVAC"
widgetApp: false
importPaths: [ "imports","asset_imports" ]
qdsVersion: ""
quickVersion: ""
qt6Project: false
qtForMCUs: true
multilanguageSupport: false
primaryLanguage: ""
supportedLanguages: [ ]
Environment {
QMLSCENE_CORE_PROFILE: "true"
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
}
ShaderTool {
args: ""
files: [ ]
}
QmlFiles {
directory: "."
}
JavaScriptFiles {
directory: "."
}
ImageFiles {
directory: "."
}
Files {
directory: "."
filters: "*.conf"
files: [ "qtquickcontrols2.conf" ]
}
Files {
directory: "."
filters: "*.ttf;*.otf"
}
Files {
directory: "."
filters: "*.mesh;*.vert;*.frag"
}
Files {
directory: "."
filters: "qmldir"
}
}

View File

@@ -0,0 +1,55 @@
/* File generated by Qt Creator */
import QmlProject 1.1
Project {
mainFile: "OutrunHVAC.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "."
}
JavaScriptFiles {
directory: "."
}
ImageFiles {
directory: "."
}
Files {
filter: "*.conf"
files: ["qtquickcontrols2.conf"]
}
Files {
filter: "qmldir"
directory: "."
}
Files {
filter: "*.ttf;*.otf"
}
Files {
filter: "*.mesh;*.vert;*.frag"
directory: "."
}
Environment {
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QMLSCENE_CORE_PROFILE: "true"
}
qt6Project: true
/* List of plugin directories passed to QML runtime */
importPaths: [ "imports", "asset_imports" ]
/* Required for deployment */
targetDirectory: "/opt/OutrunHVAC"
mainUiFile: "Screen01.ui.qml"
}

View File

@@ -0,0 +1,113 @@
{
"deployment": {
"targetDirectory": "/opt/OutrunHVAC"
},
"environment": {
"QMLSCENE_CORE_PROFILE": "true",
"QT_AUTO_SCREEN_SCALE_FACTOR": "1",
"QT_QUICK_CONTROLS_CONF": "qtquickcontrols2.conf"
},
"fileGroups": {
"config": {
"directories": [
"."
],
"files": [
{
"name": "qtquickcontrols2.conf"
}
],
"filters": [
"*.conf"
]
},
"font": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.ttf",
"*.otf"
]
},
"image": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.jpeg",
"*.jpg",
"*.png",
"*.svg",
"*.hdr",
".ktx"
]
},
"javaScript": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.js",
"*.ts"
]
},
"meshes": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.mesh",
"*.vert",
"*.frag"
]
},
"qml": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.qml"
]
},
"qmldir": {
"directories": [
"."
],
"files": [
],
"filters": [
"qmldir"
]
}
},
"fileVersion": 1,
"importPaths": [
"imports",
"asset_imports"
],
"language": {
},
"mcuConfig": {
},
"runConfig": {
"fileSelectors": [
],
"mainFile": "OutrunHVAC.qml",
"mainUiFile": "Screen01.ui.qml"
},
"shaderTool": {
},
"versions": {
}
}

View File

@@ -0,0 +1,54 @@
\\ prop: json-converted
\\ prop: auto-generated
import QmlProject
Project {
mainFile: "fileSelectors.qml"
mainUiFile: ""
targetDirectory: "/opt/fileSelectors"
widgetApp: false
importPaths: [ "imports" ]
qdsVersion: ""
quickVersion: ""
qt6Project: false
qtForMCUs: true
multilanguageSupport: false
primaryLanguage: ""
supportedLanguages: [ ]
Environment {
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
}
ShaderTool {
args: ""
files: [ ]
}
QmlFiles {
directory: "."
}
JavaScriptFiles {
directory: "."
}
ImageFiles {
directory: "."
}
Files {
directory: "."
filters: "*.conf"
files: [ "qtquickcontrols2.conf" ]
}
Files {
directory: "."
filters: "qmldir"
}
}

View File

@@ -0,0 +1,44 @@
/* File generated by Qt Creator */
import QmlProject 1.1
Project {
mainFile: "fileSelectors.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "."
}
JavaScriptFiles {
directory: "."
}
ImageFiles {
directory: "."
}
Files {
filter: "*.conf"
files: ["qtquickcontrols2.conf"]
}
Files {
filter: "qmldir"
directory: "."
}
Environment {
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
}
/* List of plugin directories passed to QML runtime */
importPaths: [ "imports" ]
//fileSelectors: [ "WXGA", "darkTheme" ]
fileSelectors: [ "WXGA", "darkTheme", "ShowIndicator"]
/* Required for deployment */
targetDirectory: "/opt/fileSelectors"
}

View File

@@ -0,0 +1,90 @@
{
"deployment": {
"targetDirectory": "/opt/fileSelectors"
},
"environment": {
"QT_AUTO_SCREEN_SCALE_FACTOR": "1",
"QT_QUICK_CONTROLS_CONF": "qtquickcontrols2.conf"
},
"fileGroups": {
"config": {
"directories": [
"."
],
"files": [
{
"name": "qtquickcontrols2.conf"
}
],
"filters": [
"*.conf"
]
},
"image": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.jpeg",
"*.jpg",
"*.png",
"*.svg",
"*.hdr",
".ktx"
]
},
"javaScript": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.js",
"*.ts"
]
},
"qml": {
"directories": [
"."
],
"files": [
],
"filters": [
"*.qml"
]
},
"qmldir": {
"directories": [
"."
],
"files": [
],
"filters": [
"qmldir"
]
}
},
"fileVersion": 1,
"importPaths": [
"imports"
],
"language": {
},
"mcuConfig": {
},
"runConfig": {
"fileSelectors": [
"WXGA",
"darkTheme",
"ShowIndicator"
],
"mainFile": "fileSelectors.qml"
},
"shaderTool": {
},
"versions": {
}
}

View File

@@ -0,0 +1,112 @@
import QmlProject
Project {
mainFile: "content/App.qml"
mainUiFile: "Screen01.ui.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "content"
}
QmlFiles {
directory: "imports"
}
JavaScriptFiles {
directory: "content"
}
JavaScriptFiles {
directory: "imports"
}
ImageFiles {
directory: "content"
}
Files {
filter: "*.conf"
files: ["qtquickcontrols2.conf"]
}
Files {
filter: "qmldir"
directory: "."
}
Files {
filter: "*.ttf;*.otf"
}
Files {
filter: "*.wav;*.mp3"
}
Files {
filter: "*.mp4"
}
Files {
filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag"
}
Files {
filter: "*.mesh"
directory: "asset_imports"
}
Files {
filter: "*.mesh"
directory: "content"
}
Files {
filter: "*.qml"
directory: "asset_imports"
}
ImageFiles {
directory: "asset_imports"
}
Environment {
QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf"
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
QT_LOGGING_RULES: "qt.qml.connections=false"
QT_ENABLE_HIGHDPI_SCALING: "0"
/* Useful for debugging
QSG_VISUALIZE=batches
QSG_VISUALIZE=clip
QSG_VISUALIZE=changes
QSG_VISUALIZE=overdraw
*/
}
qt6Project: true
/* List of plugin directories passed to QML runtime */
importPaths: [ "imports", "asset_imports" ]
/* Required for deployment */
targetDirectory: "/opt/MaterialLibrary"
qdsVersion: "3.9"
/* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */
widgetApp: true
/* args: Specifies command line arguments for qsb tool to generate shaders.
files: Specifies target files for qsb tool. If path is included, it must be relative to this file.
Wildcard '*' can be used in the file name part of the path.
e.g. files: [ "content/shaders/*.vert", "*.frag" ] */
ShaderTool {
args: "-s --glsl \"100 es,120,150\" --hlsl 50 --msl 12"
files: [ "content/shaders/*" ]
}
multilanguageSupport: true
supportedLanguages: ["en"]
primaryLanguage: "en"
}

Some files were not shown because too many files have changed in this diff Show More