forked from qt-creator/qt-creator
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:
@@ -72,9 +72,12 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
|
||||||
onClicked: (mouse) => {
|
onPressed: (mouse) => {
|
||||||
materialBrowserModel.selectMaterial(index)
|
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()
|
root.showContextMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include <designermcumanager.h>
|
#include <designermcumanager.h>
|
||||||
#include <documentmanager.h>
|
#include <documentmanager.h>
|
||||||
#include <qmldesignerconstants.h>
|
#include <qmldesignerconstants.h>
|
||||||
|
#include <qmldesignerplugin.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/stylehelper.h>
|
#include <utils/stylehelper.h>
|
||||||
@@ -103,6 +104,27 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event)
|
|||||||
if (event->type() == QEvent::FocusOut) {
|
if (event->type() == QEvent::FocusOut) {
|
||||||
if (obj == m_quickWidget.data())
|
if (obj == m_quickWidget.data())
|
||||||
QMetaObject::invokeMethod(m_quickWidget->rootObject(), "closeContextMenu");
|
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);
|
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()
|
QString MaterialBrowserWidget::qmlSourcesPath()
|
||||||
{
|
{
|
||||||
#ifdef SHARE_QML_PATH
|
#ifdef SHARE_QML_PATH
|
||||||
|
@@ -69,6 +69,7 @@ public:
|
|||||||
void updateMaterialPreview(const ModelNode &node, const QPixmap &pixmap);
|
void updateMaterialPreview(const ModelNode &node, const QPixmap &pixmap);
|
||||||
|
|
||||||
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
|
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
|
||||||
|
Q_INVOKABLE void startDragMaterial(int index, const QPointF &mousePos);
|
||||||
|
|
||||||
QQuickWidget *quickWidget() const;
|
QQuickWidget *quickWidget() const;
|
||||||
|
|
||||||
@@ -86,6 +87,9 @@ private:
|
|||||||
PreviewImageProvider *m_previewImageProvider = nullptr;
|
PreviewImageProvider *m_previewImageProvider = nullptr;
|
||||||
|
|
||||||
QString m_filterText;
|
QString m_filterText;
|
||||||
|
|
||||||
|
ModelNode m_materialToDrag;
|
||||||
|
QPoint m_dragStartPoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -56,6 +56,8 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
|
|||||||
// ParticleAbstractShape3D
|
// ParticleAbstractShape3D
|
||||||
// -> ParticleEmitter3D
|
// -> ParticleEmitter3D
|
||||||
// -> Attractor3D
|
// -> Attractor3D
|
||||||
|
// Material
|
||||||
|
// -> Model
|
||||||
|
|
||||||
const TypeName textureType = "QtQuick3D.Texture";
|
const TypeName textureType = "QtQuick3D.Texture";
|
||||||
if (insertInfo.isSubclassOf(textureType)) {
|
if (insertInfo.isSubclassOf(textureType)) {
|
||||||
@@ -104,6 +106,9 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
|
|||||||
if (parentInfo.isSubclassOf("QtQuick3D.Particles3D.ParticleEmitter3D")
|
if (parentInfo.isSubclassOf("QtQuick3D.Particles3D.ParticleEmitter3D")
|
||||||
|| parentInfo.isSubclassOf("QtQuick3D.Particles3D.Attractor3D"))
|
|| parentInfo.isSubclassOf("QtQuick3D.Particles3D.Attractor3D"))
|
||||||
propertyList.append("shape");
|
propertyList.append("shape");
|
||||||
|
} else if (insertInfo.isSubclassOf("QtQuick3D.Material")) {
|
||||||
|
if (parentInfo.isSubclassOf("QtQuick3D.Particles3D.Model"))
|
||||||
|
propertyList.append("materials");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -464,6 +464,7 @@ QStringList NavigatorTreeModel::mimeTypes() const
|
|||||||
{
|
{
|
||||||
const static QStringList types({Constants::MIME_TYPE_MODELNODE_LIST,
|
const static QStringList types({Constants::MIME_TYPE_MODELNODE_LIST,
|
||||||
Constants::MIME_TYPE_ITEM_LIBRARY_INFO,
|
Constants::MIME_TYPE_ITEM_LIBRARY_INFO,
|
||||||
|
Constants::MIME_TYPE_MATERIAL,
|
||||||
Constants::MIME_TYPE_ASSETS});
|
Constants::MIME_TYPE_ASSETS});
|
||||||
|
|
||||||
return types;
|
return types;
|
||||||
@@ -559,6 +560,8 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
|||||||
if (dropModelIndex.model() == this) {
|
if (dropModelIndex.model() == this) {
|
||||||
if (mimeData->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
|
if (mimeData->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
|
||||||
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
|
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
|
||||||
|
} else if (mimeData->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
|
||||||
|
handleMaterialDrop(mimeData, rowNumber, dropModelIndex);
|
||||||
} else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) {
|
} else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) {
|
||||||
const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(',');
|
const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(',');
|
||||||
NodeAbstractProperty targetProperty;
|
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,
|
ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath,
|
||||||
NodeAbstractProperty targetProperty,
|
NodeAbstractProperty targetProperty,
|
||||||
const QModelIndex &rowModelIndex,
|
const QModelIndex &rowModelIndex,
|
||||||
|
@@ -115,6 +115,7 @@ private:
|
|||||||
int targetIndex, bool executeInTransaction = true);
|
int targetIndex, bool executeInTransaction = true);
|
||||||
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||||
void handleItemLibraryItemDrop(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,
|
ModelNode handleItemLibraryImageDrop(const QString &imagePath, NodeAbstractProperty targetProperty,
|
||||||
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
|
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
|
||||||
ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty,
|
ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty,
|
||||||
|
@@ -276,6 +276,15 @@ void NavigatorView::dragStarted(QMimeData *mimeData)
|
|||||||
|
|
||||||
m_widget->setDragType(itemLibraryEntry.typeName());
|
m_widget->setDragType(itemLibraryEntry.typeName());
|
||||||
m_widget->update();
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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_ITEM_LIBRARY_INFO[] = "application/vnd.qtdesignstudio.itemlibraryinfo";
|
||||||
const char MIME_TYPE_ASSETS[] = "application/vnd.qtdesignstudio.assets";
|
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_IMAGE[] = "application/vnd.qtdesignstudio.asset.image";
|
||||||
const char MIME_TYPE_ASSET_FONT[] = "application/vnd.qtdesignstudio.asset.font";
|
const char MIME_TYPE_ASSET_FONT[] = "application/vnd.qtdesignstudio.asset.font";
|
||||||
const char MIME_TYPE_ASSET_SHADER[] = "application/vnd.qtdesignstudio.asset.shader";
|
const char MIME_TYPE_ASSET_SHADER[] = "application/vnd.qtdesignstudio.asset.shader";
|
||||||
|
Reference in New Issue
Block a user