Files
qt-creator/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp
Samuel Ghinet 192ac5db61 QmlDesigner: Allow dragging image Assets to the Material Browser
When dragging an image from the Assets Library to the Textures section
of the Material Browser, now Textures will be created from those
assets.

Task-number: QDS-8783
Change-Id: Ibbfb8697705a7d1af7714f3a32caff24282ee7a9
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
2023-02-24 12:45:06 +00:00

694 lines
27 KiB
C++

// Copyright (C) 2022 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 "materialbrowserview.h"
#include "bindingproperty.h"
#include "createtexture.h"
#include "materialbrowsermodel.h"
#include "materialbrowsertexturesmodel.h"
#include "materialbrowserwidget.h"
#include "nodeabstractproperty.h"
#include "nodemetainfo.h"
#include "qmlobjectnode.h"
#include "variantproperty.h"
#include <designmodecontext.h>
#include <nodeinstanceview.h>
#include <nodelistproperty.h>
#include <qmldesignerconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickView>
#include <QRegularExpression>
#include <QTimer>
namespace QmlDesigner {
static QString propertyEditorResourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
}
MaterialBrowserView::MaterialBrowserView(AsynchronousImageCache &imageCache,
ExternalDependenciesInterface &externalDependencies)
: AbstractView{externalDependencies}
, m_imageCache(imageCache)
{
m_previewTimer.setSingleShot(true);
connect(&m_previewTimer, &QTimer::timeout, this, &MaterialBrowserView::requestPreviews);
}
MaterialBrowserView::~MaterialBrowserView()
{}
bool MaterialBrowserView::hasWidget() const
{
return true;
}
WidgetInfo MaterialBrowserView::widgetInfo()
{
if (m_widget.isNull()) {
m_widget = new MaterialBrowserWidget(m_imageCache, this);
auto matEditorContext = new Internal::MaterialBrowserContext(m_widget.data());
Core::ICore::addContextObject(matEditorContext);
// custom notifications below are sent to the MaterialEditor
MaterialBrowserModel *matBrowserModel = m_widget->materialBrowserModel().data();
connect(matBrowserModel, &MaterialBrowserModel::selectedIndexChanged, this, [&] (int idx) {
ModelNode matNode = m_widget->materialBrowserModel()->materialAt(idx);
emitCustomNotification("selected_material_changed", {matNode}, {});
});
connect(matBrowserModel, &MaterialBrowserModel::applyToSelectedTriggered, this,
[&] (const ModelNode &material, bool add) {
emitCustomNotification("apply_to_selected_triggered", {material}, {add});
});
connect(matBrowserModel, &MaterialBrowserModel::renameMaterialTriggered, this,
[&] (const ModelNode &material, const QString &newName) {
emitCustomNotification("rename_material", {material}, {newName});
});
connect(matBrowserModel, &MaterialBrowserModel::addNewMaterialTriggered, this, [&] {
emitCustomNotification("add_new_material");
});
connect(matBrowserModel, &MaterialBrowserModel::duplicateMaterialTriggered, this,
[&] (const ModelNode &material) {
emitCustomNotification("duplicate_material", {material});
});
connect(matBrowserModel, &MaterialBrowserModel::pasteMaterialPropertiesTriggered, this,
[&] (const ModelNode &material,
const QList<QmlDesigner::MaterialBrowserModel::PropertyCopyData> &propDatas,
bool all) {
QmlObjectNode mat(material);
executeInTransaction(__FUNCTION__, [&] {
if (all) { // all material properties copied
// remove current properties
PropertyNameList propNames;
if (mat.isInBaseState()) {
const QList<AbstractProperty> baseProps = material.properties();
for (const auto &baseProp : baseProps) {
if (!baseProp.isDynamic())
propNames.append(baseProp.name());
}
} else {
QmlPropertyChanges changes = mat.propertyChangeForCurrentState();
if (changes.isValid()) {
const QList<AbstractProperty> changedProps = changes.targetProperties();
for (const auto &changedProp : changedProps) {
if (!changedProp.isDynamic())
propNames.append(changedProp.name());
}
}
}
for (const PropertyName &propName : std::as_const(propNames)) {
if (propName != "objectName" && propName != "data")
mat.removeProperty(propName);
}
}
// apply pasted properties
for (const QmlDesigner::MaterialBrowserModel::PropertyCopyData &propData : propDatas) {
if (propData.isValid) {
const bool isDynamic = !propData.dynamicTypeName.isEmpty();
const bool isBaseState = currentState().isBaseState();
const bool hasProperty = mat.hasProperty(propData.name);
if (propData.isBinding) {
if (isDynamic && (!hasProperty || isBaseState)) {
mat.modelNode().bindingProperty(propData.name)
.setDynamicTypeNameAndExpression(
propData.dynamicTypeName, propData.value.toString());
continue;
}
mat.setBindingProperty(propData.name, propData.value.toString());
} else {
const bool isRecording = mat.timelineIsActive()
&& mat.currentTimeline().isRecording();
if (isDynamic && (!hasProperty || (isBaseState && !isRecording))) {
mat.modelNode().variantProperty(propData.name)
.setDynamicTypeNameAndValue(
propData.dynamicTypeName, propData.value);
continue;
}
mat.setVariantProperty(propData.name, propData.value);
}
} else {
mat.removeProperty(propData.name);
}
}
});
});
// custom notifications below are sent to the TextureEditor
MaterialBrowserTexturesModel *texturesModel = m_widget->materialBrowserTexturesModel().data();
connect(texturesModel, &MaterialBrowserTexturesModel::selectedIndexChanged, this, [&] (int idx) {
ModelNode texNode = m_widget->materialBrowserTexturesModel()->textureAt(idx);
emitCustomNotification("selected_texture_changed", {texNode}, {});
});
connect(texturesModel, &MaterialBrowserTexturesModel::duplicateTextureTriggered, this,
[&] (const ModelNode &texture) {
emitCustomNotification("duplicate_texture", {texture});
});
connect(texturesModel, &MaterialBrowserTexturesModel::applyToSelectedMaterialTriggered, this,
[&] (const ModelNode &texture) {
if (!m_widget)
return;
const ModelNode material = m_widget->materialBrowserModel()->selectedMaterial();
applyTextureToMaterial({material}, texture);
});
connect(texturesModel, &MaterialBrowserTexturesModel::applyToSelectedModelTriggered, this,
[&] (const ModelNode &texture) {
if (m_selectedModels.size() != 1)
return;
applyTextureToModel3D(m_selectedModels[0], texture);
});
connect(texturesModel, &MaterialBrowserTexturesModel::addNewTextureTriggered, this, [&] {
emitCustomNotification("add_new_texture");
});
connect(texturesModel, &MaterialBrowserTexturesModel::updateSceneEnvStateRequested, this, [&]() {
ModelNode activeSceneEnv = CreateTexture(this).resolveSceneEnv(m_sceneId);
const bool sceneEnvExists = activeSceneEnv.isValid();
m_widget->materialBrowserTexturesModel()->setHasSceneEnv(sceneEnvExists);
});
connect(texturesModel, &MaterialBrowserTexturesModel::updateModelSelectionStateRequested, this, [&]() {
bool hasModel = false;
if (m_selectedModels.size() == 1)
hasModel = getMaterialOfModel(m_selectedModels.at(0)).isValid();
m_widget->materialBrowserTexturesModel()->setHasSingleModelSelection(hasModel);
});
connect(texturesModel, &MaterialBrowserTexturesModel::applyAsLightProbeRequested, this,
[&] (const ModelNode &texture) {
executeInTransaction(__FUNCTION__, [&] {
CreateTexture(this).assignTextureAsLightProbe(texture, m_sceneId);
});
});
}
return createWidgetInfo(m_widget.data(),
"MaterialBrowser",
WidgetInfo::LeftPane,
0,
tr("Material Browser"),
tr("Material Browser view"));
}
void MaterialBrowserView::createTextures(const QStringList &assetPaths)
{
auto *create = new CreateTextures(this, false);
executeInTransaction("MaterialBrowserView::createTextures", [&]() {
create->execute(assetPaths, AddTextureMode::Texture, m_sceneId);
});
create->deleteLater();
}
void MaterialBrowserView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
m_widget->clearSearchFilter();
m_widget->materialBrowserModel()->setHasMaterialLibrary(false);
m_hasQuick3DImport = model->hasImport("QtQuick3D");
// Project load is already very busy and may even trigger puppet reset, so let's wait a moment
// before refreshing the model
QTimer::singleShot(1000, model, [this]() {
refreshModel(true);
loadPropertyGroups(); // Needs the delay because it uses metaInfo
});
m_sceneId = model->active3DSceneId();
}
void MaterialBrowserView::refreshModel(bool updateImages)
{
if (!model())
return;
ModelNode matLib = modelNodeForId(Constants::MATERIAL_LIB_ID);
QList<ModelNode> materials;
QList<ModelNode> textures;
if (m_hasQuick3DImport && matLib.isValid()) {
const QList <ModelNode> matLibNodes = matLib.directSubModelNodes();
for (const ModelNode &node : matLibNodes) {
if (isMaterial(node))
materials.append(node);
else if (isTexture(node))
textures.append(node);
}
}
m_widget->materialBrowserModel()->setMaterials(materials, m_hasQuick3DImport);
m_widget->materialBrowserTexturesModel()->setTextures(textures);
m_widget->materialBrowserModel()->setHasMaterialLibrary(matLib.isValid());
if (updateImages) {
for (const ModelNode &node : std::as_const(materials))
m_previewRequests.insert(node);
if (!m_previewRequests.isEmpty())
m_previewTimer.start(0);
}
}
bool MaterialBrowserView::isMaterial(const ModelNode &node) const
{
return node.metaInfo().isQtQuick3DMaterial();
}
bool MaterialBrowserView::isTexture(const ModelNode &node) const
{
if (!node.isValid())
return false;
return node.metaInfo().isQtQuick3DTexture();
}
void MaterialBrowserView::modelAboutToBeDetached(Model *model)
{
m_widget->materialBrowserModel()->setMaterials({}, m_hasQuick3DImport);
m_widget->materialBrowserModel()->setHasMaterialLibrary(false);
m_widget->clearPreviewCache();
if (m_propertyGroupsLoaded) {
m_propertyGroupsLoaded = false;
m_widget->materialBrowserModel()->unloadPropertyGroups();
}
AbstractView::modelAboutToBeDetached(model);
}
void MaterialBrowserView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
[[maybe_unused]] const QList<ModelNode> &lastSelectedNodeList)
{
m_selectedModels = Utils::filtered(selectedNodeList, [](const ModelNode &node) {
return node.metaInfo().isQtQuick3DModel();
});
m_widget->materialBrowserModel()->setHasModelSelection(!m_selectedModels.isEmpty());
// the logic below selects the material of the first selected model if auto selection is on
if (!m_autoSelectModelMaterial)
return;
if (selectedNodeList.size() > 1 || m_selectedModels.isEmpty())
return;
ModelNode mat = getMaterialOfModel(m_selectedModels.at(0));
if (!mat.isValid())
return;
// if selected object is a model, select its material in the material browser and editor
int idx = m_widget->materialBrowserModel()->materialIndex(mat);
m_widget->materialBrowserModel()->selectMaterial(idx);
}
void MaterialBrowserView::modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap)
{
if (isMaterial(node))
m_widget->updateMaterialPreview(node, pixmap);
}
void MaterialBrowserView::nodeIdChanged(const ModelNode &node, [[maybe_unused]] const QString &newId,
[[maybe_unused]] const QString &oldId)
{
if (isTexture(node))
m_widget->materialBrowserTexturesModel()->updateTextureSource(node);
}
void MaterialBrowserView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
[[maybe_unused]] PropertyChangeFlags propertyChange)
{
for (const VariantProperty &property : propertyList) {
ModelNode node(property.parentModelNode());
if (isMaterial(node) && property.name() == "objectName") {
m_widget->materialBrowserModel()->updateMaterialName(node);
} else if (property.name() == "source") {
QmlObjectNode selectedTex = m_widget->materialBrowserTexturesModel()->selectedTexture();
if (isTexture(node))
m_widget->materialBrowserTexturesModel()->updateTextureSource(node);
else if (selectedTex.propertyChangeForCurrentState() == node)
m_widget->materialBrowserTexturesModel()->updateTextureSource(selectedTex);
}
}
}
void MaterialBrowserView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
{
for (const AbstractProperty &prop : propertyList) {
if (isTexture(prop.parentModelNode()) && prop.name() == "source")
m_widget->materialBrowserTexturesModel()->updateTextureSource(prop.parentModelNode());
}
}
void MaterialBrowserView::nodeReparented(const ModelNode &node,
const NodeAbstractProperty &newPropertyParent,
const NodeAbstractProperty &oldPropertyParent,
[[maybe_unused]] PropertyChangeFlags propertyChange)
{
Q_UNUSED(propertyChange)
if (node.id() == Constants::MATERIAL_LIB_ID)
m_widget->materialBrowserModel()->setHasMaterialLibrary(true);
if (!isMaterial(node) && !isTexture(node))
return;
ModelNode newParentNode = newPropertyParent.parentModelNode();
ModelNode oldParentNode = oldPropertyParent.parentModelNode();
bool added = newParentNode.id() == Constants::MATERIAL_LIB_ID;
bool removed = oldParentNode.id() == Constants::MATERIAL_LIB_ID;
if (!added && !removed)
return;
refreshModel(removed);
if (isMaterial(node)) {
if (added && !m_puppetResetPending) {
// Workaround to fix various material issues all likely caused by QTBUG-103316
resetPuppet();
m_puppetResetPending = true;
}
int idx = m_widget->materialBrowserModel()->materialIndex(node);
m_widget->materialBrowserModel()->selectMaterial(idx);
m_widget->materialBrowserModel()->refreshSearch();
} else { // is texture
int idx = m_widget->materialBrowserTexturesModel()->textureIndex(node);
m_widget->materialBrowserTexturesModel()->selectTexture(idx);
m_widget->materialBrowserTexturesModel()->refreshSearch();
}
}
void MaterialBrowserView::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
// removing the material lib node
if (removedNode.id() == Constants::MATERIAL_LIB_ID) {
m_widget->materialBrowserModel()->setMaterials({}, m_hasQuick3DImport);
m_widget->materialBrowserModel()->setHasMaterialLibrary(false);
m_widget->clearPreviewCache();
return;
}
// not under the material lib
if (removedNode.parentProperty().parentModelNode().id() != Constants::MATERIAL_LIB_ID)
return;
if (isMaterial(removedNode))
m_widget->materialBrowserModel()->removeMaterial(removedNode);
else if (isTexture(removedNode))
m_widget->materialBrowserTexturesModel()->removeTexture(removedNode);
}
void MaterialBrowserView::nodeRemoved([[maybe_unused]] const ModelNode &removedNode,
const NodeAbstractProperty &parentProperty,
[[maybe_unused]] PropertyChangeFlags propertyChange)
{
if (parentProperty.parentModelNode().id() != Constants::MATERIAL_LIB_ID)
return;
m_widget->materialBrowserModel()->updateSelectedMaterial();
m_widget->materialBrowserTexturesModel()->updateSelectedTexture();
}
void QmlDesigner::MaterialBrowserView::loadPropertyGroups()
{
if (!m_hasQuick3DImport || m_propertyGroupsLoaded || !model())
return;
QString matPropsPath = model()->metaInfo("QtQuick3D.Material").importDirectoryPath()
+ "/designer/propertyGroups.json";
m_propertyGroupsLoaded = m_widget->materialBrowserModel()->loadPropertyGroups(matPropsPath);
}
void MaterialBrowserView::requestPreviews()
{
if (model() && model()->nodeInstanceView()) {
for (const auto &node : std::as_const(m_previewRequests))
model()->nodeInstanceView()->previewImageDataForGenericNode(node, {});
}
m_previewRequests.clear();
}
ModelNode MaterialBrowserView::getMaterialOfModel(const ModelNode &model)
{
QmlObjectNode qmlObjNode(model);
QString matExp = qmlObjNode.expression("materials");
if (matExp.isEmpty())
return {};
const QStringList mats = matExp.remove('[').remove(']').split(',', Qt::SkipEmptyParts);
if (mats.isEmpty())
return {};
for (const auto &matId : mats) {
ModelNode mat = modelNodeForId(matId);
if (mat.isValid())
return mat;
}
return {};
}
void MaterialBrowserView::importsChanged([[maybe_unused]] const QList<Import> &addedImports,
[[maybe_unused]] const QList<Import> &removedImports)
{
bool hasQuick3DImport = model()->hasImport("QtQuick3D");
if (hasQuick3DImport == m_hasQuick3DImport)
return;
m_hasQuick3DImport = hasQuick3DImport;
loadPropertyGroups();
// Import change will trigger puppet reset, so we don't want to update previews immediately
refreshModel(false);
}
void MaterialBrowserView::customNotification(const AbstractView *view,
const QString &identifier,
const QList<ModelNode> &nodeList,
const QList<QVariant> &data)
{
if (view == this)
return;
if (identifier == "selected_material_changed") {
int idx = m_widget->materialBrowserModel()->materialIndex(nodeList.first());
if (idx != -1)
m_widget->materialBrowserModel()->selectMaterial(idx);
} else if (identifier == "selected_texture_changed") {
int idx = m_widget->materialBrowserTexturesModel()->textureIndex(nodeList.first());
if (idx != -1) {
m_widget->materialBrowserTexturesModel()->selectTexture(idx);
m_widget->materialBrowserTexturesModel()->refreshSearch();
if (!data.isEmpty() && data[0].toBool())
m_widget->focusMaterialSection(false);
}
} else if (identifier == "refresh_material_browser") {
QTimer::singleShot(0, model(), [this]() {
refreshModel(true);
});
} else if (identifier == "delete_selected_material") {
m_widget->deleteSelectedItem();
} else if (identifier == "apply_bundle_texture_to_model3D") {
m_appliedTexturePath = data.at(0).toString();
applyTextureToModel3D(nodeList.at(0));
} else if (identifier == "apply_texture_to_model3D") {
applyTextureToModel3D(nodeList.at(0), nodeList.at(1));
} else if (identifier == "apply_texture_to_material") {
applyTextureToMaterial({nodeList.at(0)}, nodeList.at(1));
} else if (identifier == "focus_material_section") {
m_widget->focusMaterialSection(true);
}
}
void MaterialBrowserView::active3DSceneChanged(qint32 sceneId)
{
m_sceneId = sceneId;
}
void MaterialBrowserView::currentStateChanged([[maybe_unused]] const ModelNode &node)
{
m_widget->materialBrowserTexturesModel()->updateAllTexturesSources();
}
void MaterialBrowserView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
{
for (const ModelNode &node : completedNodeList) {
// We use root node completion as indication of puppet reset
if (node.isRootNode()) {
m_puppetResetPending = false;
QTimer::singleShot(1000, this, [this]() {
if (!model() || !model()->nodeInstanceView())
return;
const QList<ModelNode> materials = m_widget->materialBrowserModel()->materials();
for (const ModelNode &node : materials)
m_previewRequests.insert(node);
if (!m_previewRequests.isEmpty())
m_previewTimer.start(0);
});
break;
}
}
}
void MaterialBrowserView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList)
{
for (const auto &nodeProp : propertyList) {
ModelNode node = nodeProp.first;
if (node.metaInfo().isQtQuick3DMaterial())
m_previewRequests.insert(node);
}
if (!m_previewRequests.isEmpty() && !m_previewTimer.isActive()) {
// Updating material browser isn't urgent in e.g. timeline scrubbing case, so have a bit
// of delay to reduce unnecessary rendering
m_previewTimer.start(500);
}
}
void MaterialBrowserView::applyTextureToModel3D(const QmlObjectNode &model3D, const ModelNode &texture)
{
if (!texture.isValid() && m_appliedTexturePath.isEmpty())
return;
if (!model3D.isValid() || !model3D.modelNode().metaInfo().isQtQuick3DModel())
return;
BindingProperty matsProp = model3D.bindingProperty("materials");
QList<ModelNode> materials;
if (hasId(matsProp.expression()))
materials.append(modelNodeForId(matsProp.expression()));
else
materials = matsProp.resolveToModelNodeList();
applyTextureToMaterial(materials, texture);
}
void MaterialBrowserView::applyTextureToMaterial(const QList<ModelNode> &materials,
const ModelNode &texture)
{
if (materials.isEmpty())
return;
if (texture.isValid())
m_appliedTextureId = texture.id();
m_textureModels.clear();
QStringList materialsModel;
for (const ModelNode &mat : std::as_const(materials)) {
QString matName = mat.variantProperty("objectName").value().toString();
materialsModel.append(QLatin1String("%1 (%2)").arg(matName, mat.id()));
QList<PropertyName> texProps;
for (const PropertyMetaInfo &p : mat.metaInfo().properties()) {
if (p.propertyType().isQtQuick3DTexture())
texProps.append(p.name());
}
m_textureModels.insert(mat.id(), texProps);
}
QString path = MaterialBrowserWidget::qmlSourcesPath() + "/ChooseMaterialProperty.qml";
m_chooseMatPropsView = new QQuickView;
m_chooseMatPropsView->setTitle(tr("Select a material property"));
m_chooseMatPropsView->setResizeMode(QQuickView::SizeRootObjectToView);
m_chooseMatPropsView->setMinimumSize({150, 100});
m_chooseMatPropsView->setMaximumSize({600, 400});
m_chooseMatPropsView->setWidth(450);
m_chooseMatPropsView->setHeight(300);
m_chooseMatPropsView->setFlags(Qt::Widget);
m_chooseMatPropsView->setModality(Qt::ApplicationModal);
m_chooseMatPropsView->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_chooseMatPropsView->rootContext()->setContextProperties({
{"rootView", QVariant::fromValue(this)},
{"materialsModel", QVariant::fromValue(materialsModel)},
{"propertiesModel", QVariant::fromValue(m_textureModels.value(materials.at(0).id()))},
});
m_chooseMatPropsView->setSource(QUrl::fromLocalFile(path));
m_chooseMatPropsView->installEventFilter(this);
m_chooseMatPropsView->show();
}
void MaterialBrowserView::updatePropsModel(const QString &matId)
{
m_chooseMatPropsView->rootContext()->setContextProperty("propertiesModel",
QVariant::fromValue(m_textureModels.value(matId)));
}
void MaterialBrowserView::applyTextureToProperty(const QString &matId, const QString &propName)
{
executeInTransaction(__FUNCTION__, [&] {
if (m_appliedTextureId.isEmpty() && !m_appliedTexturePath.isEmpty()) {
auto texCreator = new CreateTexture(this, true);
ModelNode tex = texCreator->execute(m_appliedTexturePath, AddTextureMode::Texture);
m_appliedTextureId = tex.id();
m_appliedTexturePath.clear();
texCreator->deleteLater();
}
QTC_ASSERT(!m_appliedTextureId.isEmpty(), return);
QmlObjectNode mat = modelNodeForId(matId);
QTC_ASSERT(mat.isValid(), return);
BindingProperty texProp = mat.bindingProperty(propName.toLatin1());
QTC_ASSERT(texProp.isValid(), return);
mat.setBindingProperty(propName.toLatin1(), m_appliedTextureId);
closeChooseMatPropsView();
});
}
void MaterialBrowserView::closeChooseMatPropsView()
{
m_chooseMatPropsView->close();
}
bool MaterialBrowserView::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Escape) {
if (obj == m_chooseMatPropsView)
m_chooseMatPropsView->close();
}
} else if (event->type() == QEvent::Close) {
if (obj == m_chooseMatPropsView) {
m_appliedTextureId.clear();
m_appliedTexturePath.clear();
m_chooseMatPropsView->deleteLater();
}
}
return AbstractView::eventFilter(obj, event);
}
} // namespace QmlDesigner