Draft: implement Draft_AddToLayer command

Fixes #17323.

* Instead of extending Draft_AddToGroup a separate, but similar, command has been created.
* The three "Add to" tools have been grouped in the menu and the toolbar.
* The Draft_AddToGroup icon is provisional. Ideally the "Add to" tools should have related icons (it would then be nice to keep the trowel image in some way for the construction group). Draft_AddNamedGroup.svg and Draft_SelectGroup.svg probably also need to be updated in that context.
This commit is contained in:
Roy-043
2025-02-05 16:21:58 +01:00
parent aef46ad56d
commit be0f3f9c4a
4 changed files with 337 additions and 21 deletions

View File

@@ -4,6 +4,7 @@
<file>icons/Draft_AddConstruction.svg</file>
<file>icons/Draft_AddPoint.svg</file>
<file>icons/Draft_AddToGroup.svg</file>
<file>icons/Draft_AddToLayer.svg</file>
<file>icons/Draft_AddNamedGroup.svg</file>
<file>icons/Draft_Annotation_Style.svg</file>
<file>icons/Draft_Apply.svg</file>

View File

@@ -0,0 +1,217 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
id="svg2985"
height="64px"
width="64px"
sodipodi:docname="Draft_AddToLayer.svg"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<sodipodi:namedview
id="namedview11517"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="10.429825"
inkscape:cx="23.442388"
inkscape:cy="37.632463"
inkscape:window-width="1280"
inkscape:window-height="971"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2985" />
<title
id="title853">Draft_Layer</title>
<defs
id="defs2987">
<linearGradient
id="linearGradient1852">
<stop
id="stop1848"
offset="0"
style="stop-color:#06989a;stop-opacity:1;" />
<stop
id="stop1850"
offset="1"
style="stop-color:#34e0e2;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3815">
<stop
id="stop3817"
offset="0"
style="stop-color:#d3d7cf;stop-opacity:1;" />
<stop
id="stop3819"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3815"
id="linearGradient2"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.64426076,0,0,0.63928583,17.931015,13.729721)"
x1="53.257175"
y1="19.086002"
x2="25.928942"
y2="-1.3815211" />
<linearGradient
xlink:href="#linearGradient1852"
id="linearGradient1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.66067504,0,0,0.63929414,18.06576,5.8678762)"
x1="53.257175"
y1="19.086002"
x2="25.928942"
y2="-1.3815211" />
<linearGradient
xlink:href="#linearGradient3815"
id="linearGradient3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.66067504,0,0,0.63929414,18.06576,-1.9839915)"
x1="53.257175"
y1="19.086002"
x2="25.928942"
y2="-1.3815211" />
<linearGradient
xlink:href="#linearGradient3057"
id="linearGradient3053"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.9455392,0,0,1.9455392,-47.998185,-58.673094)"
x1="41.511921"
y1="26.271811"
x2="42.984806"
y2="49.460072" />
<linearGradient
id="linearGradient3057">
<stop
style="stop-color:#8ae234;stop-opacity:1"
offset="0.0000000"
id="stop3059" />
<stop
style="stop-color:#4e9a06;stop-opacity:1"
offset="1.0000000"
id="stop3061" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3057"
id="linearGradient3053-3"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.9455392,0,0,1.9455392,-47.998185,-58.673094)"
x1="41.511921"
y1="26.271811"
x2="42.984806"
y2="49.460072" />
</defs>
<metadata
id="metadata5826">
<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>Draft_Layer</dc:title>
<dc:date>Tue Jun 10 10:21:01 2014 -0300</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>[Yorik van Havre]</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_Layer.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>page</rdf:li>
<rdf:li>pages</rdf:li>
<rdf:li>rectangles</rdf:li>
<rdf:li>stack</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:description>Three pages or rectangles stacked on top of each other. Previously VisGroup.</dc:description>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer2"
style="display:inline;stroke-width:0.653981"
transform="matrix(1.5298962,0,0,1.5282988,-17.190014,-6.6523599)">
<path
d="M 27.250224,20.840975 50.127593,30.001487 37.05481,40.470644 14.177442,31.310132 Z"
style="display:inline;overflow:visible;fill:url(#linearGradient1);fill-rule:evenodd;stroke:#2e3436;stroke-width:1.30796;stroke-linejoin:round;stroke-dasharray:none;marker:none;enable-background:accumulate"
id="path1-2-9" />
<path
id="path3-5"
style="display:inline;fill:none;stroke:#34e0e2;stroke-width:1.30796;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="m 16.744141,30.928014 c 6.697265,2.682292 13.394531,5.364583 20.091797,8.046875 3.574869,-2.863281 7.149739,-5.726563 10.724609,-8.589844 -6.697266,-2.682292 -13.394531,-5.364583 -20.091797,-8.046875 -3.57487,2.863281 -7.14974,5.726563 -10.724609,8.589844 z" />
</g>
<path
style="fill:none;stroke:#042a2a;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 6.05697,18.049229 H 29.844572"
id="path853" />
<path
id="path851"
d="M 17.950771,6.1554283 V 29.94303"
style="fill:none;stroke:#042a2a;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path847"
d="M 6.05697,18.049229 H 29.844572"
style="fill:none;stroke:#34e0e2;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;stroke:#34e0e2;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 17.950771,6.1554283 V 29.94303"
id="path849" />
<path
id="path855"
d="M 17.950771,6.1554283 V 29.94303"
style="fill:none;stroke:#179a9b;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;stroke:#0aa0a2;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 6.05697,18.049229 H 29.844572"
id="path857" />
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@@ -1,6 +1,7 @@
# ***************************************************************************
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
# * Copyright (c) 2020 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
# * Copyright (c) 2025 FreeCAD Project Association *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
@@ -33,9 +34,10 @@ from PySide.QtCore import QT_TRANSLATE_NOOP
import os
import FreeCAD as App
import FreeCADGui as Gui
import Draft
import Draft_rc
from draftguitools import gui_base
from draftmake import make_layer
from draftobjects import layer
from draftutils import params
from draftutils import utils
from draftutils.translate import translate
@@ -60,12 +62,12 @@ class Layer(gui_base.GuiCommandSimplest):
"""GuiCommand to create a Layer object in the document."""
def __init__(self):
super().__init__(name=translate("draft", "Layer"))
super().__init__(name="Draft_Layer")
def GetResources(self):
"""Set icon, menu and tooltip."""
return {"Pixmap": "Draft_Layer",
"MenuText": QT_TRANSLATE_NOOP("Draft_Layer", "Layer"),
"MenuText": QT_TRANSLATE_NOOP("Draft_Layer", "New layer"),
"ToolTip": QT_TRANSLATE_NOOP("Draft_Layer", "Adds a layer to the document.\nObjects added to this layer can share the same visual properties.")}
def Activated(self):
@@ -75,13 +77,101 @@ class Layer(gui_base.GuiCommandSimplest):
"""
super().Activated()
self.doc.openTransaction("Create Layer")
self.doc.openTransaction(translate("draft", "Create layer"))
Gui.addModule("Draft")
Gui.doCommand("_layer_ = Draft.make_layer(name=None, line_color=None, shape_color=None, line_width=None, draw_style=None, transparency=None)")
Gui.doCommand("layer = Draft.make_layer(name=None, line_color=None, shape_color=None, line_width=None, draw_style=None, transparency=None)")
Gui.doCommand("FreeCAD.ActiveDocument.recompute()")
self.doc.commitTransaction()
class AddToLayer(gui_base.GuiCommandNeedsSelection):
"""GuiCommand for the Draft_AddToLayer tool."""
def __init__(self):
super().__init__(name="Draft_AddToLayer")
def GetResources(self):
"""Set icon, menu and tooltip."""
return {"Pixmap": "Draft_AddToLayer",
"MenuText": QT_TRANSLATE_NOOP("Draft_AddToLayer", "Add to layer..."),
"ToolTip": QT_TRANSLATE_NOOP("Draft_AddToLayer", "Adds the selected objects to a layer, or removes them from any layer.")}
def Activated(self):
"""Execute when the command is called."""
super().Activated()
if not hasattr(Gui, "draftToolBar"):
return
self.ui = Gui.draftToolBar
objs = [obj for obj in App.ActiveDocument.Objects if utils.get_type(obj) == "Layer"]
objs.sort(key=lambda obj: obj.Label)
self.objects = [None] \
+ [None] \
+ objs
self.labels = [translate("draft", "Remove from layer")] \
+ ["---"] \
+ [obj.Label for obj in objs] \
+ ["---"] \
+ [translate("draft", "Add to new layer...")]
self.icons = [self.ui.getIcon(":/icons/list-remove.svg")] \
+ [None] \
+ [obj.ViewObject.Icon for obj in objs] \
+ [None] \
+ [self.ui.getIcon(":/icons/list-add.svg")]
self.ui.sourceCmd = self
self.ui.popupMenu(self.labels, self.icons)
def proceed(self, option):
self.ui.sourceCmd = None
if option == self.labels[0]:
# "Remove from layer"
changed = False
for obj in Gui.Selection.getSelection():
lyr = layer.get_layer(obj)
if lyr is not None:
if not changed:
self.doc.openTransaction(translate("draft", "Remove from layer"))
changed = True
lyr.Proxy.removeObject(lyr, obj)
if changed:
self.doc.commitTransaction()
self.doc.recompute()
return
if option == self.labels[-1]:
# "Add to new layer..."
from PySide import QtWidgets
txt, ok = QtWidgets.QInputDialog.getText(
None,
translate("draft", "Create new layer"),
translate("draft", "Layer name:"),
text=translate("draft", "Layer", "Object label")
)
if not ok:
return
if not txt:
return
self.doc.openTransaction(translate("draft", "Add to new layer"))
lyr = make_layer.make_layer(name=txt, line_color=None, shape_color=None,
line_width=None, draw_style=None, transparency=None)
for obj in Gui.Selection.getSelection():
lyr.Proxy.addObject(lyr, obj)
self.doc.commitTransaction()
self.doc.recompute()
return
# Layer has been selected
i = self.labels.index(option)
lyr = self.objects[i]
self.doc.openTransaction(translate("draft", "Add to layer"))
for obj in Gui.Selection.getSelection():
lyr.Proxy.addObject(lyr, obj)
self.doc.commitTransaction()
self.doc.recompute()
class LayerManager:
"""GuiCommand that displays a Layers manager dialog"""
@@ -156,11 +246,12 @@ class LayerManager:
doc = App.ActiveDocument
changed = False
trans_name = translate("draft", "Layers change")
# delete layers
for name in self.deleteList:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
doc.removeObject(name)
@@ -174,17 +265,17 @@ class LayerManager:
obj = doc.getObject(name)
if not obj:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
obj = Draft.make_layer(name=None, line_color=None, shape_color=None,
line_width=None, draw_style=None, transparency=None)
obj = make_layer.make_layer(name=None, line_color=None, shape_color=None,
line_width=None, draw_style=None, transparency=None)
vobj = obj.ViewObject
# visibility
checked = self.model.item(row, 0).checkState() == QtCore.Qt.Checked
if checked != vobj.Visibility:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
vobj.Visibility = checked
@@ -193,7 +284,7 @@ class LayerManager:
# Setting Label="" is possible in the Property editor but we avoid it here:
if label and obj.Label != label:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
obj.Label = label
@@ -202,7 +293,7 @@ class LayerManager:
# Setting LineWidth=0 is possible in the Property editor but we avoid it here:
if width and vobj.LineWidth != width:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
vobj.LineWidth = width
@@ -210,7 +301,7 @@ class LayerManager:
style = self.model.item(row, 3).text()
if style is not None and vobj.DrawStyle != style:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
vobj.DrawStyle = style
@@ -218,7 +309,7 @@ class LayerManager:
color = self.model.item(row, 4).data(QtCore.Qt.UserRole)
if color is not None and vobj.LineColor[:3] != color:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
vobj.LineColor = color
@@ -226,7 +317,7 @@ class LayerManager:
color = self.model.item(row, 5).data(QtCore.Qt.UserRole)
if color is not None and vobj.ShapeColor[:3] != color:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
vobj.ShapeColor = color
@@ -234,7 +325,7 @@ class LayerManager:
transparency = self.model.item(row, 6).data(QtCore.Qt.DisplayRole)
if transparency is not None and vobj.Transparency != transparency:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
vobj.Transparency = transparency
@@ -242,7 +333,7 @@ class LayerManager:
color = self.model.item(row, 7).data(QtCore.Qt.UserRole)
if color is not None and vobj.LinePrintColor[:3] != color:
if not changed:
doc.openTransaction("Layers change")
doc.openTransaction(trans_name)
changed = True
vobj.LinePrintColor = color
@@ -284,7 +375,7 @@ class LayerManager:
self.dialog.tree.setColumnWidth(1,128) # name column
# populate
objs = [obj for obj in App.ActiveDocument.Objects if Draft.getType(obj) == "Layer"]
objs = [obj for obj in App.ActiveDocument.Objects if utils.get_type(obj) == "Layer"]
objs.sort(key=lambda o:o.Label)
for obj in objs:
self.addItem(obj)
@@ -504,6 +595,7 @@ if App.GuiUp:
Gui.addCommand('Draft_Layer', Layer())
Gui.addCommand('Draft_AddToLayer', AddToLayer())
Gui.addCommand('Draft_LayerManager', LayerManager())
## @}

View File

@@ -114,9 +114,11 @@ def get_draft_utility_commands_menu():
"Draft_Layer",
"Draft_LayerManager",
"Draft_AddNamedGroup",
"Draft_AddToGroup",
"Draft_SelectGroup",
"Draft_ToggleConstructionMode",
"Separator",
"Draft_AddToLayer",
"Draft_AddToGroup",
"Draft_AddConstruction",
"Separator",
"Draft_ToggleDisplayMode",
@@ -132,8 +134,9 @@ def get_draft_utility_commands_toolbar():
"""Return the utility commands list for the toolbar."""
return ["Draft_LayerManager",
"Draft_AddNamedGroup",
"Draft_AddToGroup",
"Draft_SelectGroup",
"Draft_AddToLayer",
"Draft_AddToGroup",
"Draft_AddConstruction",
"Draft_ToggleDisplayMode",
"Draft_WorkingPlaneProxy"]
@@ -169,10 +172,13 @@ def get_draft_context_commands():
"Draft_ApplyStyle",
"Separator",
"Draft_Layer",
"Draft_LayerManager",
"Draft_AddNamedGroup",
"Draft_AddToGroup",
"Draft_SelectGroup",
"Draft_ToggleConstructionMode",
"Separator",
"Draft_AddToLayer",
"Draft_AddToGroup",
"Draft_AddConstruction",
"Separator",
"Draft_ToggleDisplayMode",