From 6503d9351d63d330330c43fbc465f00adcde7ef5 Mon Sep 17 00:00:00 2001 From: vocx-fc Date: Thu, 25 Jun 2020 21:34:09 -0500 Subject: [PATCH] Draft: move grouping functions to draftutils.groups module These functions were previously in `draftutils.utils`, and are related to grouping objects and finding objects inside groups. These include `get_group_names`, `ungroup`, `get_windows`, `get_group_contents`, `get_movable_children`. These are imported in the main `Draft.py` module, so compatibility is retained. Modules which use these functions are updated; these include Gui Commands like `Move`, `Rotate`, `Scale`, `AddToGroup`, as well as objects like `DrawingView` and `Shape2DView`, and `ViewProviderClone`. The code inside the `importDXF` module is also updated. The Arch Workbench uses many of these functions but it does so from the `Draft` namespace, so these edits don't change the situation for these commands. --- src/Mod/Draft/CMakeLists.txt | 1 + src/Mod/Draft/Draft.py | 18 +- src/Mod/Draft/draftfunctions/move.py | 16 +- src/Mod/Draft/draftfunctions/rotate.py | 17 +- src/Mod/Draft/draftguitools/gui_groups.py | 9 +- src/Mod/Draft/draftguitools/gui_move.py | 16 +- src/Mod/Draft/draftguitools/gui_rotate.py | 15 +- src/Mod/Draft/draftguitools/gui_scale.py | 6 +- src/Mod/Draft/draftobjects/drawingview.py | 16 +- src/Mod/Draft/draftobjects/shape2dview.py | 5 +- src/Mod/Draft/draftutils/groups.py | 328 ++++++++++++++++++ src/Mod/Draft/draftutils/utils.py | 237 ------------- .../Draft/draftviewproviders/view_clone.py | 4 +- src/Mod/Draft/importDXF.py | 2 +- 14 files changed, 396 insertions(+), 294 deletions(-) create mode 100644 src/Mod/Draft/draftutils/groups.py diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index abb7db357f..52fb8e880a 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -68,6 +68,7 @@ SET(Draft_tests SET(Draft_utilities draftutils/__init__.py + draftutils/groups.py draftutils/init_tools.py draftutils/init_draft_statusbar.py draftutils/units.py diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index d058ad85ce..93083f0932 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -117,14 +117,6 @@ from draftutils.utils import is_clone from draftutils.utils import getCloneBase from draftutils.utils import get_clone_base -from draftutils.utils import getGroupNames -from draftutils.utils import get_group_names - -from draftutils.utils import ungroup - -from draftutils.utils import getGroupContents -from draftutils.utils import get_group_contents - from draftutils.utils import printShape from draftutils.utils import print_shape @@ -139,9 +131,6 @@ from draftutils.utils import load_svg_patterns from draftutils.utils import svgpatterns from draftutils.utils import svg_patterns -from draftutils.utils import getMovableChildren -from draftutils.utils import get_movable_children - from draftutils.utils import filter_objects_for_modifiers from draftutils.utils import filterObjectsForModifiers @@ -185,6 +174,13 @@ from draftutils.gui_utils import select from draftutils.gui_utils import loadTexture from draftutils.gui_utils import load_texture +from draftutils.groups import (get_group_names, + getGroupNames, + ungroup, + get_group_contents, + getGroupContents, + get_movable_children, + getMovableChildren) #--------------------------------------------------------------------------- # Draft functions diff --git a/src/Mod/Draft/draftfunctions/move.py b/src/Mod/Draft/draftfunctions/move.py index b64dbbe5a5..a01601e658 100644 --- a/src/Mod/Draft/draftfunctions/move.py +++ b/src/Mod/Draft/draftfunctions/move.py @@ -28,8 +28,9 @@ import FreeCAD as App -import draftutils.gui_utils as gui_utils import draftutils.utils as utils +import draftutils.groups as groups +import draftutils.gui_utils as gui_utils from draftmake.make_copy import make_copy from draftmake.make_line import make_line @@ -59,8 +60,10 @@ def move(objectslist, vector, copy=False): The objects (or their copies) are returned. """ utils.type_check([(vector, App.Vector), (copy,bool)], "move") - if not isinstance(objectslist, list): objectslist = [objectslist] - objectslist.extend(utils.get_movable_children(objectslist)) + if not isinstance(objectslist, list): + objectslist = [objectslist] + + objectslist.extend(groups.get_movable_children(objectslist)) newobjlist = [] newgroups = {} objectslist = utils.filter_objects_for_modifiers(objectslist, copy) @@ -103,7 +106,7 @@ def move(objectslist, vector, copy=False): newobj = obj newobj.Position = obj.Position.add(real_vector) - elif utils.get_type(obj) == "Text": + elif utils.get_type(obj) in ("Text", "DraftText"): if copy: newobj = make_copy(obj) else: @@ -136,7 +139,7 @@ def move(objectslist, vector, copy=False): if newobj is not None: newobjlist.append(newobj) - + if copy: for p in obj.InList: if p.isDerivedFrom("App::DocumentObjectGroup") and (p in objectslist): @@ -150,7 +153,8 @@ def move(objectslist, vector, copy=False): gui_utils.select(objectslist) else: gui_utils.select(newobjlist) - if len(newobjlist) == 1: return newobjlist[0] + if len(newobjlist) == 1: + return newobjlist[0] return newobjlist diff --git a/src/Mod/Draft/draftfunctions/rotate.py b/src/Mod/Draft/draftfunctions/rotate.py index 64c8e9e9d7..411eaebc1f 100644 --- a/src/Mod/Draft/draftfunctions/rotate.py +++ b/src/Mod/Draft/draftfunctions/rotate.py @@ -29,15 +29,14 @@ import math import FreeCAD as App - import DraftVecUtils -import draftutils.gui_utils as gui_utils import draftutils.utils as utils +import draftutils.groups as groups +import draftutils.gui_utils as gui_utils -from draftmake.make_line import make_line from draftfunctions.join import join_wires - +from draftmake.make_line import make_line from draftmake.make_copy import make_copy @@ -70,11 +69,14 @@ def rotate(objectslist, angle, center=App.Vector(0,0,0), """ import Part utils.type_check([(copy,bool)], "rotate") - if not isinstance(objectslist,list): objectslist = [objectslist] - objectslist.extend(utils.get_movable_children(objectslist)) + if not isinstance(objectslist,list): + objectslist = [objectslist] + + objectslist.extend(groups.get_movable_children(objectslist)) newobjlist = [] newgroups = {} objectslist = utils.filter_objects_for_modifiers(objectslist, copy) + for obj in objectslist: newobj = None # real_center and real_axis are introduced to take into account @@ -143,7 +145,8 @@ def rotate(objectslist, angle, center=App.Vector(0,0,0), break gui_utils.select(newobjlist) - if len(newobjlist) == 1: return newobjlist[0] + if len(newobjlist) == 1: + return newobjlist[0] return newobjlist diff --git a/src/Mod/Draft/draftguitools/gui_groups.py b/src/Mod/Draft/draftguitools/gui_groups.py index 531a4321ae..43a020142b 100644 --- a/src/Mod/Draft/draftguitools/gui_groups.py +++ b/src/Mod/Draft/draftguitools/gui_groups.py @@ -39,6 +39,7 @@ import FreeCAD as App import FreeCADGui as Gui import Draft_rc import draftutils.utils as utils +import draftutils.groups as groups import draftguitools.gui_base as gui_base from draftutils.translate import _tr, translate @@ -79,7 +80,7 @@ class AddToGroup(gui_base.GuiCommandNeedsSelection): super(AddToGroup, self).Activated() self.groups = [self.ungroup] - self.groups.extend(utils.get_group_names()) + self.groups.extend(groups.get_group_names()) self.labels = [self.ungroup] for group in self.groups: @@ -115,7 +116,7 @@ class AddToGroup(gui_base.GuiCommandNeedsSelection): if labelname == self.ungroup: for obj in Gui.Selection.getSelection(): try: - utils.ungroup(obj) + groups.ungroup(obj) except Exception: pass else: @@ -193,7 +194,7 @@ class SelectGroup(gui_base.GuiCommandNeedsSelection): sel = Gui.Selection.getSelection() if len(sel) == 1: if sel[0].isDerivedFrom("App::DocumentObjectGroup"): - cts = utils.get_group_contents(Gui.Selection.getSelection()) + cts = groups.get_group_contents(Gui.Selection.getSelection()) for o in cts: Gui.Selection.addSelection(o) return @@ -281,7 +282,7 @@ class SetAutoGroup(gui_base.GuiCommandSimplest): self.groups = ["None"] gn = [o.Name for o in self.doc.Objects if utils.get_type(o) == "Layer"] if App.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM").GetBool("AutogroupAddGroups", False): - gn.extend(utils.get_group_names()) + gn.extend(groups.get_group_names()) if gn: self.groups.extend(gn) self.labels = [translate("draft", "None")] diff --git a/src/Mod/Draft/draftguitools/gui_move.py b/src/Mod/Draft/draftguitools/gui_move.py index 39103ed6d5..a90cdcd5da 100644 --- a/src/Mod/Draft/draftguitools/gui_move.py +++ b/src/Mod/Draft/draftguitools/gui_move.py @@ -33,12 +33,15 @@ import FreeCAD as App import FreeCADGui as Gui import Draft_rc import DraftVecUtils -import draftutils.utils as utils + +import draftutils.groups as groups import draftutils.todo as todo + import draftguitools.gui_base_original as gui_base_original -from draftguitools.gui_subelements import SubelementHighlight import draftguitools.gui_tool_utils as gui_tool_utils import draftguitools.gui_trackers as trackers + +from draftguitools.gui_subelements import SubelementHighlight from draftutils.messages import _msg, _err from draftutils.translate import translate @@ -90,10 +93,11 @@ class Move(gui_base_original.Modifier): if self.call: self.view.removeEventCallback("SoEvent", self.call) self.selected_objects = Gui.Selection.getSelection() - self.selected_objects = utils.getGroupContents(self.selected_objects, - addgroups=True, - spaces=True, - noarchchild=True) + self.selected_objects = \ + groups.get_group_contents(self.selected_objects, + addgroups=True, + spaces=True, + noarchchild=True) self.selected_subelements = Gui.Selection.getSelectionEx() self.ui.lineUi(self.name) self.ui.modUi() diff --git a/src/Mod/Draft/draftguitools/gui_rotate.py b/src/Mod/Draft/draftguitools/gui_rotate.py index d1424f935b..52c19f8725 100644 --- a/src/Mod/Draft/draftguitools/gui_rotate.py +++ b/src/Mod/Draft/draftguitools/gui_rotate.py @@ -33,13 +33,15 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD as App import FreeCADGui as Gui import Draft_rc -from FreeCAD import Units as U import DraftVecUtils -import draftutils.utils as utils + +import draftutils.groups as groups import draftutils.todo as todo import draftguitools.gui_base_original as gui_base_original import draftguitools.gui_tool_utils as gui_tool_utils import draftguitools.gui_trackers as trackers + +from FreeCAD import Units as U from draftutils.messages import _msg, _err from draftutils.translate import translate, _tr @@ -88,10 +90,11 @@ class Rotate(gui_base_original.Modifier): if self.call: self.view.removeEventCallback("SoEvent", self.call) self.selected_objects = Gui.Selection.getSelection() - self.selected_objects = utils.getGroupContents(self.selected_objects, - addgroups=True, - spaces=True, - noarchchild=True) + self.selected_objects = \ + groups.get_group_contents(self.selected_objects, + addgroups=True, + spaces=True, + noarchchild=True) self.selected_subelements = Gui.Selection.getSelectionEx() self.step = 0 self.center = None diff --git a/src/Mod/Draft/draftguitools/gui_scale.py b/src/Mod/Draft/draftguitools/gui_scale.py index 6e1c8f14c1..d47b4a69fa 100644 --- a/src/Mod/Draft/draftguitools/gui_scale.py +++ b/src/Mod/Draft/draftguitools/gui_scale.py @@ -40,12 +40,15 @@ import FreeCAD as App import FreeCADGui as Gui import Draft_rc import DraftVecUtils + import draftutils.utils as utils +import draftutils.groups as groups import draftutils.todo as todo import draftguitools.gui_base_original as gui_base_original import draftguitools.gui_tool_utils as gui_tool_utils import draftguitools.gui_trackers as trackers import drafttaskpanels.task_scale as task_scale + from draftutils.messages import _msg, _err from draftutils.translate import translate @@ -93,7 +96,8 @@ class Scale(gui_base_original.Modifier): self.view.removeEventCallback("SoEvent", self.call) self.selected_objects = Gui.Selection.getSelection() - self.selected_objects = utils.getGroupContents(self.selected_objects) + self.selected_objects = \ + groups.get_group_contents(self.selected_objects) self.selected_subelements = Gui.Selection.getSelectionEx() self.refs = [] self.ui.pointUi(self.name) diff --git a/src/Mod/Draft/draftobjects/drawingview.py b/src/Mod/Draft/draftobjects/drawingview.py index dc1f3314c0..94b7840eb9 100644 --- a/src/Mod/Draft/draftobjects/drawingview.py +++ b/src/Mod/Draft/draftobjects/drawingview.py @@ -27,18 +27,12 @@ This module is obsolete, since Drawing was substituted by TechDraw. # \ingroup DRAFT # \brief This module provides the object code for the Draft DrawingView object. -import math - from PySide.QtCore import QT_TRANSLATE_NOOP -import FreeCAD as App - -import DraftVecUtils - -from getSVG import getSVG +import getSVG import draftutils.utils as utils - +import draftutils.groups as groups from draftobjects.base import DraftObject @@ -105,16 +99,16 @@ class DrawingView(DraftObject): svg = "" shapes = [] others = [] - objs = utils.getGroupContents([obj.Source]) + objs = groups.get_group_contents([obj.Source]) for o in objs: v = o.ViewObject.isVisible() if hasattr(obj,"AlwaysOn"): if obj.AlwaysOn: v = True if v: - svg += getSVG(o,obj.Scale,obj.LineWidth,obj.FontSize.Value,obj.FillStyle,obj.Direction,ls,lc,lp) + svg += getSVG.getSVG(o,obj.Scale,obj.LineWidth,obj.FontSize.Value,obj.FillStyle,obj.Direction,ls,lc,lp) else: - svg = getSVG(obj.Source,obj.Scale,obj.LineWidth,obj.FontSize.Value,obj.FillStyle,obj.Direction,ls,lc,lp) + svg = getSVG.getSVG(obj.Source,obj.Scale,obj.LineWidth,obj.FontSize.Value,obj.FillStyle,obj.Direction,ls,lc,lp) result += ', Ken Cline * +# * (c) 2020 Eliud Cabrera Castillo * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** +"""Provides utility functions for managing groups in the Draft Workbench. + +The functions here are also used in the Arch Workbench as some of +the objects created with this workbench work like groups. +""" +## @package groups +# \ingroup DRAFT +# \brief Provides utility functions for managing groups in the Draft Workbench. + +import FreeCAD as App + +import draftutils.utils as utils +from draftutils.translate import _tr +from draftutils.messages import _msg, _err + + +def get_group_names(doc=None): + """Return a list of names of existing groups in the document. + + Parameters + ---------- + doc: App::Document, optional + It defaults to `None`. + A document on which to search group names. + It if is `None` it will search the current document. + + Returns + ------- + list of str + A list of names of objects that are "groups". + These are objects derived from `App::DocumentObjectGroup` + or which are of types `'Floor'`, `'Building'`, or `'Site'` + from the Arch Workbench. + + Otherwise, return an empty list. + """ + if not doc: + found, doc = utils.find_doc(App.activeDocument()) + + if not found: + _err(_tr("No active document. Aborting.")) + return [] + + glist = [] + + for obj in doc.Objects: + if (obj.isDerivedFrom("App::DocumentObjectGroup") + or utils.get_type(obj) in ("Floor", "Building", "Site")): + glist.append(obj.Name) + + return glist + + +def getGroupNames(): + """Return a list of group names. DEPRECATED.""" + utils.use_instead("get_group_names") + return get_group_names() + + +def ungroup(obj): + """Remove the object from any group to which it belongs. + + A "group" is any object returned by `get_group_names`. + + Parameters + ---------- + obj: App::DocumentObject or str + Any type of object. + If it is a string, it must be the `Label` of that object. + Since a label is not guaranteed to be unique in a document, + it will use the first object found with this label. + """ + if isinstance(obj, str): + obj_str = obj + + found, obj = utils.find_object(obj, doc=App.activeDocument()) + if not found: + _msg("obj: {}".format(obj_str)) + _err(_tr("Wrong input: object not in document.")) + return None + + doc = obj.Document + + for name in get_group_names(): + group = doc.getObject(name) + if obj in group.Group: + # The list of objects cannot be modified directly, + # so a new list is created, this new list is modified, + # and then it is assigned over the older list. + objects = group.Group + objects.remove(obj) + group.Group = objects + + +def get_windows(obj): + """Return the windows and rebars inside a host. + + Parameters + ---------- + obj: App::DocumentObject + A scripted object of type `'Wall'` or `'Structure'` + (Arch Workbench). + This will be searched for objects of type `'Window'` and `'Rebar'`, + and clones of them, and the found elements will be added + to the output list. + + The function will search recursively all elements under `obj.OutList`, + in case the windows and rebars are nested under other walls + and structures. + + Returns + ------- + list + A list of all found windows and rebars in `obj`. + If `obj` is itself a `'Window'` or a `'Rebar'`, or a clone of them, + it will return the same `obj` element. + """ + out = [] + if utils.get_type(obj) in ("Wall", "Structure"): + for o in obj.OutList: + out.extend(get_windows(o)) + + for i in obj.InList: + if (utils.get_type(i) == "Window" + or utils.is_clone(obj, "Window")): + if hasattr(i, "Hosts"): + if obj in i.Hosts: + out.append(i) + elif (utils.get_type(i) == "Rebar" + or utils.is_clone(obj, "Rebar")): + if hasattr(i, "Host"): + if obj == i.Host: + out.append(i) + + elif (utils.get_type(obj) in ("Window", "Rebar") + or utils.is_clone(obj, ["Window", "Rebar"])): + out.append(obj) + + return out + + +def get_group_contents(objectslist, + walls=False, addgroups=False, + spaces=False, noarchchild=False): + """Return a list of objects from expanding the input groups. + + The function accepts any type of object, although it is most useful + with "groups", as it is meant to unpack the objects inside these groups. + + Parameters + ---------- + objectslist: list + If any object in the list is a group, its contents (`obj.Group`) + are extracted and added to the output list. + + The "groups" are objects derived from `App::DocumentObjectGroup`, + but they can also be `'App::Part'`, or `'Building'`, `'BuildingPart'`, + `'Space'`, and `'Site'` from the Arch Workbench. + + Single items that aren't groups are added to the output list + as is. + + walls: bool, optional + It defaults to `False`. + If it is `True`, Wall and Structure objects (Arch Workbench) + are treated as groups; they are scanned for Window, Door, + and Rebar objects, and these are added to the output list. + + addgroups: bool, optional + It defaults to `False`. + If it is `True`, the group itself is kept as part of the output list. + + spaces: bool, optional + It defaults to `False`. + If it is `True`, Arch Spaces are treated as groups, + and are added to the output list. + + noarchchild: bool, optional + It defaults to `False`. + If it is `True`, the objects inside Building and BuildingParts + (Arch Workbench) aren't added to the output list. + + Returns + ------- + list + The list of objects from each group present in `objectslist`, + plus any other individual object given in `objectslist`. + """ + newlist = [] + if not isinstance(objectslist, list): + objectslist = [objectslist] + + for obj in objectslist: + if obj: + if (obj.isDerivedFrom("App::DocumentObjectGroup") + or (utils.get_type(obj) in ("Building", "BuildingPart", + "Space", "Site") + and hasattr(obj, "Group"))): + if utils.get_type(obj) == "Site": + if obj.Shape: + newlist.append(obj) + if obj.isDerivedFrom("Drawing::FeaturePage"): + # Skip if the group is a Drawing page + # Note: the Drawing workbench is obsolete + newlist.append(obj) + else: + if addgroups or (spaces + and utils.get_type(obj) == "Space"): + newlist.append(obj) + if (noarchchild + and utils.get_type(obj) in ("Building", + "BuildingPart")): + pass + else: + newlist.extend(get_group_contents(obj.Group, + walls, addgroups)) + else: + # print("adding ", obj.Name) + newlist.append(obj) + if walls: + newlist.extend(get_windows(obj)) + + # Clean possible duplicates + cleanlist = [] + for obj in newlist: + if obj not in cleanlist: + cleanlist.append(obj) + + return cleanlist + + +def getGroupContents(objectslist, + walls=False, addgroups=False, + spaces=False, noarchchild=False): + """Return a list of objects from groups. DEPRECATED.""" + utils.use_instead("get_group_contents") + + return get_group_contents(objectslist, + walls, addgroups, + spaces, noarchchild) + + +def get_movable_children(objectslist, recursive=True): + """Return a list of objects with child objects that move with a host. + + Builds a list of objects with all child objects (`obj.OutList`) + that have their `MoveWithHost` attribute set to `True`. + This function is mostly useful for Arch Workbench objects. + + Parameters + ---------- + objectslist: list of App::DocumentObject + A single scripted object or list of objects. + + recursive: bool, optional + It defaults to `True`, in which case the function + is called recursively to also extract the children of children + objects. + Otherwise, only direct children of the input objects + are added to the output list. + + Returns + ------- + list + List of children objects that have their `MoveWithHost` attribute + set to `True`. + """ + added = [] + if not isinstance(objectslist, list): + objectslist = [objectslist] + + for obj in objectslist: + # Skips some objects that should never move their children + if utils.get_type(obj) not in ("Clone", "SectionPlane", + "Facebinder", "BuildingPart"): + children = obj.OutList + if (hasattr(obj, "Proxy") and obj.Proxy + and hasattr(obj.Proxy, "getSiblings") + and utils.get_type(obj) != "Window"): + # children.extend(obj.Proxy.getSiblings(obj)) + pass + + for child in children: + if hasattr(child, "MoveWithHost") and child.MoveWithHost: + if hasattr(obj, "CloneOf"): + if obj.CloneOf: + if obj.CloneOf.Name != child.Name: + added.append(child) + else: + added.append(child) + else: + added.append(child) + + if recursive: + added.extend(get_movable_children(children)) + + return added + + +def getMovableChildren(objectslist, recursive=True): + """Return a list of objects with child objects. DEPRECATED.""" + utils.use_instead("get_movable_children") + return get_movable_children(objectslist, recursive) diff --git a/src/Mod/Draft/draftutils/utils.py b/src/Mod/Draft/draftutils/utils.py index 5c8dccea69..e1932922ef 100644 --- a/src/Mod/Draft/draftutils/utils.py +++ b/src/Mod/Draft/draftutils/utils.py @@ -591,52 +591,6 @@ def get_clone_base(obj, strict=False): getCloneBase = get_clone_base -def get_group_names(): - """Return a list of names of existing groups in the document. - - Returns - ------- - list of str - A list of names of objects that are "groups". - These are objects derived from `'App::DocumentObjectGroup'` - or which are of types `'Floor'`, `'Building'`, or `'Site'` - (from the Arch Workbench). - - Otherwise, return an empty list. - """ - glist = [] - doc = App.ActiveDocument - for obj in doc.Objects: - if (obj.isDerivedFrom("App::DocumentObjectGroup") - or getType(obj) in ("Floor", "Building", "Site")): - glist.append(obj.Name) - return glist - - -getGroupNames = get_group_names - - -def ungroup(obj): - """Remove the object from any group to which it belongs. - - A "group" is any object returned by `get_group_names`. - - Parameters - ---------- - obj : App::DocumentObject - Any type of scripted object. - """ - for name in getGroupNames(): - group = App.ActiveDocument.getObject(name) - if obj in group.Group: - # The list of objects cannot be modified directly, - # so a new list is created, this new list is modified, - # and then it is assigned over the older list. - objects = group.Group - objects.remove(obj) - group.Group = objects - - def shapify(obj): """Transform a parametric object into a static, non-parametric shape. @@ -693,139 +647,6 @@ def shapify(obj): return newobj -def get_windows(obj): - """Return the windows and rebars inside a host. - - Parameters - ---------- - obj : App::DocumentObject - A scripted object of type `'Wall'` or `'Structure'` - (Arch Workbench). - This will be searched for objects of type `'Window'` and `'Rebar'`, - and clones of them, and the found elements will be added - to the output list. - - The function will search recursively all elements under `obj.OutList`, - in case the windows and rebars are nested under other walls - and structures. - - Returns - ------- - list - A list of all found windows and rebars in `obj`. - If `obj` is itself a `'Window'` or a `'Rebar'`, or a clone of them, - it will return the same `obj` element. - """ - out = [] - if getType(obj) in ("Wall", "Structure"): - for o in obj.OutList: - out.extend(get_windows(o)) - for i in obj.InList: - if getType(i) in ("Window") or isClone(obj, "Window"): - if hasattr(i, "Hosts"): - if obj in i.Hosts: - out.append(i) - elif getType(i) in ("Rebar") or isClone(obj, "Rebar"): - if hasattr(i, "Host"): - if obj == i.Host: - out.append(i) - elif (getType(obj) in ("Window", "Rebar") - or isClone(obj, ["Window", "Rebar"])): - out.append(obj) - return out - - -getWindows = get_windows - - -def get_group_contents(objectslist, - walls=False, addgroups=False, - spaces=False, noarchchild=False): - """Return a list of objects from expanding the input groups. - - The function accepts any type of object, although it is most useful - with "groups", as it is meant to unpack the objects inside these groups. - - Parameters - ---------- - objectslist : list - If any object in the list is a group, its contents (`obj.Group`) - are extracted and added to the output list. - - The "groups" are objects derived from `'App::DocumentObjectGroup'`, - but they can also be `'App::Part'`, or `'Building'`, `'BuildingPart'`, - `'Space'`, and `'Site'` from the Arch Workbench. - - Single items that aren't groups are added to the output list - as is. - - walls : bool, optional - It defaults to `False`. - If it is `True`, Wall and Structure objects (Arch Workbench) - are treated as groups; they are scanned for Window, Door, - and Rebar objects, and these are added to the output list. - - addgroups : bool, optional - It defaults to `False`. - If it is `True`, the group itself is kept as part of the output list. - - spaces : bool, optional - It defaults to `False`. - If it is `True`, Arch Spaces are treated as groups, - and are added to the output list. - - noarchchild : bool, optional - It defaults to `False`. - If it is `True`, the objects inside Building and BuildingParts - (Arch Workbench) aren't added to the output list. - - Returns - ------- - list - The list of objects from each group present in `objectslist`, - plus any other individual object given in `objectslist`. - """ - newlist = [] - if not isinstance(objectslist, list): - objectslist = [objectslist] - for obj in objectslist: - if obj: - if (obj.isDerivedFrom("App::DocumentObjectGroup") - or (getType(obj) in ("Building", "BuildingPart", - "Space", "Site") - and hasattr(obj, "Group"))): - if getType(obj) == "Site": - if obj.Shape: - newlist.append(obj) - if obj.isDerivedFrom("Drawing::FeaturePage"): - # skip if the group is a page - newlist.append(obj) - else: - if addgroups or (spaces and getType(obj) == "Space"): - newlist.append(obj) - if (noarchchild - and getType(obj) in ("Building", "BuildingPart")): - pass - else: - newlist.extend(getGroupContents(obj.Group, - walls, addgroups)) - else: - # print("adding ", obj.Name) - newlist.append(obj) - if walls: - newlist.extend(getWindows(obj)) - - # Clean possible duplicates - cleanlist = [] - for obj in newlist: - if obj not in cleanlist: - cleanlist.append(obj) - return cleanlist - - -getGroupContents = get_group_contents - - def print_shape(shape): """Print detailed information of a topological shape. @@ -1056,64 +877,6 @@ def get_DXF(obj,direction=None): getDXF = get_DXF -def get_movable_children(objectslist, recursive=True): - """Return a list of objects with child objects that move with a host. - - Builds a list of objects with all child objects (`obj.OutList`) - that have their `MoveWithHost` attribute set to `True`. - This function is mostly useful for Arch Workbench objects. - - Parameters - ---------- - objectslist : list of App::DocumentObject - A single scripted object or list of objects. - - recursive : bool, optional - It defaults to `True`, in which case the function - is called recursively to also extract the children of children - objects. - Otherwise, only direct children of the input objects - are added to the output list. - - Returns - ------- - list - List of children objects that have their `MoveWithHost` attribute - set to `True`. - """ - added = [] - if not isinstance(objectslist, list): - objectslist = [objectslist] - for obj in objectslist: - # Skips some objects that should never move their children - if getType(obj) not in ("Clone", "SectionPlane", - "Facebinder", "BuildingPart"): - children = obj.OutList - if hasattr(obj, "Proxy"): - if obj.Proxy: - if (hasattr(obj.Proxy, "getSiblings") - and getType(obj) not in ("Window")): - # children.extend(obj.Proxy.getSiblings(obj)) - pass - for child in children: - if hasattr(child, "MoveWithHost"): - if child.MoveWithHost: - if hasattr(obj, "CloneOf"): - if obj.CloneOf: - if obj.CloneOf.Name != child.Name: - added.append(child) - else: - added.append(child) - else: - added.append(child) - if recursive: - added.extend(getMovableChildren(children)) - return added - - -getMovableChildren = get_movable_children - - def filter_objects_for_modifiers(objects, isCopied=False): filteredObjects = [] for obj in objects: diff --git a/src/Mod/Draft/draftviewproviders/view_clone.py b/src/Mod/Draft/draftviewproviders/view_clone.py index da7c1a48aa..5bfcb59319 100644 --- a/src/Mod/Draft/draftviewproviders/view_clone.py +++ b/src/Mod/Draft/draftviewproviders/view_clone.py @@ -26,7 +26,7 @@ # \ingroup DRAFT # \brief This module provides the view provider code for the Draft Clone object. -import draftutils.utils as utils +import draftutils.groups as groups class ViewProviderClone: @@ -53,7 +53,7 @@ class ViewProviderClone: def resetColors(self, vobj): colors = [] - for o in utils.get_group_contents(vobj.Object.Objects): + for o in groups.get_group_contents(vobj.Object.Objects): if o.isDerivedFrom("Part::Feature"): if len(o.ViewObject.DiffuseColor) > 1: colors.extend(o.ViewObject.DiffuseColor) diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 795098d86a..97ebc2a4a0 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -3599,7 +3599,7 @@ def export(objectslist, filename, nospline=False, lwPoly=False): if dxfLibrary: global exportList exportList = objectslist - exportList = Draft.getGroupContents(exportList) + exportList = Draft.get_group_contents(exportList) nlist = [] exportLayers = []