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?
Returning True switches the object into editing, but no dragger appears.
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.
how to implement python feature's setEdit properly?
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
- 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?
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()
Re: how to implement python feature's setEdit properly?
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
I looked at that some time ago then forgot about it... I'll have a look again
Re: how to implement python feature's setEdit properly?
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?
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?
- 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?
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).
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).
Re: how to implement python feature's setEdit properly?
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.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.
*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?
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.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...)