From be0f3f9c4aa62d8937c4e54c523625ea1b9d7874 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Wed, 5 Feb 2025 16:21:58 +0100 Subject: [PATCH] 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. --- src/Mod/Draft/Resources/Draft.qrc | 1 + .../Resources/icons/Draft_AddToLayer.svg | 217 ++++++++++++++++++ src/Mod/Draft/draftguitools/gui_layers.py | 128 +++++++++-- src/Mod/Draft/draftutils/init_tools.py | 12 +- 4 files changed, 337 insertions(+), 21 deletions(-) create mode 100644 src/Mod/Draft/Resources/icons/Draft_AddToLayer.svg diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc index 378d61a96b..089dac09c9 100644 --- a/src/Mod/Draft/Resources/Draft.qrc +++ b/src/Mod/Draft/Resources/Draft.qrc @@ -4,6 +4,7 @@ icons/Draft_AddConstruction.svg icons/Draft_AddPoint.svg icons/Draft_AddToGroup.svg + icons/Draft_AddToLayer.svg icons/Draft_AddNamedGroup.svg icons/Draft_Annotation_Style.svg icons/Draft_Apply.svg diff --git a/src/Mod/Draft/Resources/icons/Draft_AddToLayer.svg b/src/Mod/Draft/Resources/icons/Draft_AddToLayer.svg new file mode 100644 index 0000000000..fa7befea4d --- /dev/null +++ b/src/Mod/Draft/Resources/icons/Draft_AddToLayer.svg @@ -0,0 +1,217 @@ + + + + Draft_Layer + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Draft_Layer + Tue Jun 10 10:21:01 2014 -0300 + + + [Yorik van Havre] + + + + + FreeCAD LGPL2+ + + + + + FreeCAD + + + FreeCAD/src/Mod/Draft/Resources/icons/Draft_Layer.svg + https://www.freecad.org/wiki/index.php?title=Artwork + + + [agryson] Alexander Gryson + + + + + page + pages + rectangles + stack + + + Three pages or rectangles stacked on top of each other. Previously VisGroup. + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/draftguitools/gui_layers.py b/src/Mod/Draft/draftguitools/gui_layers.py index 1b8c4bc85c..29fc3fa947 100644 --- a/src/Mod/Draft/draftguitools/gui_layers.py +++ b/src/Mod/Draft/draftguitools/gui_layers.py @@ -1,6 +1,7 @@ # *************************************************************************** # * Copyright (c) 2014 Yorik van Havre * # * Copyright (c) 2020 Eliud Cabrera Castillo * +# * 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()) ## @} diff --git a/src/Mod/Draft/draftutils/init_tools.py b/src/Mod/Draft/draftutils/init_tools.py index 3d849c2108..62f3822655 100644 --- a/src/Mod/Draft/draftutils/init_tools.py +++ b/src/Mod/Draft/draftutils/init_tools.py @@ -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",