QmlDesigner: Add delete action to 3D Editor's context menu

This entails selecting a model upon right-clicking if it is not selected.
Also fixed a memory leak and small tweaks.

Fixes: QDS-7401
Change-Id: I592acb3fff30ecc3236f3cf2fbe126de4fb389dc
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2022-08-23 15:19:56 +03:00
parent f6e8b5f753
commit 8656bafbd4
6 changed files with 51 additions and 25 deletions

View File

@@ -363,7 +363,7 @@ Item {
} }
} }
function handleObjectClicked(object, multi) function handleObjectClicked(object, button, multi)
{ {
if (object instanceof View3D) { if (object instanceof View3D) {
// View3D can be the resolved pick target in case the 3D editor is showing content // View3D can be the resolved pick target in case the 3D editor is showing content
@@ -393,7 +393,14 @@ Item {
// Null object always clears entire selection // Null object always clears entire selection
var newSelection = []; var newSelection = [];
if (clickedObject) { if (clickedObject) {
if (multi && selectedNodes.length > 0) { if (button === Qt.RightButton) {
// Right-clicking does only single selection (when clickedObject is unselected)
// This is needed for selecting a target for the context menu
if (!selectedNodes.includes(clickedObject))
newSelection[0] = clickedObject;
else
newSelection = selectedNodes;
} else if (multi && selectedNodes.length > 0) {
var deselect = false; var deselect = false;
for (var i = 0; i < selectedNodes.length; ++i) { for (var i = 0; i < selectedNodes.length; ++i) {
// Multiselecting already selected object clears that object from selection // Multiselecting already selected object clears that object from selection
@@ -772,7 +779,7 @@ Item {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: false hoverEnabled: false
property MouseArea3D freeDraggerArea property MouseArea3D freeDraggerArea
@@ -782,7 +789,7 @@ Item {
onPressed: (mouse) => { onPressed: (mouse) => {
if (viewRoot.editView) { if (viewRoot.editView) {
var pickResult = viewRoot.editView.pick(mouse.x, mouse.y); var pickResult = viewRoot.editView.pick(mouse.x, mouse.y);
handleObjectClicked(_generalHelper.resolvePick(pickResult.objectHit), handleObjectClicked(_generalHelper.resolvePick(pickResult.objectHit), mouse.button,
mouse.modifiers & Qt.ControlModifier); mouse.modifiers & Qt.ControlModifier);
if (pickResult.objectHit && pickResult.objectHit instanceof Node) { if (pickResult.objectHit && pickResult.objectHit instanceof Node) {

View File

@@ -363,7 +363,7 @@ Item {
} }
} }
function handleObjectClicked(object, multi) function handleObjectClicked(object, button, multi)
{ {
if (object instanceof View3D) { if (object instanceof View3D) {
// View3D can be the resolved pick target in case the 3D editor is showing content // View3D can be the resolved pick target in case the 3D editor is showing content
@@ -393,7 +393,14 @@ Item {
// Null object always clears entire selection // Null object always clears entire selection
var newSelection = []; var newSelection = [];
if (clickedObject) { if (clickedObject) {
if (multi && selectedNodes.length > 0) { if (button === Qt.RightButton) {
// Right-clicking does only single selection (when clickedObject is unselected)
// This is needed for selecting a target for the context menu
if (!selectedNodes.includes(clickedObject))
newSelection[0] = clickedObject;
else
newSelection = selectedNodes;
} else if (multi && selectedNodes.length > 0) {
var deselect = false; var deselect = false;
for (var i = 0; i < selectedNodes.length; ++i) { for (var i = 0; i < selectedNodes.length; ++i) {
// Multiselecting already selected object clears that object from selection // Multiselecting already selected object clears that object from selection
@@ -917,7 +924,7 @@ Item {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: false hoverEnabled: false
property MouseArea3D freeDraggerArea property MouseArea3D freeDraggerArea
@@ -935,7 +942,7 @@ Item {
resolvedResult = _generalHelper.resolvePick(pickResult.objectHit); resolvedResult = _generalHelper.resolvePick(pickResult.objectHit);
} }
handleObjectClicked(resolvedResult, mouse.modifiers & Qt.ControlModifier); handleObjectClicked(resolvedResult, mouse.button, mouse.modifiers & Qt.ControlModifier);
if (pickResult.objectHit && pickResult.objectHit instanceof Node) { if (pickResult.objectHit && pickResult.objectHit instanceof Node) {
if (transformMode === EditView3D.TransformMode.Move) if (transformMode === EditView3D.TransformMode.Move)

View File

@@ -285,12 +285,12 @@ void Qt5InformationNodeInstanceServer::handleInputEvents()
continue; continue;
} }
} }
auto me = new QMouseEvent(command.type(), command.pos(), command.button(), QMouseEvent me(command.type(), command.pos(), command.button(), command.buttons(),
command.buttons(), command.modifiers()); command.modifiers());
// We must use sendEvent in Qt 6, as using postEvent allows the associated position // We must use sendEvent in Qt 6, as using postEvent allows the associated position
// data stored internally in QMutableEventPoint to potentially be updated by system // data stored internally in QMutableEventPoint to potentially be updated by system
// before the event is delivered. // before the event is delivered.
QGuiApplication::sendEvent(m_editView3DData.window, me); QGuiApplication::sendEvent(m_editView3DData.window, &me);
// Context menu requested // Context menu requested
if (command.button() == Qt::RightButton && command.modifiers() == Qt::NoModifier) if (command.button() == Qt::RightButton && command.modifiers() == Qt::NoModifier)
@@ -428,7 +428,8 @@ void Qt5InformationNodeInstanceServer::getModelAtPos(const QPointF &pos)
QVariant instance = resolvedPick ? instanceForObject(resolvedPick).instanceId() : -1; QVariant instance = resolvedPick ? instanceForObject(resolvedPick).instanceId() : -1;
nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::ModelAtPos, instance}); nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::ModelAtPos, instance});
return; #else
Q_UNUSED(pos)
#endif #endif
} }

View File

@@ -249,6 +249,10 @@ void Edit3DView::customNotification(const AbstractView *view, const QString &ide
void Edit3DView::modelAtPosReady(const ModelNode &modelNode) void Edit3DView::modelAtPosReady(const ModelNode &modelNode)
{ {
if (m_modelAtPosReqType == ModelAtPosReqType::ContextMenu) { if (m_modelAtPosReqType == ModelAtPosReqType::ContextMenu) {
// Make sure right-clicked item is selected. Due to a bug in puppet side right-clicking an item
// while the context-menu is shown doesn't select the item.
if (modelNode.isValid() && !modelNode.isSelected())
setSelectedModelNode(modelNode);
m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode); m_edit3DWidget->showContextMenu(m_contextMenuPos, modelNode);
} else if (m_modelAtPosReqType == ModelAtPosReqType::MaterialDrop) { } else if (m_modelAtPosReqType == ModelAtPosReqType::MaterialDrop) {
if (m_droppedMaterial.isValid() && modelNode.isValid()) { if (m_droppedMaterial.isValid() && modelNode.isValid()) {

View File

@@ -185,7 +185,12 @@ void Edit3DWidget::createContextMenu()
ModelNodeOperations::editMaterial(selCtx); ModelNodeOperations::editMaterial(selCtx);
}); });
// TODO: add more actions: delete, create, etc m_deleteAction = m_contextMenu->addAction(tr("Delete"), [&] {
view()->executeInTransaction("Edit3DWidget::createContextMenu", [&] {
for (ModelNode &node : m_view->selectedModelNodes())
node.destroy();
});
});
} }
void Edit3DWidget::contextHelp(const Core::IContext::HelpCallback &callback) const void Edit3DWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
@@ -241,6 +246,7 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode
m_contextMenuTarget = modelNode; m_contextMenuTarget = modelNode;
m_editMaterialAction->setEnabled(modelNode.isValid()); m_editMaterialAction->setEnabled(modelNode.isValid());
m_deleteAction->setEnabled(modelNode.isValid());
m_contextMenu->popup(mapToGlobal(pos)); m_contextMenu->popup(mapToGlobal(pos));
} }

View File

@@ -76,6 +76,7 @@ private:
QPointer<QMenu> m_backgroundColorMenu; QPointer<QMenu> m_backgroundColorMenu;
QPointer<QMenu> m_contextMenu; QPointer<QMenu> m_contextMenu;
QPointer<QAction> m_editMaterialAction; QPointer<QAction> m_editMaterialAction;
QPointer<QAction> m_deleteAction;
ModelNode m_contextMenuTarget; ModelNode m_contextMenuTarget;
}; };