Merge remote-tracking branch 'origin/8.0'

Conflicts:
	.github/workflows/build_cmake.yml
	src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
	src/plugins/qmldesigner/components/materialeditor/materialeditorview.h
	src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp
	src/plugins/qmldesigner/designercore/model/model.cpp

Change-Id: I111b9140375b894a5487cc012b17cc32100bdb8d
This commit is contained in:
Eike Ziller
2022-09-13 11:15:16 +02:00
73 changed files with 2547 additions and 212 deletions

View File

@@ -5,12 +5,14 @@
#include "materialeditorqmlbackend.h"
#include "materialeditorcontextobject.h"
#include "materialeditordynamicpropertiesproxymodel.h"
#include "propertyeditorvalue.h"
#include "materialeditortransaction.h"
#include "assetslibrarywidget.h"
#include <auxiliarydataproperties.h>
#include <bindingproperty.h>
#include <dynamicpropertiesmodel.h>
#include <metainfo.h>
#include <nodeinstanceview.h>
#include <nodelistproperty.h>
@@ -49,6 +51,7 @@ namespace QmlDesigner {
MaterialEditorView::MaterialEditorView(QWidget *parent)
: AbstractView(parent)
, m_stackedWidget(new QStackedWidget(parent))
, m_dynamicPropertiesModel(new Internal::DynamicPropertiesModel(true, this))
{
m_updateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F7), m_stackedWidget);
connect(m_updateShortcut, &QShortcut::activated, this, &MaterialEditorView::reloadQml);
@@ -71,6 +74,8 @@ MaterialEditorView::MaterialEditorView(QWidget *parent)
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
m_stackedWidget->setMinimumWidth(250);
QmlDesignerPlugin::trackWidgetFocusTime(m_stackedWidget, Constants::EVENT_MATERIALEDITOR_TIME);
MaterialEditorDynamicPropertiesProxyModel::registerDeclarativeType();
}
MaterialEditorView::~MaterialEditorView()
@@ -294,6 +299,29 @@ void MaterialEditorView::currentTimelineChanged(const ModelNode &)
m_qmlBackEnd->contextObject()->setHasActiveTimeline(QmlTimeline::hasActiveTimeline(this));
}
Internal::DynamicPropertiesModel *MaterialEditorView::dynamicPropertiesModel() const
{
return m_dynamicPropertiesModel;
}
MaterialEditorView *MaterialEditorView::instance()
{
static MaterialEditorView *s_instance = nullptr;
if (s_instance)
return s_instance;
const auto views = QmlDesignerPlugin::instance()->viewManager().views();
for (auto *view : views) {
MaterialEditorView *myView = qobject_cast<MaterialEditorView *>(view);
if (myView)
s_instance = myView;
}
QTC_ASSERT(s_instance, return nullptr);
return s_instance;
}
void MaterialEditorView::delayedResetView()
{
// TODO: it seems the delayed reset is not needed. Leaving it commented out for now just in case it
@@ -575,6 +603,11 @@ void MaterialEditorView::setupQmlBackend()
m_qmlBackEnd = currentQmlBackend;
if (m_hasMaterialRoot)
m_dynamicPropertiesModel->setSelectedNode(m_selectedMaterial);
else
m_dynamicPropertiesModel->reset();
delayedTypeUpdate();
initPreviewData();
@@ -746,6 +779,7 @@ void MaterialEditorView::modelAttached(Model *model)
void MaterialEditorView::modelAboutToBeDetached(Model *model)
{
AbstractView::modelAboutToBeDetached(model);
m_dynamicPropertiesModel->reset();
m_qmlBackEnd->materialEditorTransaction()->end();
}
@@ -778,8 +812,9 @@ void MaterialEditorView::variantPropertiesChanged(const QList<VariantProperty> &
bool changed = false;
for (const VariantProperty &property : propertyList) {
ModelNode node(property.parentModelNode());
if (node == m_selectedMaterial || QmlObjectNode(m_selectedMaterial).propertyChangeForCurrentState() == node) {
if (property.isDynamic())
m_dynamicPropertiesModel->variantPropertyChanged(property);
if (m_selectedMaterial.property(property.name()).isBindingProperty())
setValue(m_selectedMaterial, property.name(), QmlObjectNode(m_selectedMaterial).instanceValue(property.name()));
else
@@ -805,6 +840,8 @@ void MaterialEditorView::bindingPropertiesChanged(const QList<BindingProperty> &
m_qmlBackEnd->contextObject()->setHasAliasExport(QmlObjectNode(m_selectedMaterial).isAliasExported());
if (node == m_selectedMaterial || QmlObjectNode(m_selectedMaterial).propertyChangeForCurrentState() == node) {
if (property.isDynamic())
m_dynamicPropertiesModel->bindingPropertyChanged(property);
if (QmlObjectNode(m_selectedMaterial).modelNode().property(property.name()).isBindingProperty())
setValue(m_selectedMaterial, property.name(), QmlObjectNode(m_selectedMaterial).instanceValue(property.name()));
else
@@ -828,6 +865,16 @@ void MaterialEditorView::auxiliaryDataChanged(const ModelNode &node,
m_qmlBackEnd->setValueforAuxiliaryProperties(m_selectedMaterial, key);
}
void MaterialEditorView::propertiesAboutToBeRemoved(const QList<AbstractProperty> &propertyList)
{
for (const auto &property : propertyList) {
if (property.isBindingProperty())
m_dynamicPropertiesModel->bindingRemoved(property.toBindingProperty());
else if (property.isVariantProperty())
m_dynamicPropertiesModel->variantRemoved(property.toVariantProperty());
}
}
// request render image for the selected material node
void MaterialEditorView::requestPreviewRender()
{
@@ -936,7 +983,7 @@ void MaterialEditorView::renameMaterial(ModelNode &material, const QString &newN
QTC_ASSERT(material.isValid(), return);
executeInTransaction("MaterialEditorView:renameMaterial", [&] {
material.setIdWithRefactoring(generateIdFromName(newName));
material.setIdWithRefactoring(model()->generateIdFromName(newName, "material"));
VariantProperty objNameProp = material.variantProperty("objectName");
objNameProp.setValue(newName);
@@ -965,7 +1012,7 @@ void MaterialEditorView::duplicateMaterial(const ModelNode &material)
// set name and id
QString newName = sourceMat.modelNode().variantProperty("objectName").value().toString() + " copy";
duplicateMat.modelNode().variantProperty("objectName").setValue(newName);
duplicateMat.modelNode().setIdWithoutRefactoring(generateIdFromName(newName));
duplicateMat.modelNode().setIdWithoutRefactoring(model()->generateIdFromName(newName, "material"));
// sync properties
const QList<AbstractProperty> props = material.properties();
@@ -991,6 +1038,7 @@ void MaterialEditorView::customNotification([[maybe_unused]] const AbstractView
if (identifier == "selected_material_changed") {
if (!m_hasMaterialRoot) {
m_selectedMaterial = nodeList.first();
m_dynamicPropertiesModel->setSelectedNode(m_selectedMaterial);
QTimer::singleShot(0, this, &MaterialEditorView::resetView);
}
} else if (identifier == "apply_to_selected_triggered") {
@@ -1072,38 +1120,4 @@ void MaterialEditorView::reloadQml()
resetView();
}
// generate a unique camelCase id from a name
QString MaterialEditorView::generateIdFromName(const QString &name)
{
QString newId;
if (name.isEmpty()) {
newId = "material";
} else {
// convert to camel case
QStringList nameWords = name.split(" ");
nameWords[0] = nameWords[0].at(0).toLower() + nameWords[0].mid(1);
for (int i = 1; i < nameWords.size(); ++i)
nameWords[i] = nameWords[i].at(0).toUpper() + nameWords[i].mid(1);
newId = nameWords.join("");
// if id starts with a number prepend an underscore
if (newId.at(0).isDigit())
newId.prepend('_');
}
QRegularExpression rgx("\\d+$"); // matches a number at the end of a string
while (hasId(newId)) { // id exists
QRegularExpressionMatch match = rgx.match(newId);
if (match.hasMatch()) { // ends with a number, increment it
QString numStr = match.captured();
int num = numStr.toInt() + 1;
newId = newId.mid(0, match.capturedStart()) + QString::number(num);
} else {
newId.append('1');
}
}
return newId;
}
} // namespace QmlDesigner