QmlDesigner: Implement multi-selection in the asset library

Multi-selected assets can be dragged to the form editor
and navigator. Also increased font size for newly
created text as it was so small and some relvant
cleanups.

Change-Id: Icf28b627a8392309520b7071209812e1ae051e84
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Mahmoud Badri
2021-06-15 17:24:24 +03:00
parent 0945b8d0dc
commit 5369aea1ed
9 changed files with 388 additions and 371 deletions

View File

@@ -32,6 +32,8 @@ import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
Item { Item {
property var selectedAssets: ({})
DropArea { DropArea {
id: dropArea id: dropArea
@@ -142,7 +144,8 @@ Item {
width: assetsView.width - width: assetsView.width -
(assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0) (assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0)
height: img.height height: img.height
color: mouseArea.containsMouse ? "#444444" : "transparent" color: selectedAssets[filePath] ? StudioTheme.Values.themeInteraction
: (mouseArea.containsMouse ? "#444444" : "transparent")
Row { Row {
spacing: 5 spacing: 5
@@ -178,10 +181,32 @@ Item {
onPositionChanged: tooltipBackend.reposition() onPositionChanged: tooltipBackend.reposition()
onPressed: { onPressed: {
forceActiveFocus() forceActiveFocus()
if (mouse.button === Qt.LeftButton) if (mouse.button === Qt.LeftButton) {
rootView.startDragAsset(filePath, mapToGlobal(mouse.x, mouse.y)) var ctrlDown = mouse.modifiers & Qt.ControlModifier
else if (!selectedAssets[filePath] && !ctrlDown)
selectedAssets = {}
selectedAssets[filePath] = true
selectedAssetsChanged()
var selectedAssetsArr = []
for (var assetPath in selectedAssets) {
if (selectedAssets[assetPath])
selectedAssetsArr.push(assetPath)
}
rootView.startDragAsset(selectedAssetsArr, mapToGlobal(mouse.x, mouse.y))
} else {
print("TODO: impl context menu") print("TODO: impl context menu")
}
}
onReleased: {
if (mouse.button === Qt.LeftButton) {
if (!(mouse.modifiers & Qt.ControlModifier))
selectedAssets = {}
selectedAssets[filePath] = true
selectedAssetsChanged()
}
} }
ToolTip { ToolTip {

View File

@@ -27,6 +27,7 @@
#include "formeditorview.h" #include "formeditorview.h"
#include "formeditorwidget.h" #include "formeditorwidget.h"
#include "formeditorscene.h" #include "formeditorscene.h"
#include "itemlibrarywidget.h"
#include <modelnodecontextmenu.h> #include <modelnodecontextmenu.h>
@@ -234,9 +235,21 @@ void AbstractFormEditorTool::dropEvent(const QList<QGraphicsItem*> &/*itemList*/
void AbstractFormEditorTool::dragEnterEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneDragDropEvent *event) void AbstractFormEditorTool::dragEnterEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneDragDropEvent *event)
{ {
if (event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.itemlibraryinfo")) bool hasValidAssets = false;
|| event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.libraryresource.image")) if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
|| event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.libraryresource.font"))) { const QStringList assetPaths = QString::fromUtf8(event->mimeData()
->data("application/vnd.bauhaus.libraryresource")).split(",");
for (const QString &assetPath : assetPaths) {
QString assetType = ItemLibraryWidget::getAssetTypeAndData(assetPath).first;
if (assetType == "application/vnd.bauhaus.libraryresource.image"
|| assetType == "application/vnd.bauhaus.libraryresource.font") {
hasValidAssets = true;
break;
}
}
}
if (event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.itemlibraryinfo")) || hasValidAssets) {
event->accept(); event->accept();
view()->changeToDragTool(); view()->changeToDragTool();
view()->currentTool()->dragEnterEvent(itemList, event); view()->currentTool()->dragEnterEvent(itemList, event);

View File

@@ -27,6 +27,7 @@
#include "formeditorscene.h" #include "formeditorscene.h"
#include "formeditorview.h" #include "formeditorview.h"
#include "itemlibrarywidget.h"
#include <metainfo.h> #include <metainfo.h>
#include <nodehints.h> #include <nodehints.h>
#include <rewritingexception.h> #include <rewritingexception.h>
@@ -45,9 +46,7 @@ namespace QmlDesigner {
DragTool::DragTool(FormEditorView *editorView) DragTool::DragTool(FormEditorView *editorView)
: AbstractFormEditorTool(editorView), : AbstractFormEditorTool(editorView),
m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView), m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
m_selectionIndicator(editorView->scene()->manipulatorLayerItem()), m_selectionIndicator(editorView->scene()->manipulatorLayerItem())
m_blockMove(false),
m_isAborted(false)
{ {
} }
@@ -57,7 +56,7 @@ void DragTool::clear()
{ {
m_moveManipulator.clear(); m_moveManipulator.clear();
m_selectionIndicator.clear(); m_selectionIndicator.clear();
m_movingItem = nullptr; m_movingItems.clear();
} }
void DragTool::mousePressEvent(const QList<QGraphicsItem *> &, QGraphicsSceneMouseEvent *) {} void DragTool::mousePressEvent(const QList<QGraphicsItem *> &, QGraphicsSceneMouseEvent *) {}
@@ -83,9 +82,9 @@ void DragTool::updateMoveManipulator() {}
void DragTool::beginWithPoint(const QPointF &beginPoint) void DragTool::beginWithPoint(const QPointF &beginPoint)
{ {
m_movingItem = scene()->itemForQmlItemNode(m_dragNode); m_movingItems = scene()->itemsForQmlItemNodes(m_dragNodes);
m_moveManipulator.setItem(m_movingItem); m_moveManipulator.setItems(m_movingItems);
m_moveManipulator.begin(beginPoint); m_moveManipulator.begin(beginPoint);
} }
@@ -108,17 +107,17 @@ void DragTool::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry,
adjustedParentNode = view()->rootModelNode(); adjustedParentNode = view()->rootModelNode();
} }
m_dragNode = QmlItemNode::createQmlItemNode(view(), itemLibraryEntry, itemPos, adjustedParentNode); m_dragNodes.append(QmlItemNode::createQmlItemNode(view(), itemLibraryEntry, itemPos, adjustedParentNode));
if (rootIsFlow) if (rootIsFlow) {
m_dragNode.setFlowItemPosition(positonInItemSpace); for (QmlItemNode &dragNode : m_dragNodes)
dragNode.setFlowItemPosition(positonInItemSpace);
}
QList<QmlItemNode> nodeList; m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(m_dragNodes));
nodeList.append(m_dragNode);
m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
} }
void DragTool::createQmlItemNodeFromImage(const QString &imageName, void DragTool::createQmlItemNodeFromImage(const QString &imagePath,
const QmlItemNode &parentNode, const QmlItemNode &parentNode,
const QPointF &scenePosition) const QPointF &scenePosition)
{ {
@@ -128,15 +127,11 @@ void DragTool::createQmlItemNodeFromImage(const QString &imageName,
FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode); FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform().inverted().map(scenePosition); QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform().inverted().map(scenePosition);
m_dragNode = QmlItemNode::createQmlItemNodeFromImage(view(), imageName, positonInItemSpace, parentNode); m_dragNodes.append(QmlItemNode::createQmlItemNodeFromImage(view(), imagePath, positonInItemSpace, parentNode));
QList<QmlItemNode> nodeList;
nodeList.append(m_dragNode);
m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
} }
} }
void DragTool::createQmlItemNodeFromFont(const QString &fontFamily, void DragTool::createQmlItemNodeFromFont(const QString &fontPath,
const QmlItemNode &parentNode, const QmlItemNode &parentNode,
const QPointF &scenePos) const QPointF &scenePos)
{ {
@@ -147,18 +142,18 @@ void DragTool::createQmlItemNodeFromFont(const QString &fontFamily,
QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform() QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform()
.inverted().map(scenePos); .inverted().map(scenePos);
m_dragNode = QmlItemNode::createQmlItemNodeFromFont(view(), fontFamily, positonInItemSpace, const auto typeAndData = ItemLibraryWidget::getAssetTypeAndData(fontPath);
parentNode); QString fontFamily = QString::fromUtf8(typeAndData.second);
QList<QmlItemNode> nodeList; m_dragNodes.append(QmlItemNode::createQmlItemNodeFromFont(view(), fontFamily,
nodeList.append(m_dragNode); positonInItemSpace, parentNode));
m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
} }
} }
FormEditorItem *DragTool::targetContainerOrRootItem(const QList<QGraphicsItem *> &itemList, FormEditorItem *currentItem) FormEditorItem *DragTool::targetContainerOrRootItem(const QList<QGraphicsItem *> &itemList,
const QList<FormEditorItem *> &currentItems)
{ {
FormEditorItem *formEditorItem = containerFormEditorItem(itemList, {currentItem}); FormEditorItem *formEditorItem = containerFormEditorItem(itemList, currentItems);
if (!formEditorItem) if (!formEditorItem)
formEditorItem = scene()->rootFormEditorItem(); formEditorItem = scene()->rootFormEditorItem();
@@ -168,19 +163,27 @@ FormEditorItem *DragTool::targetContainerOrRootItem(const QList<QGraphicsItem *>
void DragTool::formEditorItemsChanged(const QList<FormEditorItem *> &itemList) void DragTool::formEditorItemsChanged(const QList<FormEditorItem *> &itemList)
{ {
if (m_movingItem && itemList.contains(m_movingItem)) { if (!m_movingItems.isEmpty()) {
QList<FormEditorItem *> updateItemList; for (auto item : std::as_const(m_movingItems)) {
updateItemList.append(m_movingItem); if (itemList.contains(item)) {
m_selectionIndicator.updateItems(updateItemList); m_selectionIndicator.updateItems(m_movingItems);
break;
}
}
} }
} }
void DragTool::instancesCompleted(const QList<FormEditorItem *> &itemList) void DragTool::instancesCompleted(const QList<FormEditorItem *> &itemList)
{ {
m_moveManipulator.synchronizeInstanceParent(itemList); m_moveManipulator.synchronizeInstanceParent(itemList);
foreach (FormEditorItem* item, itemList) for (FormEditorItem *item : itemList) {
if (item->qmlItemNode() == m_dragNode) for (const QmlItemNode &dragNode : std::as_const(m_dragNodes)) {
clearMoveDelay(); if (item->qmlItemNode() == dragNode) {
clearMoveDelay();
break;
}
}
}
} }
void DragTool::instancesParentChanged(const QList<FormEditorItem *> &itemList) void DragTool::instancesParentChanged(const QList<FormEditorItem *> &itemList)
@@ -194,7 +197,7 @@ void DragTool::clearMoveDelay()
{ {
if (m_blockMove) { if (m_blockMove) {
m_blockMove = false; m_blockMove = false;
if (m_dragNode.isValid()) if (!m_dragNodes.isEmpty())
beginWithPoint(m_startPoint); beginWithPoint(m_startPoint);
} }
} }
@@ -206,8 +209,11 @@ void DragTool::abort()
if (!m_isAborted) { if (!m_isAborted) {
m_isAborted = true; m_isAborted = true;
if (m_dragNode.isValid()) for (auto &node : m_dragNodes) {
m_dragNode.destroy(); if (node.isValid())
node.destroy();
}
m_dragNodes.clear();
} }
} }
@@ -233,48 +239,38 @@ static bool hasItemLibraryInfo(const QMimeData *mimeData)
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo")); return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"));
} }
static bool hasImageResource(const QMimeData *mimeData)
{
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.libraryresource.image"));
}
static bool hasFontResource(const QMimeData *mimeData)
{
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.libraryresource.font"));
}
static bool canHandleMimeData(const QMimeData *mimeData)
{
return hasItemLibraryInfo(mimeData) || hasImageResource(mimeData) || hasFontResource(mimeData);
}
static bool dragAndDropPossible(const QMimeData *mimeData)
{
return canHandleMimeData(mimeData) && canBeDropped(mimeData);
}
void DragTool::dropEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event) void DragTool::dropEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event)
{ {
if (dragAndDropPossible(event->mimeData())) { if (canBeDropped(event->mimeData())) {
event->accept(); event->accept();
end(generateUseSnapping(event->modifiers())); end(generateUseSnapping(event->modifiers()));
if (m_dragNode.isValid()) { bool resetPuppet = false;
if ((m_dragNode.instanceParentItem().isValid() for (auto &node : m_dragNodes) {
&& m_dragNode.instanceParent().modelNode().metaInfo().isLayoutable()) if (node.isValid()) {
|| m_dragNode.isFlowItem()) { if ((node.instanceParentItem().isValid()
m_dragNode.removeProperty("x"); && node.instanceParent().modelNode().metaInfo().isLayoutable())
m_dragNode.removeProperty("y"); || node.isFlowItem()) {
view()->resetPuppet(); //Otherwise the layout might not reposition the item node.removeProperty("x");
node.removeProperty("y");
resetPuppet = true;
}
} }
} }
if (resetPuppet)
view()->resetPuppet(); // Otherwise the layout might not reposition the items
commitTransaction(); commitTransaction();
if (m_dragNode.isValid()) if (!m_dragNodes.isEmpty()) {
view()->setSelectedModelNode(m_dragNode); QList<ModelNode> nodeList;
for (auto &node : std::as_const(m_dragNodes)) {
m_dragNode = QmlItemNode(); if (node.isValid())
nodeList.append(node);
}
view()->setSelectedModelNodes(nodeList);
}
m_dragNodes.clear();
view()->changeToSelectionTool(); view()->changeToSelectionTool();
} }
@@ -282,11 +278,10 @@ void DragTool::dropEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSc
void DragTool::dragEnterEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event) void DragTool::dragEnterEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event)
{ {
if (dragAndDropPossible(event->mimeData())) { if (canBeDropped(event->mimeData())) {
m_blockMove = false; m_blockMove = false;
if (hasItemLibraryInfo(event->mimeData())) { if (hasItemLibraryInfo(event->mimeData())) {
view()->widgetInfo().widget->setFocus(); view()->widgetInfo().widget->setFocus();
m_isAborted = false; m_isAborted = false;
} }
@@ -300,13 +295,17 @@ void DragTool::dragEnterEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraph
void DragTool::dragLeaveEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event) void DragTool::dragLeaveEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event)
{ {
if (dragAndDropPossible(event->mimeData())) { if (canBeDropped(event->mimeData())) {
event->accept(); event->accept();
m_moveManipulator.end(); m_moveManipulator.end();
clear(); clear();
if (m_dragNode.isValid())
m_dragNode.destroy(); for (auto &node : m_dragNodes) {
if (node.isValid())
node.destroy();
}
m_dragNodes.clear();
commitTransaction(); commitTransaction();
} }
@@ -314,31 +313,31 @@ void DragTool::dragLeaveEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraph
view()->changeToSelectionTool(); view()->changeToSelectionTool();
} }
static QString libraryResourceFile(const QMimeData *mimeData) void DragTool::createDragNodes(const QMimeData *mimeData, const QPointF &scenePosition,
const QList<QGraphicsItem *> &itemList)
{ {
return QString::fromUtf8((mimeData->data(QStringLiteral("application/vnd.bauhaus.libraryresource")))); if (m_dragNodes.isEmpty()) {
}
static QString libraryResourceFont(const QMimeData *mimeData)
{
return QString::fromUtf8((mimeData->data(QStringLiteral("application/vnd.bauhaus.libraryresource.font"))));
}
void DragTool::createDragNode(const QMimeData *mimeData, const QPointF &scenePosition, const QList<QGraphicsItem *> &itemList)
{
if (!m_dragNode.hasModelNode()) {
FormEditorItem *targetContainerFormEditorItem = targetContainerOrRootItem(itemList); FormEditorItem *targetContainerFormEditorItem = targetContainerOrRootItem(itemList);
if (targetContainerFormEditorItem) { if (targetContainerFormEditorItem) {
QmlItemNode targetContainerQmlItemNode; QmlItemNode targetContainerQmlItemNode = targetContainerFormEditorItem->qmlItemNode();
if (targetContainerFormEditorItem)
targetContainerQmlItemNode = targetContainerFormEditorItem->qmlItemNode();
if (hasItemLibraryInfo(mimeData)) if (hasItemLibraryInfo(mimeData)) {
createQmlItemNode(itemLibraryEntryFromMimeData(mimeData), targetContainerQmlItemNode, scenePosition); createQmlItemNode(itemLibraryEntryFromMimeData(mimeData), targetContainerQmlItemNode,
else if (hasImageResource(mimeData)) scenePosition);
createQmlItemNodeFromImage(libraryResourceFile(mimeData), targetContainerQmlItemNode, scenePosition); } else {
else if (hasFontResource(mimeData)) const QStringList assetPaths = QString::fromUtf8(mimeData
createQmlItemNodeFromFont(libraryResourceFont(mimeData), targetContainerQmlItemNode, scenePosition); ->data("application/vnd.bauhaus.libraryresource")).split(",");
for (const QString &assetPath : assetPaths) {
QString assetType = ItemLibraryWidget::getAssetTypeAndData(assetPath).first;
if (assetType == "application/vnd.bauhaus.libraryresource.image")
createQmlItemNodeFromImage(assetPath, targetContainerQmlItemNode, scenePosition);
else if (assetType == "application/vnd.bauhaus.libraryresource.font")
createQmlItemNodeFromFont(assetPath, targetContainerQmlItemNode, scenePosition);
}
if (!m_dragNodes.isEmpty())
m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(m_dragNodes));
}
m_blockMove = true; m_blockMove = true;
m_startPoint = scenePosition; m_startPoint = scenePosition;
@@ -348,18 +347,22 @@ void DragTool::createDragNode(const QMimeData *mimeData, const QPointF &scenePos
void DragTool::dragMoveEvent(const QList<QGraphicsItem *> &itemList, QGraphicsSceneDragDropEvent *event) void DragTool::dragMoveEvent(const QList<QGraphicsItem *> &itemList, QGraphicsSceneDragDropEvent *event)
{ {
if (!m_blockMove && !m_isAborted && dragAndDropPossible(event->mimeData())) { if (!m_blockMove && !m_isAborted && canBeDropped(event->mimeData())) {
event->accept(); event->accept();
if (m_dragNode.isValid()) { if (!m_dragNodes.isEmpty()) {
FormEditorItem *targetContainerItem = targetContainerOrRootItem(itemList); FormEditorItem *targetContainerItem = targetContainerOrRootItem(itemList);
if (targetContainerItem) { if (targetContainerItem) {
move(event->scenePos(), itemList); move(event->scenePos(), itemList);
} else { } else {
end(); end();
m_dragNode.destroy(); for (auto &node : m_dragNodes) {
if (node.isValid())
node.destroy();
}
m_dragNodes.clear();
} }
} else { } else {
createDragNode(event->mimeData(), event->scenePos(), itemList); createDragNodes(event->mimeData(), event->scenePos(), itemList);
} }
} else { } else {
event->ignore(); event->ignore();
@@ -378,20 +381,21 @@ void DragTool::end(Snapper::Snapping useSnapping)
clear(); clear();
} }
void DragTool::move(const QPointF &scenePosition, const QList<QGraphicsItem *> &itemList) void DragTool::move(const QPointF &scenePosition, const QList<QGraphicsItem *> &itemList)
{ {
if (m_movingItem) { if (!m_movingItems.isEmpty()) {
FormEditorItem *containerItem = targetContainerOrRootItem(itemList, m_movingItem); FormEditorItem *containerItem = targetContainerOrRootItem(itemList, m_movingItems);
if (containerItem && m_movingItem->parentItem() && for (auto &movingItem : std::as_const(m_movingItems)) {
containerItem != m_movingItem->parentItem()) { if (containerItem && movingItem->parentItem() &&
containerItem != movingItem->parentItem()) {
const QmlItemNode movingNode = movingItem->qmlItemNode();
const QmlItemNode containerNode = containerItem->qmlItemNode();
const QmlItemNode movingNode = m_movingItem->qmlItemNode(); qCInfo(dragToolInfo()) << Q_FUNC_INFO << movingNode << containerNode << movingNode.canBereparentedTo(containerNode);
const QmlItemNode containerNode = containerItem->qmlItemNode();
qCInfo(dragToolInfo()) << Q_FUNC_INFO << movingNode << containerNode << movingNode.canBereparentedTo(containerNode); if (movingNode.canBereparentedTo(containerNode))
m_moveManipulator.reparentTo(containerItem);
if (movingNode.canBereparentedTo(containerNode)) }
m_moveManipulator.reparentTo(containerItem);
} }
Snapper::Snapping useSnapping = Snapper::UseSnapping; Snapper::Snapping useSnapping = Snapper::UseSnapping;
@@ -409,4 +413,4 @@ void DragTool::commitTransaction()
} }
} }
} } // namespace QmlDesigner

View File

@@ -80,22 +80,23 @@ public:
protected: protected:
void abort(); void abort();
void createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, const QmlItemNode &parentNode, const QPointF &scenePos); void createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, const QmlItemNode &parentNode, const QPointF &scenePos);
void createQmlItemNodeFromImage(const QString &imageName, const QmlItemNode &parentNode, const QPointF &scenePos); void createQmlItemNodeFromImage(const QString &imagePath, const QmlItemNode &parentNode, const QPointF &scenePos);
void createQmlItemNodeFromFont(const QString &fontFamily, const QmlItemNode &parentNode, const QPointF &scenePos); void createQmlItemNodeFromFont(const QString &fontPath, const QmlItemNode &parentNode, const QPointF &scenePos);
FormEditorItem *targetContainerOrRootItem(const QList<QGraphicsItem*> &itemList, FormEditorItem *urrentItem = nullptr); FormEditorItem *targetContainerOrRootItem(const QList<QGraphicsItem *> &itemList,
const QList<FormEditorItem *> &currentItems = {});
void begin(QPointF scenePos); void begin(QPointF scenePos);
void end(); void end();
void end(Snapper::Snapping useSnapping); void end(Snapper::Snapping useSnapping);
void move(const QPointF &scenePos, const QList<QGraphicsItem *> &itemList); void move(const QPointF &scenePos, const QList<QGraphicsItem *> &itemList);
void createDragNode(const QMimeData *mimeData, const QPointF &scenePosition, const QList<QGraphicsItem *> &itemList); void createDragNodes(const QMimeData *mimeData, const QPointF &scenePosition, const QList<QGraphicsItem *> &itemList);
void commitTransaction(); void commitTransaction();
private: private:
MoveManipulator m_moveManipulator; MoveManipulator m_moveManipulator;
SelectionIndicator m_selectionIndicator; SelectionIndicator m_selectionIndicator;
FormEditorItem *m_movingItem = nullptr; QList<FormEditorItem *> m_movingItems;
RewriterTransaction m_rewriterTransaction; RewriterTransaction m_rewriterTransaction;
QmlItemNode m_dragNode; QList<QmlItemNode> m_dragNodes;
bool m_blockMove; bool m_blockMove;
QPointF m_startPoint; QPointF m_startPoint;
bool m_isAborted; bool m_isAborted;

View File

@@ -117,24 +117,23 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
m_itemToDrag = {}; m_itemToDrag = {};
} }
} else if (!m_assetToDrag.isEmpty()) { } else if (!m_assetsToDrag.isEmpty()) {
QMouseEvent *me = static_cast<QMouseEvent *>(event); QMouseEvent *me = static_cast<QMouseEvent *>(event);
if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) { if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) {
auto drag = new QDrag(this); auto drag = new QDrag(this);
drag->setPixmap(m_assetsIconProvider->requestPixmap(m_assetToDrag, nullptr, {128, 128})); drag->setPixmap(m_assetsIconProvider->requestPixmap(m_assetsToDrag[0], nullptr, {128, 128}));
QMimeData *mimeData = new QMimeData; QMimeData *mimeData = new QMimeData;
mimeData->setData("application/vnd.bauhaus.libraryresource", m_assetToDrag.toUtf8()); mimeData->setData("application/vnd.bauhaus.libraryresource", m_assetsToDrag.join(',').toUtf8());
mimeData->setData(m_assetToDragTypeAndData.first, m_assetToDragTypeAndData.second);
drag->setMimeData(mimeData); drag->setMimeData(mimeData);
drag->exec(); drag->exec();
drag->deleteLater(); drag->deleteLater();
m_assetToDrag.clear(); m_assetsToDrag.clear();
} }
} }
} else if (event->type() == QMouseEvent::MouseButtonRelease) { } else if (event->type() == QMouseEvent::MouseButtonRelease) {
m_itemToDrag = {}; m_itemToDrag = {};
m_assetToDrag.clear(); m_assetsToDrag.clear();
} }
return QObject::eventFilter(obj, event); return QObject::eventFilter(obj, event);
@@ -471,30 +470,24 @@ void ItemLibraryWidget::startDragAndDrop(const QVariant &itemLibEntry, const QPo
m_dragStartPoint = mousePos.toPoint(); m_dragStartPoint = mousePos.toPoint();
} }
void ItemLibraryWidget::startDragAsset(const QString &assetPath, const QPointF &mousePos) void ItemLibraryWidget::startDragAsset(const QStringList &assetPaths, const QPointF &mousePos)
{ {
QFileInfo fileInfo(assetPath);
m_assetToDragTypeAndData = getAssetTypeAndData(fileInfo);
if (m_assetToDragTypeAndData.first.isEmpty())
return;
// Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay // Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay
// active (and blocks mouse release) if mouse is released at the same spot of the drag start. // active (and blocks mouse release) if mouse is released at the same spot of the drag start.
m_assetToDrag = fileInfo.absoluteFilePath(); m_assetsToDrag = assetPaths;
m_dragStartPoint = mousePos.toPoint(); m_dragStartPoint = mousePos.toPoint();
} }
QPair<QString, QByteArray> ItemLibraryWidget::getAssetTypeAndData(const QFileInfo &fi) const QPair<QString, QByteArray> ItemLibraryWidget::getAssetTypeAndData(const QString &assetPath)
{ {
QString suffix = "*." + fi.suffix().toLower(); QString suffix = "*." + assetPath.split('.').last().toLower();
if (!suffix.isEmpty()) { if (!suffix.isEmpty()) {
if (ItemLibraryAssetsModel::supportedImageSuffixes().contains(suffix)) { if (ItemLibraryAssetsModel::supportedImageSuffixes().contains(suffix)) {
// Data: Image format (suffix) // Data: Image format (suffix)
return {"application/vnd.bauhaus.libraryresource.image", suffix.toUtf8()}; return {"application/vnd.bauhaus.libraryresource.image", suffix.toUtf8()};
} else if (ItemLibraryAssetsModel::supportedFontSuffixes().contains(suffix)) { } else if (ItemLibraryAssetsModel::supportedFontSuffixes().contains(suffix)) {
// Data: Font family name // Data: Font family name
QRawFont font(fi.absoluteFilePath(), 10); QRawFont font(assetPath, 10);
QString fontFamily = font.isValid() ? font.familyName() : ""; QString fontFamily = font.isValid() ? font.familyName() : "";
return {"application/vnd.bauhaus.libraryresource.font", fontFamily.toUtf8()}; return {"application/vnd.bauhaus.libraryresource.font", fontFamily.toUtf8()};
} else if (ItemLibraryAssetsModel::supportedShaderSuffixes().contains(suffix)) { } else if (ItemLibraryAssetsModel::supportedShaderSuffixes().contains(suffix)) {

View File

@@ -90,10 +90,10 @@ public:
void setResourcePath(const QString &resourcePath); void setResourcePath(const QString &resourcePath);
void setModel(Model *model); void setModel(Model *model);
void setFlowMode(bool b); void setFlowMode(bool b);
QPair<QString, QByteArray> getAssetTypeAndData(const QFileInfo &fi) const; static QPair<QString, QByteArray> getAssetTypeAndData(const QString &assetPath);
Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos); Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos);
Q_INVOKABLE void startDragAsset(const QString &assetPath, const QPointF &mousePos); Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos);
Q_INVOKABLE void removeImport(const QString &importUrl); Q_INVOKABLE void removeImport(const QString &importUrl);
Q_INVOKABLE void addImportForItem(const QString &importUrl); Q_INVOKABLE void addImportForItem(const QString &importUrl);
Q_INVOKABLE void handleTabChanged(int index); Q_INVOKABLE void handleTabChanged(int index);
@@ -143,7 +143,7 @@ private:
AsynchronousImageCache &m_imageCache; AsynchronousImageCache &m_imageCache;
QPointer<Model> m_model; QPointer<Model> m_model;
QVariant m_itemToDrag; QVariant m_itemToDrag;
QString m_assetToDrag; QStringList m_assetsToDrag;
QPair<QString, QByteArray> m_assetToDragTypeAndData; QPair<QString, QByteArray> m_assetToDragTypeAndData;
bool m_updateRetry = false; bool m_updateRetry = false;
QString m_filterText; QString m_filterText;

View File

@@ -27,6 +27,7 @@
#include "navigatorview.h" #include "navigatorview.h"
#include "choosetexturepropertydialog.h" #include "choosetexturepropertydialog.h"
#include "qmldesignerplugin.h" #include "qmldesignerplugin.h"
#include "itemlibrarywidget.h"
#include <bindingproperty.h> #include <bindingproperty.h>
#include <designersettings.h> #include <designersettings.h>
@@ -484,39 +485,6 @@ QModelIndex NavigatorTreeModel::createIndexFromModelNode(int row, int column, co
return index; return index;
} }
bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
Qt::DropAction action,
int rowNumber,
int /*columnNumber*/,
const QModelIndex &dropModelIndex)
{
if (action == Qt::IgnoreAction)
return true;
if (m_reverseItemOrder)
rowNumber = rowCount(dropModelIndex) - rowNumber;
if (dropModelIndex.model() == this) {
if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.image")) {
handleItemLibraryImageDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.font")) {
handleItemLibraryFontDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.shader")) {
handleItemLibraryShaderDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.sound")) {
handleItemLibrarySoundDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.texture3d")) {
handleItemLibraryTexture3dDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat("application/vnd.modelnode.list")) {
handleInternalDrop(mimeData, rowNumber, dropModelIndex);
}
}
return false; // don't let the view do drag&drop on its own
}
static bool findTargetProperty(const QModelIndex &rowModelIndex, static bool findTargetProperty(const QModelIndex &rowModelIndex,
NavigatorTreeModel *navigatorTreeModel, NavigatorTreeModel *navigatorTreeModel,
NodeAbstractProperty *targetProperty, NodeAbstractProperty *targetProperty,
@@ -551,6 +519,62 @@ static bool findTargetProperty(const QModelIndex &rowModelIndex,
return true; return true;
} }
bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
Qt::DropAction action,
int rowNumber,
int /*columnNumber*/,
const QModelIndex &dropModelIndex)
{
if (action == Qt::IgnoreAction)
return true;
if (m_reverseItemOrder)
rowNumber = rowCount(dropModelIndex) - rowNumber;
if (dropModelIndex.model() == this) {
if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource")) {
QStringList assetsPaths = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")).split(",");
NodeAbstractProperty targetProperty;
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
int targetRowNumber = rowNumber;
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber);
if (foundTarget) {
QList<ModelNode> addedNodes;
ModelNode currNode;
for (const QString &assetPath : std::as_const(assetsPaths)) {
auto assetTypeAndData = ItemLibraryWidget::getAssetTypeAndData(assetPath);
QString assetType = assetTypeAndData.first;
QString assetData = QString::fromUtf8(assetTypeAndData.second);
if (assetType == "application/vnd.bauhaus.libraryresource.image")
currNode = handleItemLibraryImageDrop(assetPath, targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.font")
currNode = handleItemLibraryFontDrop(assetData, targetProperty, rowModelIndex); // assetData is fontFamily
else if (assetType == "application/vnd.bauhaus.libraryresource.shader")
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f", targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.sound")
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d")
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty, rowModelIndex);
if (currNode.isValid())
addedNodes.append(currNode);
}
if (!addedNodes.isEmpty()) {
moveNodesInteractive(targetProperty, addedNodes, rowNumber);
m_view->setSelectedModelNodes(addedNodes);
}
}
} else if (mimeData->hasFormat("application/vnd.modelnode.list")) {
handleInternalDrop(mimeData, rowNumber, dropModelIndex);
}
}
return false; // don't let the view do drag&drop on its own
}
void NavigatorTreeModel::handleInternalDrop(const QMimeData *mimeData, void NavigatorTreeModel::handleInternalDrop(const QMimeData *mimeData,
int rowNumber, int rowNumber,
const QModelIndex &dropModelIndex) const QModelIndex &dropModelIndex)
@@ -583,6 +607,7 @@ static ItemLibraryEntry createItemLibraryEntryFromMimeData(const QByteArray &dat
void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex) void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex)
{ {
QTC_ASSERT(m_view, return); QTC_ASSERT(m_view, return);
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
int targetRowNumber = rowNumber; int targetRowNumber = rowNumber;
NodeAbstractProperty targetProperty; NodeAbstractProperty targetProperty;
@@ -714,89 +739,72 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
} }
} }
void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex) ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath,
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
{ {
QTC_ASSERT(m_view, return); 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); ModelNode targetNode(modelNodeForIndex(rowModelIndex));
if (foundTarget) {
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
const QString imageSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")); // absolute path const QString imagePathRelative = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(imagePath); // relative to .ui.qml file
const QString imagePath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(imageSource); // relative to .ui.qml file
ModelNode newModelNode; ModelNode newModelNode;
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) { if (!dropAsImage3dTexture(targetNode, targetProperty, imagePathRelative, newModelNode)) {
if (targetNode.isSubclassOf("QtQuick.Image") if (targetNode.isSubclassOf("QtQuick.Image")
|| targetNode.isSubclassOf("QtQuick.BorderImage")) { || targetNode.isSubclassOf("QtQuick.BorderImage")) {
// if dropping an image on an existing image, set the source // if dropping an image on an existing image, set the source
targetNode.variantProperty("source").setValue(imagePath); targetNode.variantProperty("source").setValue(imagePathRelative);
} else { } else {
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryImageDrop", [&] { m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryImageDrop", [&] {
// create an image // create an image
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imageSource, QPointF(), targetProperty, false); QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imagePath, QPointF(), targetProperty, false);
if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode()))
newModelNode = newItemNode.modelNode();
else
newItemNode.destroy();
});
}
}
if (newModelNode.isValid()) {
moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber);
m_view->setSelectedModelNode(newModelNode);
}
}
}
void NavigatorTreeModel::handleItemLibraryFontDrop(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);
if (foundTarget) {
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
const QString fontFamily = QString::fromUtf8(
mimeData->data("application/vnd.bauhaus.libraryresource.font"));
ModelNode newModelNode;
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryFontDrop", [&] {
if (targetNode.isSubclassOf("QtQuick.Text")) {
// if dropping into an existing Text, update font
targetNode.variantProperty("font.family").setValue(fontFamily);
} else {
// create a Text node
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromFont(
m_view, fontFamily, QPointF(), targetProperty, false);
if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode())) if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode()))
newModelNode = newItemNode.modelNode(); newModelNode = newItemNode.modelNode();
else else
newItemNode.destroy(); newItemNode.destroy();
} });
});
if (newModelNode.isValid()) {
moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber);
m_view->setSelectedModelNode(newModelNode);
} }
} }
return newModelNode;
} }
void NavigatorTreeModel::handleItemLibraryShaderDrop(const QMimeData *mimeData, int rowNumber, ModelNode NavigatorTreeModel::handleItemLibraryFontDrop(const QString &fontFamily,
const QModelIndex &dropModelIndex) NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
{ {
QTC_ASSERT(m_view, return); QTC_ASSERT(m_view, return {});
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
ModelNode newModelNode;
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryFontDrop", [&] {
if (targetNode.isSubclassOf("QtQuick.Text")) {
// if dropping into an existing Text, update font
targetNode.variantProperty("font.family").setValue(fontFamily);
} else {
// create a Text node
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromFont(
m_view, fontFamily, QPointF(), targetProperty, false);
if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode()))
newModelNode = newItemNode.modelNode();
else
newItemNode.destroy();
}
});
return newModelNode;
}
ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
{
QTC_ASSERT(m_view, return {});
Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D")); Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D"));
bool addImport = false; bool addImport = false;
if (!m_view->model()->hasImport(import, true, true)) { if (!m_view->model()->hasImport(import, true, true)) {
@@ -811,68 +819,56 @@ void NavigatorTreeModel::handleItemLibraryShaderDrop(const QMimeData *mimeData,
} }
} }
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); ModelNode targetNode(modelNodeForIndex(rowModelIndex));
int targetRowNumber = rowNumber; ModelNode newModelNode;
NodeAbstractProperty targetProperty;
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(shaderPath);
if (foundTarget) {
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
ModelNode newModelNode;
const QString shaderSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")); m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] {
const bool fragShader = mimeData->data("application/vnd.bauhaus.libraryresource.shader").startsWith('f'); if (targetNode.isSubclassOf("QtQuick3D.Shader")) {
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(shaderSource); // if dropping into an existing Shader, update
targetNode.variantProperty("stage").setEnumeration(isFragShader ? "Shader.Fragment"
: "Shader.Vertex");
targetNode.variantProperty("shader").setValue(relPath);
} else {
// create a new Shader
ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setName("Shader");
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] { // set shader properties
if (targetNode.isSubclassOf("QtQuick3D.Shader")) { PropertyName prop = "shader";
// if dropping into an existing Shader, update QString type = "QByteArray";
if (fragShader) QVariant val = relPath;
targetNode.variantProperty("stage").setEnumeration("Shader.Fragment"); itemLibraryEntry.addProperty(prop, type, val);
else prop = "stage";
targetNode.variantProperty("stage").setEnumeration("Shader.Vertex"); type = "enum";
targetNode.variantProperty("shader").setValue(relPath); val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
} else { itemLibraryEntry.addProperty(prop, type, val);
// create a new Shader
ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setName("Shader");
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
// set shader properties // create a texture
PropertyName prop = "shader"; newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
QString type = "QByteArray"; targetProperty, false);
QVariant val = relPath;
itemLibraryEntry.addProperty(prop, type, val);
prop = "stage";
type = "enum";
val = fragShader ? "Shader.Fragment" : "Shader.Vertex";
itemLibraryEntry.addProperty(prop, type, val);
// create a texture // Rename the node based on shader source
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, QFileInfo fi(relPath);
targetProperty, false); newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"shader"));
// Rename the node based on shader source
QFileInfo fi(relPath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"shader"));
}
});
if (newModelNode.isValid()) {
moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber);
m_view->setSelectedModelNode(newModelNode);
} }
});
if (addImport) if (addImport)
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
}
return newModelNode;
} }
void NavigatorTreeModel::handleItemLibrarySoundDrop(const QMimeData *mimeData, int rowNumber, ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPath,
const QModelIndex &dropModelIndex) NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
{ {
QTC_ASSERT(m_view, return); QTC_ASSERT(m_view, return {});
Import import = Import::createLibraryImport(QStringLiteral("QtMultimedia")); Import import = Import::createLibraryImport(QStringLiteral("QtMultimedia"));
bool addImport = false; bool addImport = false;
if (!m_view->model()->hasImport(import, true, true)) { if (!m_view->model()->hasImport(import, true, true)) {
@@ -887,92 +883,71 @@ void NavigatorTreeModel::handleItemLibrarySoundDrop(const QMimeData *mimeData, i
} }
} }
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); ModelNode targetNode(modelNodeForIndex(rowModelIndex));
int targetRowNumber = rowNumber; ModelNode newModelNode;
NodeAbstractProperty targetProperty;
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(soundPath);
if (foundTarget) {
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
ModelNode newModelNode;
const QString soundSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")); m_view->executeInTransaction("NavigatorTreeModel::handleItemLibrarySoundDrop", [&] {
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(soundSource); if (targetNode.isSubclassOf("QtMultimedia.SoundEffect")) {
// if dropping into on an existing SoundEffect, update
targetNode.variantProperty("source").setValue(relPath);
} else {
// create a new SoundEffect
ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setName("SoundEffect");
itemLibraryEntry.setType("QtMultimedia.SoundEffect", 1, 0);
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibrarySoundDrop", [&] { // set source property
if (targetNode.isSubclassOf("QtMultimedia.SoundEffect")) { PropertyName prop = "source";
// if dropping into on an existing SoundEffect, update QString type = "QUrl";
targetNode.variantProperty("source").setValue(relPath); QVariant val = relPath;
} else { itemLibraryEntry.addProperty(prop, type, val);
// create a new SoundEffect
ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setName("SoundEffect");
itemLibraryEntry.setType("QtMultimedia.SoundEffect", 1, 0);
// set shader properties // create a texture
PropertyName prop = "source"; newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
QString type = "QUrl"; targetProperty, false);
QVariant val = relPath;
itemLibraryEntry.addProperty(prop, type, val);
// create a texture // Rename the node based on source
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, QFileInfo fi(relPath);
targetProperty, false); newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"soundEffect"));
// Rename the node based on source
QFileInfo fi(relPath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"soundEffect"));
}
});
if (newModelNode.isValid()) {
moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber);
m_view->setSelectedModelNode(newModelNode);
} }
});
if (addImport) if (addImport)
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
}
return newModelNode;
} }
void NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QMimeData *mimeData, int rowNumber, ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3DPath,
const QModelIndex &dropModelIndex) NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
{ {
QTC_ASSERT(m_view, return); QTC_ASSERT(m_view, return {});
Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D")); Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D"));
if (!m_view->model()->hasImport(import, true, true)) if (!m_view->model()->hasImport(import, true, true))
return; return {};
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); ModelNode targetNode(modelNodeForIndex(rowModelIndex));
int targetRowNumber = rowNumber;
NodeAbstractProperty targetProperty;
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber); const QString imagePath = DocumentManager::currentFilePath().toFileInfo().dir()
if (foundTarget) { .relativeFilePath(tex3DPath); // relative to qml file
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
const QString imageSource = QString::fromUtf8( ModelNode newModelNode;
mimeData->data("application/vnd.bauhaus.libraryresource")); // absolute path
const QString imagePath = DocumentManager::currentFilePath().toFileInfo().dir()
.relativeFilePath(imageSource); // relative to qml file
ModelNode newModelNode; if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) {
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] {
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) { // create a standalone Texture3D at drop location
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] { newModelNode = createTextureNode(targetProperty, imagePath);
// create a standalone Texture3D at drop location if (!NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newModelNode))
newModelNode = createTextureNode(targetProperty, imagePath); newModelNode.destroy();
if (!NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newModelNode)) });
newModelNode.destroy();
});
}
if (newModelNode.isValid()) {
moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber);
m_view->setSelectedModelNode(newModelNode);
}
} }
return newModelNode;
} }
bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode, bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,

View File

@@ -114,11 +114,16 @@ 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 handleItemLibraryImageDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); ModelNode handleItemLibraryImageDrop(const QString &imagePath, NodeAbstractProperty targetProperty,
void handleItemLibraryFontDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); const QModelIndex &rowModelIndex);
void handleItemLibraryShaderDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty,
void handleItemLibrarySoundDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); const QModelIndex &rowModelIndex);
void handleItemLibraryTexture3dDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex); ModelNode handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
NodeAbstractProperty targetProperty, const QModelIndex &rowModelIndex);
ModelNode handleItemLibrarySoundDrop(const QString &soundPath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp, bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp,
const QString &imagePath, ModelNode &newNode); const QString &imagePath, ModelNode &newNode);
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath); ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);

View File

@@ -161,6 +161,7 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromFont(AbstractView *view,
propertyPairList.append({PropertyName("x"), QVariant(qRound(position.x()))}); propertyPairList.append({PropertyName("x"), QVariant(qRound(position.x()))});
propertyPairList.append({PropertyName("y"), QVariant(qRound(position.y()))}); propertyPairList.append({PropertyName("y"), QVariant(qRound(position.y()))});
propertyPairList.append({PropertyName("font.family"), QVariant(fontFamily)}); propertyPairList.append({PropertyName("font.family"), QVariant(fontFamily)});
propertyPairList.append({PropertyName("font.pointSize"), 20});
propertyPairList.append({PropertyName("text"), QVariant(fontFamily)}); propertyPairList.append({PropertyName("text"), QVariant(fontFamily)});
newQmlItemNode = QmlItemNode(view->createModelNode("QtQuick.Text", metaInfo.majorVersion(), newQmlItemNode = QmlItemNode(view->createModelNode("QtQuick.Text", metaInfo.majorVersion(),