forked from qt-creator/qt-creator
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:
@@ -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
|
||||||
@@ -697,10 +704,10 @@ Item {
|
|||||||
view3D: overlayView
|
view3D: overlayView
|
||||||
dragHelper: gizmoDragHelper
|
dragHelper: gizmoDragHelper
|
||||||
|
|
||||||
onPropertyValueCommit: (propName)=> {
|
onPropertyValueCommit: (propName) => {
|
||||||
viewRoot.commitObjectProperty([targetNode], [propName]);
|
viewRoot.commitObjectProperty([targetNode], [propName]);
|
||||||
}
|
}
|
||||||
onPropertyValueChange: (propName)=> {
|
onPropertyValueChange: (propName) => {
|
||||||
viewRoot.changeObjectProperty([targetNode], [propName]);
|
viewRoot.changeObjectProperty([targetNode], [propName]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -772,17 +779,17 @@ 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
|
||||||
property point pressPoint
|
property point pressPoint
|
||||||
property bool initialMoveBlock: false
|
property bool initialMoveBlock: false
|
||||||
|
|
||||||
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) {
|
||||||
@@ -800,7 +807,7 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPositionChanged: (mouse)=> {
|
onPositionChanged: (mouse) => {
|
||||||
if (freeDraggerArea) {
|
if (freeDraggerArea) {
|
||||||
if (initialMoveBlock && Math.abs(pressPoint.x - mouse.x) + Math.abs(pressPoint.y - mouse.y) > 10) {
|
if (initialMoveBlock && Math.abs(pressPoint.x - mouse.x) + Math.abs(pressPoint.y - mouse.y) > 10) {
|
||||||
// Don't force press event at actual press, as that puts the gizmo
|
// Don't force press event at actual press, as that puts the gizmo
|
||||||
@@ -825,10 +832,10 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onReleased: (mouse)=> {
|
onReleased: (mouse) => {
|
||||||
handleRelease(mouse);
|
handleRelease(mouse);
|
||||||
}
|
}
|
||||||
onCanceled: (mouse)=> {
|
onCanceled: (mouse) => {
|
||||||
handleRelease(mouse);
|
handleRelease(mouse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
@@ -841,10 +848,10 @@ Item {
|
|||||||
view3D: overlayView
|
view3D: overlayView
|
||||||
dragHelper: gizmoDragHelper
|
dragHelper: gizmoDragHelper
|
||||||
|
|
||||||
onPropertyValueCommit: (propName)=> {
|
onPropertyValueCommit: (propName) => {
|
||||||
viewRoot.commitObjectProperty([targetNode], [propName]);
|
viewRoot.commitObjectProperty([targetNode], [propName]);
|
||||||
}
|
}
|
||||||
onPropertyValueChange: (propName)=> {
|
onPropertyValueChange: (propName) => {
|
||||||
viewRoot.changeObjectProperty([targetNode], [propName]);
|
viewRoot.changeObjectProperty([targetNode], [propName]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -917,14 +924,14 @@ 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
|
||||||
property point pressPoint
|
property point pressPoint
|
||||||
property bool initialMoveBlock: false
|
property bool initialMoveBlock: false
|
||||||
|
|
||||||
onPressed: (mouse)=> {
|
onPressed: (mouse) => {
|
||||||
if (viewRoot.editView) {
|
if (viewRoot.editView) {
|
||||||
// First pick overlay to check for hits there
|
// First pick overlay to check for hits there
|
||||||
var pickResult = _generalHelper.pickViewAt(overlayView, mouse.x, mouse.y);
|
var pickResult = _generalHelper.pickViewAt(overlayView, mouse.x, mouse.y);
|
||||||
@@ -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)
|
||||||
@@ -952,7 +959,7 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPositionChanged: (mouse)=> {
|
onPositionChanged: (mouse) => {
|
||||||
if (freeDraggerArea) {
|
if (freeDraggerArea) {
|
||||||
if (initialMoveBlock && Math.abs(pressPoint.x - mouse.x) + Math.abs(pressPoint.y - mouse.y) > 10) {
|
if (initialMoveBlock && Math.abs(pressPoint.x - mouse.x) + Math.abs(pressPoint.y - mouse.y) > 10) {
|
||||||
// Don't force press event at actual press, as that puts the gizmo
|
// Don't force press event at actual press, as that puts the gizmo
|
||||||
@@ -977,10 +984,10 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onReleased: (mouse)=> {
|
onReleased: (mouse) => {
|
||||||
handleRelease(mouse);
|
handleRelease(mouse);
|
||||||
}
|
}
|
||||||
onCanceled: (mouse)=> {
|
onCanceled: (mouse) => {
|
||||||
handleRelease(mouse);
|
handleRelease(mouse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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()) {
|
||||||
|
@@ -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));
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user