QmlDesigner: Enable drag-n-drop a material to a model in Navigator

Fixes: QDS-6694
Change-Id: I2fb32052559b1d459cc8025e9f30368b0189e8ab
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Mahmoud Badri
2022-06-27 14:31:59 +03:00
parent ee40ed19e5
commit 234958a47a
8 changed files with 83 additions and 2 deletions

View File

@@ -72,9 +72,12 @@ Rectangle {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: (mouse) => {
onPressed: (mouse) => {
materialBrowserModel.selectMaterial(index)
if (mouse.button === Qt.RightButton)
if (mouse.button === Qt.LeftButton)
rootView.startDragMaterial(index, mapToGlobal(mouse.x, mouse.y))
else if (mouse.button === Qt.RightButton)
root.showContextMenu()
}

View File

@@ -32,6 +32,7 @@
#include <designermcumanager.h>
#include <documentmanager.h>
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
#include <utils/algorithm.h>
#include <utils/stylehelper.h>
@@ -103,6 +104,27 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
if (event->type() == QEvent::FocusOut) {
if (obj == m_quickWidget.data())
QMetaObject::invokeMethod(m_quickWidget->rootObject(), "closeContextMenu");
} else if (event->type() == QMouseEvent::MouseMove) {
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
QTC_ASSERT(document, return false);
Model *model = document->currentModel();
QTC_ASSERT(model, return false);
if (m_materialToDrag.isValid()) {
QMouseEvent *me = static_cast<QMouseEvent *>(event);
if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) {
QByteArray data;
QMimeData *mimeData = new QMimeData;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << m_materialToDrag.internalId();
mimeData->setData(Constants::MIME_TYPE_MATERIAL, data);
mimeData->removeFormat("text/plain");
model->startDrag(mimeData, m_previewImageProvider->requestPixmap(
QString::number(m_materialToDrag.internalId()), nullptr, {128, 128}));
m_materialToDrag = {};
}
}
}
return QObject::eventFilter(obj, event);
@@ -166,6 +188,12 @@ void MaterialBrowserWidget::handleSearchfilterChanged(const QString &filterText)
}
}
void MaterialBrowserWidget::startDragMaterial(int index, const QPointF &mousePos)
{
m_materialToDrag = m_materialBrowserModel->materialAt(index);
m_dragStartPoint = mousePos.toPoint();
}
QString MaterialBrowserWidget::qmlSourcesPath()
{
#ifdef SHARE_QML_PATH

View File

@@ -69,6 +69,7 @@ public:
void updateMaterialPreview(const ModelNode &node, const QPixmap &pixmap);
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
Q_INVOKABLE void startDragMaterial(int index, const QPointF &mousePos);
QQuickWidget *quickWidget() const;
@@ -86,6 +87,9 @@ private:
PreviewImageProvider *m_previewImageProvider = nullptr;
QString m_filterText;
ModelNode m_materialToDrag;
QPoint m_dragStartPoint;
};
} // namespace QmlDesigner

View File

@@ -56,6 +56,8 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
// ParticleAbstractShape3D
// -> ParticleEmitter3D
// -> Attractor3D
// Material
// -> Model
const TypeName textureType = "QtQuick3D.Texture";
if (insertInfo.isSubclassOf(textureType)) {
@@ -104,6 +106,9 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
if (parentInfo.isSubclassOf("QtQuick3D.Particles3D.ParticleEmitter3D")
|| parentInfo.isSubclassOf("QtQuick3D.Particles3D.Attractor3D"))
propertyList.append("shape");
} else if (insertInfo.isSubclassOf("QtQuick3D.Material")) {
if (parentInfo.isSubclassOf("QtQuick3D.Particles3D.Model"))
propertyList.append("materials");
}
}

View File

@@ -464,6 +464,7 @@ QStringList NavigatorTreeModel::mimeTypes() const
{
const static QStringList types({Constants::MIME_TYPE_MODELNODE_LIST,
Constants::MIME_TYPE_ITEM_LIBRARY_INFO,
Constants::MIME_TYPE_MATERIAL,
Constants::MIME_TYPE_ASSETS});
return types;
@@ -559,6 +560,8 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
if (dropModelIndex.model() == this) {
if (mimeData->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
handleMaterialDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) {
const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(',');
NodeAbstractProperty targetProperty;
@@ -779,6 +782,33 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
}
}
void NavigatorTreeModel::handleMaterialDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex)
{
QTC_ASSERT(m_view, return);
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
int targetRowNumber = rowNumber;
NodeAbstractProperty targetProperty;
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber, "materials");
if (!foundTarget)
return;
ModelNode targetNode = targetProperty.parentModelNode();
if (!targetNode.isSubclassOf("QtQuick3D.Model"))
return;
QByteArray data = mimeData->data(Constants::MIME_TYPE_MATERIAL);
QDataStream stream(data);
qint32 internalId;
stream >> internalId;
ModelNode matNode = m_view->modelNodeForInternalId(internalId);
m_view->executeInTransaction(__FUNCTION__, [&] {
m_view->assignMaterialTo3dModel(targetNode, matNode);
});
}
ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath,
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex,

View File

@@ -115,6 +115,7 @@ private:
int targetIndex, bool executeInTransaction = true);
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
void handleMaterialDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
ModelNode handleItemLibraryImageDrop(const QString &imagePath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty,

View File

@@ -276,6 +276,15 @@ void NavigatorView::dragStarted(QMimeData *mimeData)
m_widget->setDragType(itemLibraryEntry.typeName());
m_widget->update();
} else if (mimeData->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
QByteArray data = mimeData->data(Constants::MIME_TYPE_MATERIAL);
QDataStream stream(data);
qint32 internalId;
stream >> internalId;
ModelNode matNode = modelNodeForInternalId(internalId);
m_widget->setDragType(matNode.metaInfo().typeName());
m_widget->update();
}
}

View File

@@ -92,6 +92,7 @@ const char MATERIAL_LIB_ID[] = "__materialLibrary__";
const char MIME_TYPE_ITEM_LIBRARY_INFO[] = "application/vnd.qtdesignstudio.itemlibraryinfo";
const char MIME_TYPE_ASSETS[] = "application/vnd.qtdesignstudio.assets";
const char MIME_TYPE_MATERIAL[] = "application/vnd.qtdesignstudio.material";
const char MIME_TYPE_ASSET_IMAGE[] = "application/vnd.qtdesignstudio.asset.image";
const char MIME_TYPE_ASSET_FONT[] = "application/vnd.qtdesignstudio.asset.font";
const char MIME_TYPE_ASSET_SHADER[] = "application/vnd.qtdesignstudio.asset.shader";