how to implement python feature's setEdit properly?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

how to implement python feature's setEdit properly?

Post by DeepSOIC »

Hi!
I'm implementing a custom editing mode for ShapeGroup container in Part-o-magic. And I came across a problem.

I implemented setEdit(self, selfvp, mode), and it works. But, now if I right-click it in tree and choose "transform", transform is not initiated. Instead, my edit mode is launched.

So I added a check to mode, and if mode == 0, my editing is to be initiated, otherwise... what to do otherwise?
:arrow: Returning True switches the object into editing, but no dragger appears.
:arrow: Returning False or None suppresses the edit mode altogether.
The only working solution I found so far is to raise an exception in setEdit, for example raise NotImplementedError(). The only annoying thing about it is that the error is printed to report view.

relevant posts:
https://forum.freecadweb.org/viewtopic. ... it#p161062 - commit that changed the behavior.
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: how to implement python feature's setEdit properly?

Post by DeepSOIC »

Code that I mentioned, with exception, that kind-of works:

Code: Select all

class ViewProviderShapeGroup:
    ...
    def setEdit(self, selfvp, mode):
        if mode == 0:
            try:
            	#long boring irrelevant code that makes up my edit mode
            except Exception as err:
                App.Console.PrintError("Error in ShapeGroup setEdit: {err}\n".format(err= err.message))
                return False
            return True
        raise NotImplementedError()
User avatar
yorik
Founder
Posts: 13630
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: how to implement python feature's setEdit properly?

Post by yorik »

I think what is not implemented is falling back from python to C++ edit modes.. For example, the C++ view provider of Parts has a mode for applying per-face color which is something like mode 4 or mode 5, i dont remember. If you make a c++ view provider derived from Part that implements mode 0, mode 4 is still called when needed. However, if you implement a python view provider, the C++ mode 4 is not called anymore, only python mode 4, if existing.

I looked at that some time ago then forgot about it... I'll have a look again
wmayer
Founder
Posts: 20202
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: how to implement python feature's setEdit properly?

Post by wmayer »

Currently, the setEdit mode framework doesn't work very well when a sub-class wants to extend the modes of the base class. Have a look at this comment: https://freecadweb.org/tracker/view.php?id=1954#c7874

An alternative way would be to replace the int parameter with a string which gives a brief description (only for internal use) what it is about. Then for the programmer it's easier to decide which chosen mode to handle. Another advantage is that this way a sub-class could disable or remove an edit mode of the base class. In this case it would still have to know the above internal string to remove the corresponding action from the menu.

Any opinions?
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: how to implement python feature's setEdit properly?

Post by DeepSOIC »

I have no idea how context menu is involved here. But for calling c++ edit mode, I can suggest:
1. use NotImplementedError() as a command to call c++ setEdit.
Like it does now, just suppress its printout to report view
2. use special return value, like None.
This is somewhat equivalent to the exception approach, except a little bit less easy to read in code.
3. pass c++ setEdit as a python callable, in an additional argument to setEdit
Maximum flexibility, but it breaks all existing code because of changed function footprint.
4. expose c++ setEdit as a method of viewprovider (btw, does calling selfvp.setEdit(...) cause recursion?.. I didn't try, I assume it does...)

My preference is on 1+4 (implement both).
User avatar
yorik
Founder
Posts: 13630
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: how to implement python feature's setEdit properly?

Post by yorik »

wmayer wrote:An alternative way would be to replace the int parameter with a string which gives a brief description (only for internal use) what it is about.
This would indeed make it easier, but not fundamentally change the base problem, no? If you create a subclass, being c++ or python, you would still need to know what are the edit modes implemented by the base class. But I think, anyway, if you make a sub class, you NEED to inform about what the base class does. And when you do, it doesn't matter much if implemented modes are 0, 1 and 5 or "edit geometry", "edit something else" and "change color", because you can discover that easily enough.

*EDIT* Actually not so easily... if the base class is itself a sub class of something else...

Maybe it should be just some code convention? Like, always add a comment or something in view provider code, that says what edit modes are implemented by this VP?
DeepSOIC wrote:4. expose c++ setEdit as a method of viewprovider (btw, does calling selfvp.setEdit(...) cause recursion?.. I didn't try, I assume it does...)
For me this should be automatic, like in Qt when you choose to handle an event or not... Ex: In your VP's setEdit method, you return True if you handled it, or False if you didn't. In that last case, the setEdit of the parent class is called. So you would only need to return False to call the corresponding edit mode of the parent class. This currently works for c++ VPs (I think) but not for python VPs.
Post Reply