forked from qt-creator/qt-creator
QmlDesigner: drag effects from assets view to navigator
Effects can be dragged from the assets panel to the navigator, also effects can be dragged between components in the navigator. There were lots of transformations because the way navigator works in not suitable with effects Task-number: QDS-8235 Change-Id: I378a70b5586fa95d0890bda4fbe53191c7ab0bc4 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -42,13 +42,6 @@ void AssetsLibraryModel::createBackendModel()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetsLibraryModel::isEffectQmlExist(const QString &effectName)
|
|
||||||
{
|
|
||||||
Utils::FilePath effectsResDir = ModelNodeOperations::getEffectsDirectory();
|
|
||||||
Utils::FilePath qmlPath = effectsResDir.resolvePath(effectName + "/" + effectName + ".qml");
|
|
||||||
return qmlPath.exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssetsLibraryModel::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
void AssetsLibraryModel::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||||
[[maybe_unused]] const QList<int> &roles)
|
[[maybe_unused]] const QList<int> &roles)
|
||||||
{
|
{
|
||||||
|
@@ -63,8 +63,6 @@ public:
|
|||||||
static const QStringList &supportedEffectMakerSuffixes();
|
static const QStringList &supportedEffectMakerSuffixes();
|
||||||
static const QSet<QString> &supportedSuffixes();
|
static const QSet<QString> &supportedSuffixes();
|
||||||
|
|
||||||
static bool isEffectQmlExist(const QString &effectName);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void directoryLoaded(const QString &path);
|
void directoryLoaded(const QString &path);
|
||||||
void rootPathChanged();
|
void rootPathChanged();
|
||||||
|
@@ -2,13 +2,13 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 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 "modelnodeoperations.h"
|
#include "modelnodeoperations.h"
|
||||||
|
#include "coreplugin/coreplugintr.h"
|
||||||
#include "designmodewidget.h"
|
#include "designmodewidget.h"
|
||||||
#include "modelnodecontextmenu_helper.h"
|
#include "modelnodecontextmenu_helper.h"
|
||||||
#include "addimagesdialog.h"
|
#include "addimagesdialog.h"
|
||||||
#include "layoutingridlayout.h"
|
#include "layoutingridlayout.h"
|
||||||
#include "findimplementation.h"
|
#include "findimplementation.h"
|
||||||
|
|
||||||
|
|
||||||
#include "addsignalhandlerdialog.h"
|
#include "addsignalhandlerdialog.h"
|
||||||
|
|
||||||
#include <bindingproperty.h>
|
#include <bindingproperty.h>
|
||||||
@@ -1704,6 +1704,33 @@ QString getEffectIcon(const QString &effectPath)
|
|||||||
return effectResPath.exists() ? QString("effectExported") : QString("effectClass");
|
return effectResPath.exists() ? QString("effectExported") : QString("effectClass");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool useLayerEffect()
|
||||||
|
{
|
||||||
|
QSettings *settings = Core::ICore::settings();
|
||||||
|
const QString layerEffectEntry = "QML/Designer/UseLayerEffect";
|
||||||
|
|
||||||
|
return settings->value(layerEffectEntry, true).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validateEffect(const QString &effectPath)
|
||||||
|
{
|
||||||
|
const QString effectName = QFileInfo(effectPath).baseName();
|
||||||
|
Utils::FilePath effectsResDir = ModelNodeOperations::getEffectsDirectory();
|
||||||
|
Utils::FilePath qmlPath = effectsResDir.resolvePath(effectName + "/" + effectName + ".qml");
|
||||||
|
if (!qmlPath.exists()) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText(QObject::tr("Effect %1 not complete").arg(effectName));
|
||||||
|
msgBox.setInformativeText(QObject::tr("Do you want to edit %1?").arg(effectName));
|
||||||
|
msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Yes);
|
||||||
|
msgBox.setIcon(QMessageBox::Question);
|
||||||
|
if (msgBox.exec() == QMessageBox::Yes)
|
||||||
|
ModelNodeOperations::openEffectMaker(effectName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ModelNodeOperations
|
} // namespace ModelNodeOperations
|
||||||
|
|
||||||
} //QmlDesigner
|
} //QmlDesigner
|
||||||
|
@@ -122,6 +122,8 @@ void updateImported3DAsset(const SelectionContext &selectionContext);
|
|||||||
QMLDESIGNERCORE_EXPORT Utils::FilePath getEffectsDirectory();
|
QMLDESIGNERCORE_EXPORT Utils::FilePath getEffectsDirectory();
|
||||||
void openEffectMaker(const QString &filePath);
|
void openEffectMaker(const QString &filePath);
|
||||||
QString getEffectIcon(const QString &effectPath);
|
QString getEffectIcon(const QString &effectPath);
|
||||||
|
bool useLayerEffect();
|
||||||
|
bool validateEffect(const QString &effectPath);
|
||||||
|
|
||||||
// ModelNodePreviewImageOperations
|
// ModelNodePreviewImageOperations
|
||||||
QVariant previewImageDataForGenericNode(const ModelNode &modelNode);
|
QVariant previewImageDataForGenericNode(const ModelNode &modelNode);
|
||||||
|
@@ -243,31 +243,14 @@ void DragTool::dropEvent(const QList<QGraphicsItem *> &itemList, QGraphicsSceneD
|
|||||||
if (!effectPath.isEmpty()) {
|
if (!effectPath.isEmpty()) {
|
||||||
FormEditorItem *targetContainerFormEditorItem = targetContainerOrRootItem(itemList);
|
FormEditorItem *targetContainerFormEditorItem = targetContainerOrRootItem(itemList);
|
||||||
if (targetContainerFormEditorItem) {
|
if (targetContainerFormEditorItem) {
|
||||||
QmlItemNode parentQmlItemNode = targetContainerFormEditorItem->qmlItemNode();
|
if (!ModelNodeOperations::validateEffect(effectPath)) {
|
||||||
QString effectName = QFileInfo(effectPath).baseName();
|
|
||||||
|
|
||||||
if (!AssetsLibraryModel::isEffectQmlExist(effectName)) {
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setText("Effect " + effectName + " is empty");
|
|
||||||
msgBox.setInformativeText("Do you want to edit " + effectName + "?");
|
|
||||||
msgBox.setStandardButtons(QMessageBox::No |QMessageBox::Yes);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::Yes);
|
|
||||||
msgBox.setIcon(QMessageBox::Question);
|
|
||||||
int ret = msgBox.exec();
|
|
||||||
switch (ret) {
|
|
||||||
case QMessageBox::Yes:
|
|
||||||
ModelNodeOperations::openEffectMaker(effectPath);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
event->ignore();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlItemNode::createQmlItemNodeForEffect(view(), parentQmlItemNode, effectName);
|
bool layerEffect = ModelNodeOperations::useLayerEffect();
|
||||||
|
QmlItemNode parentQmlItemNode = targetContainerFormEditorItem->qmlItemNode();
|
||||||
|
QmlItemNode::createQmlItemNodeForEffect(view(), parentQmlItemNode, effectPath, layerEffect);
|
||||||
view()->setSelectedModelNodes({parentQmlItemNode});
|
view()->setSelectedModelNodes({parentQmlItemNode});
|
||||||
|
|
||||||
commitTransaction();
|
commitTransaction();
|
||||||
|
@@ -146,16 +146,25 @@ static bool isInLayoutable(NodeAbstractProperty &parentProperty)
|
|||||||
static void reparentModelNodeToNodeProperty(NodeAbstractProperty &parentProperty, const ModelNode &modelNode)
|
static void reparentModelNodeToNodeProperty(NodeAbstractProperty &parentProperty, const ModelNode &modelNode)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
if (parentProperty.parentModelNode().type().startsWith("Effects."))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!modelNode.hasParentProperty() || parentProperty != modelNode.parentProperty()) {
|
if (!modelNode.hasParentProperty() || parentProperty != modelNode.parentProperty()) {
|
||||||
if (isInLayoutable(parentProperty)) {
|
if (isInLayoutable(parentProperty)) {
|
||||||
removePosition(modelNode);
|
removePosition(modelNode);
|
||||||
parentProperty.reparentHere(modelNode);
|
parentProperty.reparentHere(modelNode);
|
||||||
} else {
|
} else {
|
||||||
if (QmlItemNode::isValidQmlItemNode(modelNode)) {
|
if (QmlItemNode::isValidQmlItemNode(modelNode)) {
|
||||||
QPointF scenePosition = QmlItemNode(modelNode).instanceScenePosition();
|
if (modelNode.hasParentProperty() && modelNode.parentProperty().name() == "layer.effect") {
|
||||||
parentProperty.reparentHere(modelNode);
|
parentProperty = parentProperty.parentModelNode().nodeAbstractProperty("layer.effect");
|
||||||
if (!scenePosition.isNull())
|
QmlItemNode::placeEffectNode(parentProperty, modelNode, true);
|
||||||
setScenePosition(modelNode, scenePosition);
|
} else {
|
||||||
|
QPointF scenePosition = QmlItemNode(modelNode).instanceScenePosition();
|
||||||
|
parentProperty.reparentHere(modelNode);
|
||||||
|
if (!scenePosition.isNull())
|
||||||
|
setScenePosition(modelNode, scenePosition);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
parentProperty.reparentHere(modelNode);
|
parentProperty.reparentHere(modelNode);
|
||||||
}
|
}
|
||||||
@@ -597,6 +606,9 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
|||||||
} else if (assetType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
|
} else if (assetType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
|
||||||
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty,
|
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty,
|
||||||
rowModelIndex, moveNodesAfter);
|
rowModelIndex, moveNodesAfter);
|
||||||
|
} else if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
|
||||||
|
currNode = handleItemLibraryEffectDrop(assetPath, rowModelIndex);
|
||||||
|
moveNodesAfter = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currNode.isValid())
|
if (currNode.isValid())
|
||||||
@@ -1003,6 +1015,24 @@ ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3
|
|||||||
return newModelNode;
|
return newModelNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelNode NavigatorTreeModel::handleItemLibraryEffectDrop(const QString &effectPath, const QModelIndex &rowModelIndex)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_view, return {});
|
||||||
|
|
||||||
|
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
if (targetNode.hasParentProperty() && targetNode.parentProperty().name() == "layer.effect")
|
||||||
|
return newModelNode;
|
||||||
|
|
||||||
|
if (ModelNodeOperations::validateEffect(effectPath)) {
|
||||||
|
bool layerEffect = ModelNodeOperations::useLayerEffect();
|
||||||
|
newModelNode = QmlItemNode::createQmlItemNodeForEffect(m_view, targetNode, effectPath, layerEffect);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newModelNode;
|
||||||
|
}
|
||||||
|
|
||||||
bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
|
bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
|
||||||
const NodeAbstractProperty &targetProp,
|
const NodeAbstractProperty &targetProp,
|
||||||
const QString &imagePath,
|
const QString &imagePath,
|
||||||
|
@@ -106,6 +106,7 @@ private:
|
|||||||
const QModelIndex &rowModelIndex);
|
const QModelIndex &rowModelIndex);
|
||||||
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty,
|
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty,
|
||||||
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
|
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
|
||||||
|
ModelNode handleItemLibraryEffectDrop(const QString &effectPath, const QModelIndex &rowModelIndex);
|
||||||
bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp,
|
bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp,
|
||||||
const QString &imagePath, ModelNode &newNode, bool &outMoveNodesAfter);
|
const QString &imagePath, ModelNode &newNode, bool &outMoveNodesAfter);
|
||||||
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
|
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
|
||||||
|
@@ -60,9 +60,19 @@ public:
|
|||||||
const QPointF &position,
|
const QPointF &position,
|
||||||
NodeAbstractProperty parentproperty,
|
NodeAbstractProperty parentproperty,
|
||||||
bool executeInTransaction = true);
|
bool executeInTransaction = true);
|
||||||
static void createQmlItemNodeForEffect(AbstractView *view,
|
|
||||||
const QmlItemNode &parentNode,
|
static QmlItemNode createQmlItemNodeForEffect(AbstractView *view,
|
||||||
const QString &effectName);
|
QmlItemNode parentQmlItemNode,
|
||||||
|
const QString &effectPath,
|
||||||
|
bool isLayerEffect);
|
||||||
|
static QmlItemNode createQmlItemNodeForEffect(AbstractView *view,
|
||||||
|
NodeAbstractProperty parentProperty,
|
||||||
|
const QString &effectPath,
|
||||||
|
bool isLayerEffect);
|
||||||
|
static void placeEffectNode(NodeAbstractProperty &parentProperty,
|
||||||
|
const QmlItemNode &effectNode,
|
||||||
|
bool isLayerEffect);
|
||||||
|
|
||||||
QList<QmlItemNode> children() const;
|
QList<QmlItemNode> children() const;
|
||||||
QList<QmlObjectNode> resources() const;
|
QList<QmlObjectNode> resources() const;
|
||||||
QList<QmlObjectNode> allDirectSubNodes() const;
|
QList<QmlObjectNode> allDirectSubNodes() const;
|
||||||
|
@@ -158,24 +158,31 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromFont(AbstractView *view,
|
|||||||
return newQmlItemNode;
|
return newQmlItemNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool useLayerEffect()
|
QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view,
|
||||||
|
QmlItemNode parentQmlItemNode,
|
||||||
|
const QString &effectPath,
|
||||||
|
bool isLayerEffect)
|
||||||
{
|
{
|
||||||
QSettings *settings = Core::ICore::settings();
|
if (!parentQmlItemNode.isValid())
|
||||||
const QString layerEffectEntry = "QML/Designer/UseLayerEffect";
|
parentQmlItemNode = QmlItemNode(view->rootModelNode());
|
||||||
|
|
||||||
return settings->value(layerEffectEntry, true).toBool();
|
NodeAbstractProperty parentProperty = isLayerEffect
|
||||||
|
? parentQmlItemNode.nodeAbstractProperty("layer.effect")
|
||||||
|
: parentQmlItemNode.defaultNodeAbstractProperty();
|
||||||
|
|
||||||
|
return createQmlItemNodeForEffect(view, parentProperty, effectPath, isLayerEffect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlItemNode::createQmlItemNodeForEffect(AbstractView *view,
|
QmlItemNode QmlItemNode::createQmlItemNodeForEffect(AbstractView *view,
|
||||||
const QmlItemNode &parentNode,
|
NodeAbstractProperty parentProperty,
|
||||||
const QString &effectName)
|
const QString &effectPath,
|
||||||
|
bool isLayerEffect)
|
||||||
{
|
{
|
||||||
QmlItemNode newQmlItemNode;
|
QmlItemNode newQmlItemNode;
|
||||||
|
|
||||||
view->executeInTransaction("QmlItemNode::createQmlItemNodeForEffect", [=, &newQmlItemNode, &parentNode]() {
|
auto createEffectNode = [=, &newQmlItemNode, &parentProperty]() {
|
||||||
const bool layerEffect = useLayerEffect();
|
const QString effectName = QFileInfo(effectPath).baseName();
|
||||||
|
Import import = Import::createLibraryImport("Effects." + effectName, "1.0");
|
||||||
QmlDesigner::Import import = Import::createLibraryImport("Effects." + effectName, "1.0");
|
|
||||||
try {
|
try {
|
||||||
if (!view->model()->hasImport(import, true, true))
|
if (!view->model()->hasImport(import, true, true))
|
||||||
view->model()->changeImports({import}, {});
|
view->model()->changeImports({import}, {});
|
||||||
@@ -185,26 +192,28 @@ void QmlItemNode::createQmlItemNodeForEffect(AbstractView *view,
|
|||||||
|
|
||||||
TypeName type(effectName.toUtf8());
|
TypeName type(effectName.toUtf8());
|
||||||
newQmlItemNode = QmlItemNode(view->createModelNode(type, -1, -1));
|
newQmlItemNode = QmlItemNode(view->createModelNode(type, -1, -1));
|
||||||
NodeAbstractProperty parentProperty = layerEffect
|
|
||||||
? parentNode.nodeAbstractProperty("layer.effect")
|
|
||||||
: parentNode.defaultNodeAbstractProperty();
|
|
||||||
|
|
||||||
if (layerEffect) {
|
placeEffectNode(parentProperty, newQmlItemNode, isLayerEffect);
|
||||||
if (!parentProperty .isEmpty()) { //already contains a node
|
};
|
||||||
ModelNode oldEffect = parentProperty.toNodeProperty().modelNode();
|
|
||||||
QmlObjectNode(oldEffect).destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parentProperty.reparentHere(newQmlItemNode);
|
view->executeInTransaction("QmlItemNode::createQmlItemNodeFromEffect", createEffectNode);
|
||||||
|
return newQmlItemNode;
|
||||||
|
}
|
||||||
|
|
||||||
if (!layerEffect) {
|
void QmlItemNode::placeEffectNode(NodeAbstractProperty &parentProperty, const QmlItemNode &effectNode, bool isLayerEffect) {
|
||||||
newQmlItemNode.modelNode().bindingProperty("source").setExpression("parent");
|
if (isLayerEffect && !parentProperty.isEmpty()) { // already contains a node
|
||||||
newQmlItemNode.modelNode().bindingProperty("anchors.fill").setExpression("parent");
|
ModelNode oldEffect = parentProperty.toNodeProperty().modelNode();
|
||||||
} else {
|
QmlObjectNode(oldEffect).destroy();
|
||||||
parentNode.modelNode().variantProperty("layer.enabled").setValue(true);
|
}
|
||||||
}
|
|
||||||
});
|
parentProperty.reparentHere(effectNode);
|
||||||
|
|
||||||
|
if (!isLayerEffect) {
|
||||||
|
effectNode.modelNode().bindingProperty("source").setExpression("parent");
|
||||||
|
effectNode.modelNode().bindingProperty("anchors.fill").setExpression("parent");
|
||||||
|
} else {
|
||||||
|
parentProperty.parentModelNode().variantProperty("layer.enabled").setValue(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlItemNode::isValid() const
|
bool QmlItemNode::isValid() const
|
||||||
|
Reference in New Issue
Block a user