Gui: add 'Select group contents' context menu item (#22082)

* Gui: add 'Select group contents' context menu item

* Gui: remove dependency from Draft icon
This commit is contained in:
Furgo
2025-07-28 00:44:12 +02:00
committed by GitHub
parent 5c2b5507d6
commit f2e9a7f62e
4 changed files with 505 additions and 0 deletions

View File

@@ -0,0 +1,450 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
id="svg3612"
height="64px"
width="64px">
<defs
id="defs3614">
<marker
style="overflow:visible"
id="Arrow1Lstart"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.8) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path3809" />
</marker>
<linearGradient
id="linearGradient3144-6">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:1"
id="stop3146-9" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop3148-2" />
</linearGradient>
<linearGradient
id="linearGradient3701">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:1"
id="stop3703" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop3705" />
</linearGradient>
<radialGradient
r="34.345188"
fy="672.79736"
fx="225.26402"
cy="672.79736"
cx="225.26402"
gradientTransform="matrix(1,0,0,0.6985294,0,202.82863)"
gradientUnits="userSpaceOnUse"
id="radialGradient3688"
xlink:href="#linearGradient3144-6" />
<linearGradient
id="linearGradient3708">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:1"
id="stop3710" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0"
id="stop3712" />
</linearGradient>
<linearGradient
id="linearGradient3864-0-0">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-5-7" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-7-6" />
</linearGradient>
<linearGradient
id="linearGradient3377">
<stop
style="stop-color:#ffaa00;stop-opacity:1;"
offset="0"
id="stop3379" />
<stop
style="stop-color:#faff2b;stop-opacity:1;"
offset="1"
id="stop3381" />
</linearGradient>
<linearGradient
id="linearGradient3864-0">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-5" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-7" />
</linearGradient>
<linearGradient
id="linearGradient5048">
<stop
id="stop5050"
offset="0"
style="stop-color:black;stop-opacity:0;" />
<stop
style="stop-color:black;stop-opacity:1;"
offset="0.5"
id="stop5056" />
<stop
id="stop5052"
offset="1"
style="stop-color:black;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient3841-0-3">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3843-1-3" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3845-0-8" />
</linearGradient>
<radialGradient
id="aigrd2"
cx="20.892099"
cy="114.5684"
r="5.256"
fx="20.892099"
fy="114.5684"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#F0F0F0"
id="stop15566" />
<stop
offset="1.0000000"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
id="stop15568" />
</radialGradient>
<radialGradient
id="aigrd3"
cx="20.892099"
cy="64.567902"
r="5.257"
fx="20.892099"
fy="64.567902"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#F0F0F0"
id="stop15573" />
<stop
offset="1.0000000"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
id="stop15575" />
</radialGradient>
<linearGradient
id="linearGradient15662">
<stop
id="stop15664"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop15666"
offset="1.0000000"
style="stop-color:#f8f8f8;stop-opacity:1.0000000;" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient259"
id="radialGradient4452"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.96049297,0,0,1.041132,-52.144249,-702.33158)"
cx="33.966679"
cy="35.736916"
fx="33.966679"
fy="35.736916"
r="86.70845" />
<linearGradient
id="linearGradient259">
<stop
id="stop260"
offset="0.0000000"
style="stop-color:#fafafa;stop-opacity:1.0000000;" />
<stop
id="stop261"
offset="1.0000000"
style="stop-color:#bbbbbb;stop-opacity:1.0000000;" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient269"
id="radialGradient4454"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.96827297,0,0,1.032767,-48.790699,-701.68513)"
cx="8.824419"
cy="3.7561285"
fx="8.824419"
fy="3.7561285"
r="37.751713" />
<linearGradient
id="linearGradient269">
<stop
id="stop270"
offset="0.0000000"
style="stop-color:#a3a3a3;stop-opacity:1.0000000;" />
<stop
id="stop271"
offset="1.0000000"
style="stop-color:#4c4c4c;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
id="linearGradient4095">
<stop
id="stop4097"
offset="0"
style="stop-color:#005bff;stop-opacity:1;" />
<stop
id="stop4099"
offset="1"
style="stop-color:#c1e3f7;stop-opacity:1;" />
</linearGradient>
<linearGradient
gradientTransform="matrix(0.94231826,0,0,0.94231826,23.727549,8.8262536)"
gradientUnits="userSpaceOnUse"
y2="140.22731"
x2="434.73947"
y1="185.1304"
x1="394.15784"
id="linearGradient4253"
xlink:href="#linearGradient4247" />
<linearGradient
id="linearGradient4247">
<stop
id="stop4249"
offset="0"
style="stop-color:#2e8207;stop-opacity:1;" />
<stop
id="stop4251"
offset="1"
style="stop-color:#52ff00;stop-opacity:1;" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient4247"
id="linearGradient5087"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.94231826,0,0,0.94231826,23.727549,8.8262536)"
x1="394.15784"
y1="185.1304"
x2="434.73947"
y2="140.22731" />
</defs>
<g
id="layer1">
<path
style="fill:none;stroke:#2e3436;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 8.999987,12.999996 0,32 14.000001,0"
id="path5098-3" />
<path
style="fill:none;stroke:#2e3436;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 23,29 8.999999,29"
id="path5100-6" />
<path
style="fill:none;stroke:#d3d7cf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 8.999987,12.999996 0,32 14.000001,0"
id="path5098-1" />
<path
style="fill:none;stroke:#d3d7cf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 23,29 8.999999,29"
id="path5100-7" />
<rect
style="color:#000000;fill:#eeeeec;stroke:#2e3436;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect4258-1-7-4-4"
width="37.999989"
height="10"
x="3"
y="3"
rx="0"
ry="0" />
<rect
style="color:#000000;fill:#3465a4;stroke:#0b1521;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect4258-1-7-4-7"
width="28"
height="10"
x="23"
y="25"
rx="0"
ry="0" />
<rect
y="27"
x="24.806452"
height="5.9999914"
width="24.387096"
id="rect3852"
style="fill:#3465a4;fill-opacity:1;stroke:#729fcf;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<rect
y="5"
x="5"
height="6"
width="34"
id="rect3852-5-3"
style="fill:#d3d7cf;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<rect
style="color:#000000;fill:#3465a4;stroke:#0b1521;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect4258-1-7-4-7-0"
width="28"
height="10"
x="23"
y="41"
rx="0"
ry="0" />
<rect
y="43"
x="24.806452"
height="6"
width="24.387094"
id="rect3852-9"
style="fill:#3465a4;fill-opacity:1;stroke:#729fcf;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
id="path3953-1"
d="m 20.999999,19 4,0"
style="fill:none;stroke:#204a87;stroke-width:5.99999952000000030;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3957-5"
d="M 53.000001,19 C 57,19 57,19 57,19"
style="fill:none;stroke:#204a87;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-1"
d="m 20.999999,19 4,0"
style="fill:none;stroke:#729fcf;stroke-width:1.99999988000000010;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3957-5-8"
d="M 53.000001,19 C 57,19 57,19 57,19"
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-5"
d="m 37,19 4,0"
style="fill:none;stroke:#204a87;stroke-width:5.99999952000000030;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-1-7"
d="m 37,19 4,0"
style="fill:none;stroke:#729fcf;stroke-width:1.99999988000000010;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-6"
d="m 19,57 4,0"
style="fill:none;stroke:#204a87;stroke-width:5.99999952000000030;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3957-5-1"
d="m 51.000002,57 c 3.999999,0 3.999999,0 3.999999,0"
style="fill:none;stroke:#204a87;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-1-8"
d="m 19,57 4,0"
style="fill:none;stroke:#729fcf;stroke-width:1.99999988000000010;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3957-5-8-9"
d="m 51.000002,57 c 3.999999,0 3.999999,0 3.999999,0"
style="fill:none;stroke:#729fcf;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-5-2"
d="m 35.000001,57 4,0"
style="fill:none;stroke:#204a87;stroke-width:5.99999952000000030;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-1-7-7"
d="m 35.000001,57 4,0"
style="fill:none;stroke:#729fcf;stroke-width:1.99999988000000010;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-9"
d="M 17,26.999999 17,31"
style="fill:none;stroke:#204a87;stroke-width:5.99999952000000030;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-1-4"
d="M 17,26.999999 17,31"
style="fill:none;stroke:#729fcf;stroke-width:1.99999988000000010;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-5-1"
d="M 17,43.000001 17,47"
style="fill:none;stroke:#204a87;stroke-width:5.99999952000000030;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-1-7-2"
d="M 17,43.000001 17,47"
style="fill:none;stroke:#729fcf;stroke-width:1.99999988000000010;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-9-3"
d="M 57,28.999999 57,33"
style="fill:none;stroke:#204a87;stroke-width:5.99999952000000030;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-1-4-3"
d="M 57,28.999999 57,33"
style="fill:none;stroke:#729fcf;stroke-width:1.99999988000000010;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-5-1-4"
d="M 57,45.000001 57,49"
style="fill:none;stroke:#204a87;stroke-width:5.99999952000000030;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
id="path3953-1-1-7-2-1"
d="M 57,45.000001 57,49"
style="fill:none;stroke:#729fcf;stroke-width:1.99999988000000010;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<metadata
id="metadata5469">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="" />
<dc:date>Mon Oct 10 13:44:52 2011 +0000</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>[wmayer]</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/Draft/Resources/icons/Draft_SelectGroup.svg</dc:identifier>
<dc:relation>https://www.freecad.org/wiki/index.php?title=Artwork</dc:relation>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
<dc:subject>
<rdf:Bag>
<rdf:li>hierarchy</rdf:li>
<rdf:li>group</rdf:li>
<rdf:li>selection</rdf:li>
<rdf:li>tree</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:description>A hierarchical tree structure with two blue child elements of a white parent element, both of which are surrounded by the same dotted box</dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -199,6 +199,7 @@
<file>Std_DockOverlayToggleTop.svg</file>
<file>Std_DuplicateSelection.svg</file>
<file>Std_Export.svg</file>
<file>Std_SelectGroupContents.svg</file>
<file>Std_HideObjects.svg</file>
<file>Std_HideSelection.svg</file>
<file>Std_Import.svg</file>

View File

@@ -23,6 +23,12 @@
#include "PreCompiled.h"
#include <App/DocumentObjectGroup.h>
#include <App/Document.h>
#include <Gui/Selection/Selection.h>
#include <Gui/BitmapFactory.h>
#include <QMenu>
#include <QAction>
#include <QObject>
#include "ViewProviderDocumentObjectGroup.h"
#include "Application.h"
@@ -82,6 +88,51 @@ void ViewProviderDocumentObjectGroup::getViewProviders(std::vector<ViewProviderD
}
}
void ViewProviderDocumentObjectGroup::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
{
// First, call the base class implementation to get all the standard menu items.
ViewProviderDocumentObject::setupContextMenu(menu, receiver, member);
App::DocumentObject* obj = this->getObject();
// This action is only for plain "Std::Group" objects, not for derived types like "Draft::Layer".
// We check the TypeId to ensure we don't add this menu to other group-like objects.
if (obj->getTypeId() == App::DocumentObjectGroup::getClassTypeId()) {
auto* group = static_cast<App::DocumentObjectGroup*>(obj);
// Only add the action if the group actually contains objects.
if (group && !group->getObjects().empty()) {
// Add the custom action.
QIcon icon = BitmapFactory().iconFromTheme("Std_SelectGroupContents");
QAction* selectAction = new QAction(icon, QObject::tr("Select group contents"), menu);
selectAction->setToolTip(QObject::tr("Selects all objects that are children of this group."));
// Connect the action's triggered signal to a lambda function that performs the selection.
QObject::connect(selectAction, &QAction::triggered, [group]() {
if (!group) return;
// Use getAllChildren() to recursively select contents of subgroups.
const auto& children = group->getAllChildren();
if (!children.empty()) {
const char* docName = group->getDocument()->getName();
Gui::Selection().clearSelection(docName);
// Add each child object to the selection individually.
for (App::DocumentObject* child : children) {
if (child && child->isAttachedToDocument()) {
Gui::Selection().addSelection(docName, child->getNameInDocument());
}
}
}
});
// Insert the action at the top of the menu for better visibility.
menu->insertAction(menu->actions().isEmpty() ? nullptr : menu->actions().first(), selectAction);
}
}
}
// Python feature -----------------------------------------------------------------------

View File

@@ -48,6 +48,9 @@ public:
/// deliver the icon shown in the tree view
QIcon getIcon() const override;
// Set up the context menu with the supported edit modes
void setupContextMenu(QMenu* menu, QObject* receiver, const char* member) override;
/* Check whether the object accept reordering of its children during drop.*/
bool acceptReorderingObjects() const override { return true; };