diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h index 54729d9075a..c59bef9ace3 100644 --- a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h +++ b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h @@ -39,6 +39,8 @@ inline constexpr char resetPositionCommandId[] = "ResetPosition"; inline constexpr char copyFormatCommandId[] = "CopyFormat"; inline constexpr char applyFormatCommandId[] = "ApplyFormat"; inline constexpr char visiblityCommandId[] = "ToggleVisiblity"; +inline constexpr char isolateSelectionCommandId[] = "IsolateSelection"; +inline constexpr char showAllCommandId[] = "ShowAll"; inline constexpr char anchorsFillCommandId[] = "AnchorsFill"; inline constexpr char anchorsResetCommandId[] = "AnchorsReset"; @@ -142,7 +144,10 @@ inline constexpr char redoDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextM inline constexpr char visibilityDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Visibility"); - +inline constexpr char isolateSelectionDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", + "Isolate Selection"); +inline constexpr char showAllDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", + "Show All Nodes"); inline constexpr char resetSizeDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Reset Size"); inline constexpr char resetPositionDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", @@ -266,6 +271,10 @@ inline constexpr char lowerToolTip[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu inline constexpr char resetSizeToolTip[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Reset size and use implicit size."); +inline constexpr char isolateNodesToolTip[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", + "Show selected nodes only."); +inline constexpr char showAllToolTip[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", + "Show all nodes."); inline constexpr char resetPositionTooltip[] = QT_TRANSLATE_NOOP( "QmlDesignerContextMenu", "Reset position and use implicit position."); inline constexpr char copyFormatTooltip[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", @@ -330,6 +339,8 @@ enum PrioritiesEnum : int { ResetView, Group, Visibility, + IsolateSelection, + ShowAllNodes, ShowBoundingRect, /******** Section *****************************/ CustomActionsSection = 6000, diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index 6cb88e5f411..2c79c0f9580 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -1515,6 +1515,28 @@ void DesignerActionManager::createDefaultDesignerActions() &resetSize, &selectionNotEmptyAndHasWidthOrHeightProperty)); + addDesignerAction(new ModelNodeAction( + isolateSelectionCommandId, + isolateSelectionDisplayName, + contextIcon(DesignerIcons::VisibilityIcon), // TODO: placeholder icon + isolateNodesToolTip, + rootCategory, + QKeySequence("shift+h"), + Priorities::IsolateSelection, + &isolateSelectedNodes, + &selectionNot2D3DMix)); + + addDesignerAction(new ModelNodeAction( + showAllCommandId, + showAllDisplayName, + contextIcon(DesignerIcons::VisibilityIcon), // TODO: placeholder icon + showAllToolTip, + rootCategory, + QKeySequence("alt+h"), + Priorities::ShowAllNodes, + &showAllNodes, + &always)); + addDesignerAction(new SeparatorDesignerAction(editCategory, 40)); addDesignerAction(new VisiblityModelNodeAction( diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h index fbf27083127..f645975d0fd 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h +++ b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.h @@ -4,14 +4,15 @@ #pragma once #include "abstractaction.h" -#include "bindingproperty.h" #include "abstractactiongroup.h" -#include "qmlitemnode.h" -#include -#include +#include "utils3d.h" +#include #include #include +#include +#include +#include #include @@ -113,6 +114,23 @@ inline bool selectionNotEmpty(const SelectionContext &selectionState) return !selectionState.selectedModelNodes().isEmpty(); } +inline bool selectionNot2D3DMix(const SelectionContext &selectionState) +{ + const QList selectedNodes = selectionState.view()->selectedModelNodes(); + if (selectedNodes.size() <= 1) + return true; + + ModelNode active3DScene = Utils3D::active3DSceneNode(selectionState.view()); + bool isFirstNode3D = active3DScene.isAncestorOf(selectedNodes.first()); + + for (const ModelNode &node : selectedNodes) { + if (active3DScene.isAncestorOf(node) != isFirstNode3D) + return false; + } + + return true; +} + inline bool singleSelectionNotRoot(const SelectionContext &selectionState) { return selectionState.singleNodeIsSelected() diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index cd67e806dd8..9210554c4bd 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -279,6 +279,82 @@ void setVisible(const SelectionContext &selectionState) } } +static QSet collectAncestorsAndDescendants(AbstractView *view, const ModelNode &node) +{ + QSet keepVisible; + + ModelNode ancestor = node.parentProperty().parentModelNode(); + while (ancestor && ancestor != view->rootModelNode()) { + keepVisible.insert(ancestor); + if (!ancestor.hasParentProperty()) + break; + ancestor = ancestor.parentProperty().parentModelNode(); + } + + const QList descendants = node.allSubModelNodes(); + for (const ModelNode &subNode : descendants) + keepVisible.insert(subNode); + + return keepVisible; +} + +void isolateSelectedNodes(const SelectionContext &selectionState) +{ + AbstractView *view = selectionState.view(); + const QList selectedNodes = view->selectedModelNodes(); + + if (selectedNodes.isEmpty() || view->rootModelNode().isSelected()) + return; + + const QList allModelNodes = view->allModelNodes(); + ModelNode active3DScene = Utils3D::active3DSceneNode(view); + QSet nodesToKeepVisible({view->rootModelNode()}); + + for (const ModelNode &node : selectedNodes) { + nodesToKeepVisible.insert(node); + nodesToKeepVisible.unite(collectAncestorsAndDescendants(view, node)); + } + + auto hideNode = [](const ModelNode &node) { + QmlVisualNode(node).setVisibilityOverride(true); + }; + + auto doNotHideSubNodes = [&nodesToKeepVisible](const ModelNode &node) { + if (node.hasAnySubModelNodes()) { + const QList allSubModelNodes = node.allSubModelNodes(); + for (const ModelNode &subNode : allSubModelNodes) + nodesToKeepVisible.insert(subNode); + } + }; + + const bool is3DSelection = active3DScene.isAncestorOf(selectedNodes.first()); + const QList nodesToProcess = is3DSelection ? active3DScene.allSubModelNodes() + : allModelNodes; + + for (const ModelNode &node : nodesToProcess) { + if (nodesToKeepVisible.contains(node)) + continue; + + if (!is3DSelection) { + NodeHints hint = NodeHints::fromModelNode(node); + if (!((node && !hint.hideInNavigator()) || hint.visibleInNavigator()) + || node.id() == Constants::MATERIAL_LIB_ID) { + continue; + } + } + + doNotHideSubNodes(node); // makes sure only the top-most node in the hierarchy is hidden + hideNode(node); + } +} + +void showAllNodes(const SelectionContext &selectionState) +{ + const QList allModelNodes = selectionState.view()->allModelNodes(); + for (const ModelNode &node : allModelNodes) + QmlVisualNode(node).setVisibilityOverride(false); +} + void setFillWidth(const SelectionContext &selectionState) { if (!selectionState.view() diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h index 54fea337e36..4d16549c95d 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h @@ -73,6 +73,8 @@ void paste(const SelectionContext &selectionState); void undo(const SelectionContext &selectionState); void redo(const SelectionContext &selectionState); void setVisible(const SelectionContext &selectionState); +void isolateSelectedNodes(const SelectionContext &selectionState); +void showAllNodes(const SelectionContext &selectionState); void setFillWidth(const SelectionContext &selectionState); void setFillHeight(const SelectionContext &selectionState); void resetSize(const SelectionContext &selectionState);