New FeaturePython is grey

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
bernd
Veteran
Posts: 12849
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

New FeaturePython is grey

Post by bernd »

Assumed is a very simple FeaturePython:

Code: Select all

class _MyFeaturePython:
    def __init__(self, obj):
        "'''Add some custom properties to our box feature'''"
        obj.addProperty("App::PropertyBool","MySwitch","Base","ToolTipSwitchMyFeaturePython")
        obj.MySwitch = False
        obj.Proxy = self

    def execute(self, fp):
        "'''Do something when doing a recomputation, this method is mandatory'''"
        FreeCAD.Console.PrintMessage("Recompute MyFeaturePython\n")


class _ViewProviderMyFeaturePython:
    "A View Provider for the MyFeaturePython object"

    def __init__(self, vobj):
        vobj.Proxy = self

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

    def __getstate__(self):
        return None

    def __setstate__(self, state):
        return None

a new instanz of the class MyFeaturePython

Code: Select all

# create a new FreeCAD Document object
myobj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","MyObject")
# create instanzes of class _MyFeaturePython and _ViewProviderMyFeaturePython
_MyFeaturePython(myobj)
_ViewProviderMyFeaturePython(myobj.ViewObject)
# recompute
FreeCAD.ActiveDocument.recompute()
Why is the new object grey in treeview ? It looks like it is not visible? How do I get some color ? Visibility is set to true.

Does someone know what am I missing?
User avatar
yorik
Founder
Posts: 13630
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: New FeaturePython is grey

Post by yorik »

Usually when a feature is greyed out in the tree, it is because either it has no view provider, or the view provider has some problems... Maybe some more methods (getDisplayMode, etc...) of the view provider are mandatory, I don't remember exactly which ones are or not... Look into src/Mod/TemplatePyMod/FeaturePython.py, you should have all of them there.
User avatar
bernd
Veteran
Posts: 12849
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: New FeaturePython is grey

Post by bernd »

Thanks Yorik, good examples ! They helped me I found a solution !!

instead

Code: Select all

myobj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","MyObject")
it should be

Code: Select all

myobj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","MyObject")
User avatar
bernd
Veteran
Posts: 12849
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: New FeaturePython is grey

Post by bernd »

simple scripted object class definition:

Code: Select all

class MyFeaturePython:
    def __init__(self, obj):
        "'''Add a custom property to the FeaturePython'''"
        obj.addProperty("App::PropertyBool","MySwitch","Base","ToolTipSwitchMyFeaturePython")
        obj.MySwitch = False
        obj.Proxy = self

    def execute(self, fp):
        "'''Do something when doing a recomputation, this method is mandatory'''"
        FreeCAD.Console.PrintMessage("Recompute MyFeaturePython\n")
create some objects

Code: Select all

FreeCAD.newDocument()

myobjPart = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","MyObject")  # coloured icon in tree
MyFeaturePython(myobjPart)
myobjPart.ViewObject.Proxy = 0

myobjApp = FreeCAD.ActiveDocument.addObject("App::FeaturePython","MyObject")    # grey icon in tree
MyFeaturePython(myobjApp)
myobjApp.ViewObject.Proxy = 0

# recompute
FreeCAD.ActiveDocument.recompute()
Mhh why is Part::FeaturePython coloured and App::FeaturePython grey in TreeView? Since I do not have a shape in my scripted object I would tend to use App::FeaturePython but it looks very poor in TreeView. What should I use if I do not need a shape in my scripted object?

Could someone bring some light in the darkness?
User avatar
yorik
Founder
Posts: 13630
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: New FeaturePython is grey

Post by yorik »

Indeed you should be able to use App::FeaturePython without problems, it is used for ex. for the dimension object in Draft...
My guess is that the Part::FeaturePython comes with a "pre-filled" view provider. When you are using App::FeaturePython, probably there are some things you need to do in your python class that are mandatory, that you didn't do (but that exist in Part::FeaturePython)... Adding a default Display Mode maybe?
User avatar
bernd
Veteran
Posts: 12849
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: New FeaturePython is grey

Post by bernd »

yorik wrote:... Adding a default Display Mode maybe?
Yes the display mode ... :)

The ViewProvider of an App::FeaturePython needs at least a minimalistic DisplayMode

Code: Select all

    def attach(self, vobj):
        self.standard = coin.SoGroup()
        vobj.addDisplayMode(self.standard,"Standard");

    def getDisplayModes(self,obj):
        "'''Return a list of display modes.'''"
        return ["Standard"]

    def getDefaultDisplayMode(self):
        "'''Return the name of the default display mode. It must be defined in getDisplayModes.'''"
        return "Standard"
full example of a simple scripted object

Code: Select all

# simple scripted object class definition:
class MyFeaturePython:
    def __init__(self, obj):
        "'''Add a custom property to the FeaturePython'''"
        obj.addProperty("App::PropertyBool","MySwitch","Base","ToolTipSwitchMyFeaturePython")
        obj.MySwitch = False
        obj.Proxy = self

    def execute(self, fp):
        "'''Do something when doing a recomputation, this method is mandatory'''"
        FreeCAD.Console.PrintMessage("Recompute MyFeaturePython\n")


class _ViewProviderMyFeaturePython:
    "A View Provider for the MyFeaturePython object"

    def __init__(self, vobj):
        vobj.Proxy = self

    def attach(self, vobj):
        self.standard = coin.SoGroup()
        vobj.addDisplayMode(self.standard,"Standard");

    def getDisplayModes(self,obj):
        "'''Return a list of display modes.'''"
        return ["Standard"]

    def getDefaultDisplayMode(self):
        "'''Return the name of the default display mode. It must be defined in getDisplayModes.'''"
        return "Standard"


# create some objects
from pivy import coin
FreeCAD.newDocument()

myobjPart = FreeCAD.ActiveDocument.addObject("Part::FeaturePython","MyObject")
MyFeaturePython(myobjPart)
_ViewProviderMyFeaturePython(myobjPart.ViewObject)

myobjApp = FreeCAD.ActiveDocument.addObject("App::FeaturePython","MyObject")
MyFeaturePython(myobjApp)
_ViewProviderMyFeaturePython(myobjApp.ViewObject)

# recompute
FreeCAD.ActiveDocument.recompute()
the icon of the App::FeaturePython is coloured :D
User avatar
bernd
Veteran
Posts: 12849
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: New FeaturePython is grey

Post by bernd »

New problems I'm not able to solve ... :( I added a simple EditTaksPanel but neither on call of def accept nor def reject the def unsetEdit of the ViewProvider is called ?!? What do I need to call in def reject or def accept to close the dialog ?!

How to reproduce: Copy the code into the PythonKnsole, double click on the new object. Try to click on OK or Cancel the dialog stays open :(

Code: Select all

#################################################################################################################
# simple scripted object class definition:
class MyFeaturePython:
    def __init__(self, obj):
        obj.addProperty("App::PropertyBool","MySwitch","Base","ToolTipSwitchMyFeaturePython")
        obj.MySwitch = False
        obj.Proxy = self

    def execute(self, fp):
        FreeCAD.Console.PrintMessage("Recompute MyFeaturePython\n")


class _ViewProviderMyFeaturePython:
    def __init__(self, vobj):
        vobj.Proxy = self

    def attach(self, vobj):
        self.ViewObject = vobj
        self.Object = vobj.Object
        self.standard = coin.SoGroup()
        vobj.addDisplayMode(self.standard,"Standard");

    def getDisplayModes(self,obj):
        return ["Standard"]

    def getDefaultDisplayMode(self):
        return "Standard"

    def setEdit(self, vobj, mode = 0):
        taskd = _FemShellThicknessTaskPanel(self.Object)
        taskd.obj = vobj.Object
        #taskd.update()                          # When would this be needed ?
        FreeCADGui.Control.showDialog(taskd)
        return True

    def unsetEdit(self, vobj, mode = 0):
        print 'unset'
        FreeCADGui.Control.closeDialog()
        return

    def doubleClicked(self,vobj):
        self.setEdit(vobj)


class _FemShellThicknessTaskPanel:
    def __init__(self, obj):
        FreeCADGui.Selection.clearSelection()
        self.sel_server = None
        self.obj = obj
        #self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/MechanicalMaterial.ui")

        self.form = QtGui.QWidget()
        self.form.setObjectName("TaskPanel")
        self.addButton = QtGui.QPushButton(self.form)
        self.addButton.setText("PushButton")

    def accept(self):
        print 'accept and resetEdit'
        FreeCADGui.ActiveDocument.resetEdit()

    def reject(self):
        print 'reject and resetEdit'
        FreeCADGui.ActiveDocument.resetEdit()




# create an objects
from PySide import QtCore, QtGui
from pivy import coin
FreeCAD.newDocument()


myobjApp = FreeCAD.ActiveDocument.addObject("App::FeaturePython","MyObject")
MyFeaturePython(myobjApp)
_ViewProviderMyFeaturePython(myobjApp.ViewObject)

# recompute
FreeCAD.ActiveDocument.recompute()



User avatar
bernd
Veteran
Posts: 12849
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: New FeaturePython is grey

Post by bernd »

found a possibility without even use the setEdit and unsetEdit defs.

call the TaskPanel in def doubleClicked of the ViewProvider:

Code: Select all

    def doubleClicked(self,vobj):
        taskd = _FemShellThicknessTaskPanel(self.Object)
        taskd.obj = vobj.Object
        #taskd.update()                          # When would this be needed ?
        FreeCADGui.Control.showDialog(taskd)
close the TaskPanel in the accept and reject defs off the TaskPanel:

Code: Select all

    def accept(self):
        FreeCADGui.ActiveDocument.resetEdit()
        FreeCADGui.Control.closeDialog()

    def reject(self):
        FreeCADGui.ActiveDocument.resetEdit()
        FreeCADGui.Control.closeDialog()

complete code

Code: Select all

#################################################################################################################
# simple scripted object class definition:
class MyFeaturePython:
    def __init__(self, obj):
        obj.addProperty("App::PropertyBool","MySwitch","Base","ToolTipSwitchMyFeaturePython")
        obj.MySwitch = False
        obj.Proxy = self

    def execute(self, fp):
        FreeCAD.Console.PrintMessage("Recompute MyFeaturePython\n")


class _ViewProviderMyFeaturePython:
    def __init__(self, vobj):
        vobj.Proxy = self

    def attach(self, vobj):
        self.ViewObject = vobj
        self.Object = vobj.Object
        self.standard = coin.SoGroup()
        vobj.addDisplayMode(self.standard,"Standard");

    def getDisplayModes(self,obj):
        return ["Standard"]

    def getDefaultDisplayMode(self):
        return "Standard"

    def doubleClicked(self,vobj):
        taskd = _FemShellThicknessTaskPanel(self.Object)
        taskd.obj = vobj.Object
        #taskd.update()                          # When would this be needed ?
        FreeCADGui.Control.showDialog(taskd)


class _FemShellThicknessTaskPanel:
    def __init__(self, obj):
        FreeCADGui.Selection.clearSelection()
        self.sel_server = None
        self.obj = obj
        #self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/MechanicalMaterial.ui")

        self.form = QtGui.QWidget()
        self.form.setObjectName("TaskPanel")
        self.addButton = QtGui.QPushButton(self.form)
        self.addButton.setText("PushButton")

    def accept(self):
        print 'accept and resetEdit'
        FreeCADGui.ActiveDocument.resetEdit()
        FreeCADGui.Control.closeDialog()

    def reject(self):
        print 'reject and resetEdit'
        FreeCADGui.ActiveDocument.resetEdit()
        FreeCADGui.Control.closeDialog()




# create an objects
from PySide import QtCore, QtGui
from pivy import coin
FreeCAD.newDocument()


myobjApp = FreeCAD.ActiveDocument.addObject("App::FeaturePython","MyObject")
MyFeaturePython(myobjApp)
_ViewProviderMyFeaturePython(myobjApp.ViewObject)

# recompute
FreeCAD.ActiveDocument.recompute()
User avatar
yorik
Founder
Posts: 13630
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: New FeaturePython is grey

Post by yorik »

bernd wrote:close the TaskPanel in the accept and reject defs off the TaskPanel
Yes, out of memory I think that's what I've been doing too...
wmayer
Founder
Posts: 20202
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: New FeaturePython is grey

Post by wmayer »

How to reproduce: Copy the code into the PythonKnsole, double click on the new object. Try to click on OK or Cancel the dialog stays open
You must return True.

Code: Select all

class _FemShellThicknessTaskPanel:
...
    def accept(self):
        print 'accept and resetEdit'
        FreeCADGui.ActiveDocument.resetEdit()
        return True

    def reject(self):
        print 'reject and resetEdit'
        FreeCADGui.ActiveDocument.resetEdit()
        return True
Post Reply