-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow the definition of public interfaces for plugins #1370
Conversation
This is particularly interesting to get access to functionality from python
To make use of it: from qgis import globe glb = iface.pluginInterface( 'libglobeplugin' ) # On windows it's just 'globeplugin' glb.syncExtent()
Hi Matthias so if I understand the PR correctly, this adds the possibility to implement QgsPluginInterface interface within plugins and thus allow third parties to access some of the plugin's functionality. In order to access the functionality, in C++, one needs access to plugin's header file, in Python there has to be a sip-based module. Throwing in some ideas... I am wondering if we couldn't use QObject introspection with QMetaObject when working with plugin interface objects. The introspection allows us to find out what are instance's signals, slots and properties. At least in Python, a helper could automatically add appropriate Python methods and properties. This would avoid the need to deliver also additional SIP modules and plugin headers. Additionally, IIRC on Mac there are problems if a plugin is used both as a shared library and as a plugin (in CMake SHARED vs MODULE argument for ADD_LIBRARY) - for that GRASS provider+plugin come with qgis-grass library which contains common code used by both provider and plugin. In case we would decide for QObject-based approach, instead of having explicit plugin interface classes, the QgisInterface could allow registration of custom QObject instances with a known name. That could be then used also by some other parts of QGIS application (which are not exposed in API) to exposes some functionality. In the future, for globe plugin, it would be good to actually have qgis 3D library that would provide the functionality that could be expected from the plugin interface. But I understand that would mean a lot of work :-) |
assigned to @wonder-sk |
Hi Martin, I don't know if the QObject based approach you propose works, I don't have the experience to answer this question, so I cannot comment on the feasibility. How would you handle custom classes required by the plugin interface? As soon as there is no simple interface with only basic setters and getters using primitive datatypes or pyqt datatypes there is the need for further header files / sip bindings anyway. Couldn't being forced to use the signal/slot/properties system also add an overhead which can result in a performance impact (or other undesired effects)? IMO, if somebody wants this type of ducktyping support for his objects, he can just write a python plugin and it will do all that. If there is a C++ plugin written, I prefer to keep it the C++ way where headers need be provided in order to use the code, compiler, IDE etc. are all built to support this style of development. |
True, with the need to provide wrappers for further data types it would get more complicated. My feeling is that if there is a need to export some classes, this is best done by adding the classes to one of QGIS libraries. For example, if we wanted to provide georeferencer functionality outside of the plugin, the best idea would be to move the code to the analysis library and provide wrappers there. The plugin interface (if still needed) could then just provide access to the "live" instance. My inspiration comes mainly from QML - as far as I understand, objects there are based on QObject and the interaction is done with properties, signals and slots.
I assume the overhead is practically non-existent unless one would do millions of calls... I have no data to confirm that though :-) |
What about third-party libs on which plugins depend? PS: I am not sure if I will ever integrate these wrappers, but they serve as a good example. |
There's always trouble with third-party libs :-) If we needed to pass pointer to some instances of their classes, It should be fairly easy to pass the pointers through QVariant. That way the client may also use the API directly (now talking about C/C++). But it is also worth noting that if we provide a plugin interface for such third-party data structures, we are effectively making them a part of our API, because any other plugin then may start using that functionality (even if technically it is not a part of QGIS libraries). |
And QVariant adds more overhead again. And you need to start casting and checking if the cast went ok. I like the compiler way of checking at build time and letting me know that I'm a moron if I try to pass class A when it expects class B. Another problem with QVariant is, that it's not perfect in terms of subclassing. If you have subclass B inheriting from subclass A, and you wrap an object of B in a QVariant and on the other end retrieve the value as A, the conversion will fail. It's not hard to work around this, but it's a possible source of problems and you need to write code that deals with situations, that the compiler could check in well-written code in a language like C++. What's the main drawback of my proposed approach again?
I personally don't consider the first one to be a drawback, but a different approach, more C++ like by declaring the interface (and this PR only applies to C++ plugins) in a header file. |
As an example, the method
syncExtent()
from the globe plugin can be called from python.Question: should a "lib" prefix be stripped away for platform independence?