diff --git a/src/Mod/Draft/draftviewproviders/view_layer.py b/src/Mod/Draft/draftviewproviders/view_layer.py index b7231ae1f1..1f88700105 100644 --- a/src/Mod/Draft/draftviewproviders/view_layer.py +++ b/src/Mod/Draft/draftviewproviders/view_layer.py @@ -1,6 +1,7 @@ # *************************************************************************** # * Copyright (c) 2014 Yorik van Havre * # * Copyright (c) 2020 Eliud Cabrera Castillo * +# * Copyright (c) 2021 FreeCAD Developers * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -37,7 +38,7 @@ import FreeCAD as App import FreeCADGui as Gui from draftutils.messages import _msg -from draftutils.translate import translate +from draftutils.translate import _tr from draftobjects.layer import Layer @@ -355,13 +356,13 @@ class ViewProviderLayer: def setupContextMenu(self, vobj, menu): """Set up actions to perform in the context menu.""" action1 = QtGui.QAction(QtGui.QIcon(":/icons/button_right.svg"), - translate("draft", "Activate this layer"), + _tr("Activate this layer"), menu) action1.triggered.connect(self.activate) menu.addAction(action1) action2 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectGroup.svg"), - translate("draft", "Select layer contents"), + _tr("Select layer contents"), menu) action2.triggered.connect(self.select_contents) menu.addAction(action2) @@ -399,80 +400,76 @@ class ViewProviderLayerContainer: def setupContextMenu(self, vobj, menu): """Set up actions to perform in the context menu.""" action1 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_Layer.svg"), - translate("Draft", "Merge layer duplicates"), + _tr("Merge layer duplicates"), menu) action1.triggered.connect(self.merge_by_name) menu.addAction(action1) action2 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_NewLayer.svg"), - translate("Draft", "Add new layer"), + _tr("Add new layer"), menu) action2.triggered.connect(self.add_layer) menu.addAction(action2) def merge_by_name(self): - """Merge the layers that have the same name.""" + """Merge the layers that have the same base label.""" if not hasattr(self, "Object") or not hasattr(self.Object, "Group"): return - obj = self.Object + doc = App.ActiveDocument + doc.openTransaction(_tr("Merge layer duplicates")) - layers = list() - for iobj in obj.Group: - if hasattr(iobj, "Proxy") and isinstance(iobj.Proxy, Layer): - layers.append(iobj) + layer_container = self.Object + layers = [] + for obj in layer_container.Group: + if hasattr(obj, "Proxy") and isinstance(obj.Proxy, Layer): + layers.append(obj) - to_delete = list() + to_delete = [] for layer in layers: - # Test the last three characters of the layer's Label to see - # if it's a number, like `'Layer017'` - if (layer.Label[-1].isdigit() - and layer.Label[-2].isdigit() - and layer.Label[-3].isdigit()): - # If the object inside the layer has the same Label - # as the layer, save this object - orig = None - for ol in layer.OutList: - if ol.Label == layer.Label[:-3].strip(): - orig = ol - break + # Remove trailing digits (usually 3 but there might be more) and + # trailing spaces from Label before comparing: + base_label = layer.Label.rstrip("0123456789 ") - # Go into the objects that reference this layer object - # and set the layer property with the previous `orig` - # object found - # Editor: when is this possible? Maybe if a layer is inside - # another layer? Currently the code doesn't allow this - # so maybe this was a previous behavior that was disabled - # in `ViewProviderLayer`. - if orig: - for par in layer.InList: - for prop in par.PropertiesList: - if getattr(par, prop) == layer: - _msg("Changed property '" + prop - + "' of object " + par.Label - + " from " + layer.Label - + " to " + orig.Label) - setattr(par, prop, orig) - to_delete.append(layer) + # Try to find the `'base'` layer: + base = None + for other_layer in layers: + if ((not other_layer in to_delete) # Required if there are duplicate labels. + and other_layer != layer + and other_layer.Label.upper() == base_label.upper()): + base = other_layer + break + + if base: + if layer.Group: + base_group = base.Group + for obj in layer.Group: + if not obj in base_group: + base_group.append(obj) + base.Group = base_group + to_delete.append(layer) + elif layer.Label != base_label: + _msg(_tr("Relabeling layer:") + + " '{}' -> '{}'".format(layer.Label, base_label)) + layer.Label = base_label for layer in to_delete: - if not layer.InList: - _msg("Merging duplicate layer: " + layer.Label) - App.ActiveDocument.removeObject(layer.Name) - elif len(layer.InList) == 1: - first = layer.InList[0] + _msg(_tr("Merging layer:") + " '{}'".format(layer.Label)) + doc.removeObject(layer.Name) - if first.isDerivedFrom("App::DocumentObjectGroup"): - _msg("Merging duplicate layer: " + layer.Label) - App.ActiveDocument.removeObject(layer.Name) - else: - _msg("InList not empty. " - "Unable to delete layer: " + layer.Label) + doc.recompute() + doc.commitTransaction() def add_layer(self): """Creates a new layer""" import Draft + + doc = App.ActiveDocument + doc.openTransaction(_tr("Add new layer")) + Draft.make_layer() - App.ActiveDocument.recompute() + + doc.recompute() + doc.commitTransaction() def __getstate__(self): """Return a tuple of objects to save or None."""