[Solved] There is way to make an object present in treview child of another?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
onekk
Veteran
Posts: 6205
Joined: Sat Jan 17, 2015 7:48 am
Contact:

[Solved] There is way to make an object present in treview child of another?

Post by onekk »

Hello, I'm making some work about objects.

I want to create a new "Part::FeaturePython" object that will have as childs (like in a boolean operation or in extrude) as child in the TreeView to not pollute the view and avoid to hid too many things.

I have some primitives (cubes, cones, spheres and cylinders) and complex objects, like extrusion from sketchs.

For now I have made Links and togled the visibility of the linked objects, but it is a suboptimal solution.

TIA for any help.

Regards

Carlo D.
Last edited by onekk on Fri Jun 03, 2022 10:38 am, edited 1 time in total.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
User avatar
wandererfan
Veteran
Posts: 6309
Joined: Tue Nov 06, 2012 5:42 pm
Contact:

Re: There is way to make an object present in treview child of another?

Post by wandererfan »

onekk wrote: Fri May 27, 2022 10:48 am I want to create a new "Part::FeaturePython" object that will have as childs (like in a boolean operation or in extrude) as child in the TreeView to not pollute the view and avoid to hid too many things.
obj.ViewObject.claimChildren() controls what appears below obj in the tree.
User avatar
onekk
Veteran
Posts: 6205
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: There is way to make an object present in treview child of another?

Post by onekk »

wandererfan wrote: Fri May 27, 2022 3:02 pm obj.ViewObject.claimChildren() controls what appears below obj in the tree.
Thanks, I will try it

EDIT:

claimChildren() from the documentation will return the children Objects, could you kindly point me on some Python examples to study the mechanics?


Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
User avatar
wandererfan
Veteran
Posts: 6309
Joined: Tue Nov 06, 2012 5:42 pm
Contact:

Re: There is way to make an object present in treview child of another?

Post by wandererfan »

onekk wrote: Fri May 27, 2022 3:26 pm claimChildren() from the documentation will return the children Objects, could you kindly point me on some Python examples to study the mechanics?
Maybe Draft/draftviewproviders/view_base.py?
TheMarkster
Veteran
Posts: 5513
Joined: Thu Apr 05, 2018 1:53 am

Re: There is way to make an object present in treview child of another?

Post by TheMarkster »

You return the list of document objects you want to appear as children in the tree view, or an empty list if none are to be claimed. If it is sensible to also delete the children when the user deletes the feature python object, then also look at onDelete(self, vobj, subelements). I use both of these in the pdwrapper macro.
User avatar
onekk
Veteran
Posts: 6205
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: There is way to make an object present in treview child of another?

Post by onekk »

TheMarkster wrote: Fri May 27, 2022 3:52 pm You return the list of document objects you want to appear as children in the tree view, or an empty list if none are to be claimed. If it is sensible to also delete the children when the user deletes the feature python object, then also look at onDelete(self, vobj, subelements). I use both of these in the pdwrapper macro.
Thanks, I've read your code but I'm getting lost in analyzing the code.

I could guess that there is a need of a ViewProvider with some functions to make things work, this complicated things some more.

I was hoping that there is around some examples maybe like:

https://wiki.freecadweb.org/Scripted_ob ... attachment

Where things are explained in a more easy way to catch the whole mechanics.

For now I've managed to link the objects to new created object and make the original objects "greyed out" using Visibility = False, If I don't get to make them children of the newly created object, I will left this for some future improvements.


Thanks and Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
User avatar
Zolko
Veteran
Posts: 2213
Joined: Mon Dec 17, 2018 10:02 am

Re: There is way to make an object present in treview child of another?

Post by Zolko »

onekk wrote: Fri May 27, 2022 4:18 pm I could guess that there is a need of a ViewProvider with some functions to make things work, this complicated things some more.
yes, you need to define a ViewProvider() for your object. You can find a minimalistic example on how to setup and use one here:

https://github.com/Zolko-123/FreeCAD_As ... ts.py#L301
try the Assembly4 workbench for FreCAD — tutorials here and here
User avatar
onekk
Veteran
Posts: 6205
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: There is way to make an object present in treview child of another?

Post by onekk »

Thanks @Zolko I will see your code tomorrow, and let you know if I've solved.


Thanks again and Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
User avatar
onekk
Veteran
Posts: 6205
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: There is way to make an object present in treview child of another?

Post by onekk »

Zolko wrote: Mon May 30, 2022 9:44 am
Hello, I've tried your code, and probably I've not guessed the points:

Code: Select all

class ViewProvider_EM(object):
    """ViewProvider Object."""

    def __init__(self, vobj):
        """Init things."""
        vobj.Proxy = self
        self.attach(vobj)

    def attach(self, vobj):
        """Attach things."""
        self.ViewObject = vobj
        self.Object = vobj.Object


    def claimChildren(self):
        """Return objects that will be placed under it in the tree view."""
        if hasattr(self.Object, "ShowElement") and self.Object.ShowElement:
            return self.Object.ElementList
        elif hasattr(self.Object, "SourceObject"):
            return [self.Object.SourceObject]

    '''
    def getIcon(self):
        """Return an icon corresponding to the array type."""
        iconFile = None
        if hasattr(self.Object,"ArrayType"):
            tp = self.Object.ArrayType
            if tp=='Circular Array':
                iconFile = os.path.join( Asm4.iconPath, 'Asm4_PolarArray.svg')
            if tp=='Linear Array':
                iconFile = os.path.join( Asm4.iconPath, 'Asm4_LinkArray.svg')
        if iconFile:
            return iconFile
    '''

    def __getstate__(self):
        """Get state."""
        return None

    def __setstate__(self, _state):
        """Set state."""
        return None
There are errors, and I could suppose that:

Code: Select all

    def claimChildren(self):
        """Return objects that will be placed under it in the tree view."""
        if hasattr(self.Object, "ShowElement") and self.Object.ShowElement:
            return self.Object.ElementList
        elif hasattr(self.Object, "SourceObject"):
            return [self.Object.SourceObject]

And probably this code is not exactly the best, as it is a mix of two different source.

Code: Select all

    obj = doc.addObject("Part::FeaturePython", "EM_Object")
    obj.Label = "EM_Object"
    EM_Object(obj, sel)

    obj.ViewObject.Proxy = 0
    ViewProvider_EM(obj.ViewObject)
    doc.recompute()
NOw I 've linked selected objects, but if I want them to be child of my "EM_Object", how I've to modify your code and very probably what property I have to add to the "EM_Object" code?

I know that is more than an advice, but I'm almost lost due to the lack of information.

TIA and Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
User avatar
Zolko
Veteran
Posts: 2213
Joined: Mon Dec 17, 2018 10:02 am

Re: There is way to make an object present in treview child of another?

Post by Zolko »

onekk wrote: Tue May 31, 2022 11:12 am

Code: Select all

class ViewProvider_EM(object):
    """ViewProvider Object."""

    def __init__(self, vobj):
        """Init things."""
        vobj.Proxy = self
        self.attach(vobj)

    def attach(self, vobj):
        """Attach things."""
        self.ViewObject = vobj
        self.Object = vobj.Object

    def __getstate__(self):
        """Get state."""
        return None

    def __setstate__(self, _state):
        """Set state."""
        return None
I think these are necessary minimal requirements. I just copied them from other code. The interesting bit is this:


Code: Select all

    def claimChildren(self):
        """Return objects that will be placed under it in the tree view."""
        if hasattr(self.Object, "ShowElement") and self.Object.ShowElement:
            return self.Object.ElementList
        elif hasattr(self.Object, "SourceObject"):
            return [self.Object.SourceObject]
this function must return what you want to see in the tree. So that (future child-) object needs to be referenced in your custom object (EM-Object ?). So your EM-Object needs a variable/property knowing that child-object. But for that, the viewprovider needs to know the object itself, and this is done by:

Code: Select all

    def attach(self, vobj):
        """Attach things."""
        self.ViewObject = vobj
        self.Object = vobj.Object
ANd now, inside the viewprovider, self.Object is your EM_Object. If your sub-object (the child-object) is EM_Object.selobject, then the claimChildrne() function must return self.Object.selobject

And probably this code is not exactly the best, as it is a mix of two different source.

Code: Select all

    obj = doc.addObject("Part::FeaturePython", "EM_Object")
    obj.Label = "EM_Object"
    EM_Object(obj, sel)

    obj.ViewObject.Proxy = 0
    ViewProvider_EM(obj.ViewObject)
    doc.recompute()
NOw I 've linked selected objects, but if I want them to be child of my "EM_Object", how I've to modify your code and very probably what property I have to add to the "EM_Object" code?
obj.ViewObject.Proxy = 0 seems strange, where did you get that from ? Anyway, inside the EM_Object, "sel" needs to be known, and that is what claimChildren() must return. In short, the child needs to be known by the parent (that's the EM_Object), and the parent must be known by the viewprovider (that's the attach() function). You might try :

Code: Select all

    obj = doc.addObject("Part::FeaturePython", "EM_Object")
    EM_Object(obj, sel)
    ViewProvider_EM(obj.ViewObject)
    doc.recompute()
or

Code: Select all

...
EM_Object.ViewObject.Proxy = ViewProvider_EM()
dunno which is the correct usage. you can also look into the Draft ViewProvider:

https://github.com/FreeCAD/FreeCAD/blob ... ew_base.py
try the Assembly4 workbench for FreCAD — tutorials here and here
Post Reply