ParaView Plugins Implementation

From ParaQ Wiki
Jump to navigationJump to search

ParaView_Plugins focuses on the use cases and how a developer would add a plugin. This page focuses on the actual implementation of plugins, the interfaces of which a developer of a plugin would be exposed to. This is a rough draft.

Server vs. Client Plugins

  • Server plugins should not depend on Qt and should be loadable in an instance of pvserver.
  • The client plugin implementation will use Qt's plugin code as much as possible.
  • This doesn't prevent anyone from building one shared library with both server and client plugins in it.
  • The Server and Client plugin design should be quite similar to ease development.

Server Plugins (Implementation 1)

These plugins can be used to include new VTK reader/writers/sources/filters.

vtkPVPlugin Interface

A plugin has one instance of vtkPVPlugin, which returns all interfaces the plugin implements.

class vtkPVPlugin
{
  public:
  vtkPVPlugin() {}
  ~vtkPVPlugin() {}
  virtual void GetInterfaces(vtkCollection* collection) = 0;
};
PARAVIEW_DECLARE_INTERFACE("com.Kitware.Paraview.InterfaceCollection")

Developers implement that interface as

class MyPVPlugin : public vtkObject, public vtkPVPlugin
{
  public:
  .. Standard VTK stuff ...

  void GetInterfaces(vtkCollection* collection)
  {
    ...
    add MyFancyReader to the collection
    ...
  }
};
I'm confused about what this class is providing. What is supposed to be put in collection? Is it an instance of each reader, filter, and writer the plugin provides? That makes little sense, because PV will still need to instantiate its own copies of these objects, and that is provided by the #vtkSMInterface Interface described below. What exactly does vtkPVPlugin provide?
--Ken 19:07, 5 Feb 2007 (EST)
It allows a plugin to provide implementation for more than one interface. --Clinton 20:41, 5 Feb 2007 (EST)

A macro will be provided to instantiate it and provide ParaView with entry points.

PARAVIEW_EXPORT_PLUGIN(MyPVPlugin)

vtkSMInterface Interface

An interface could be provided for adding readers/filters/etc...

class vtkSMInterface
{
  public:
  virtual ~vtkSMInterface() {}
  // add filters/readers to interpreter
  virtual void Initialize(vtkClientServerInterpreter* interp) = 0;
  // retrieve XML for readers/filters
  virtual const char* XML() = 0;
};
PARAVIEW_DECLARE_INTERFACE("com.Kitware.Paraview.Interface")

A developer would implement that interface

class MyFancyReader : public vtkObject, public vtkSMInterface
{
  public:
  .. Standard VTK stuff ...

  void Initialize(vtkClientServerInterpreter* interp)
  {
    ...
    add MyFancyReader to the interpreter
    ...
  }
  const char* XML()
  {
    // actually use kwProcessXML to generate this
    return "<ServerManagerConfiguration>\n<ProxyGroup name = \"readers\"> ....."
  }
};
How hard would it be to have CMake automatically generate the vtkSMInterface subclass? The files to be wrapped up for the client/server interpreter are already listed in the CMakeLists.txt, since it has to perform the actual wrapping. The server manager configuration files are also already listed in CMakeLists.txt since it has to run kwProcessXML to embed them in the library.
To simplify things for the user, could the CMake macro that makes the plugin automatically wrap the client server bindings, embed the xml, and generate the vtkSMInterface class? This should also make supporting the plugin easier since things like lists of class names need only be specified once in the CMakeLists.txt file rather than also in a cxx file.
--Ken 19:15, 5 Feb 2007 (EST)
Yes, it'll be possible to wrap all this up in CMake. If this is going to be the only interface ever created, then this is too much. I'll post another section for an alternate implementation. --Clinton 20:42, 5 Feb 2007 (EST)

Server Plugins (Implementation 2)

At the most basic level, there are only two things needed to make a server plugin work.

  • Adding methods for creating/manipulating VTK objects to the vtkClientServerInterpreter.
  • Adding XML to the vtkSMProxyManager.

ParaView 2 plugins consisted of a shared library with a "void {ModuleName}_Initialize(vtkClientServerInterpreter*)" function, and a separate XML file. For ParaView3, we could embed the XML into the shared library and provide a "const char* {ModuleName}_XML()" function that returns the string of XML to parse for the vtkSMProxyManager.

This is what I had in mind several months ago when I first started thinking about the requirements for plugins. I think we are both on the same page here. I vote we go with this approach. It's the simplest to implement and the simplest to use. I also cannot think of a use case where this approach will not work.
--Ken 17:27, 7 Feb 2007 (EST)

Client Plugins (Implementation 1)

  • Client plugins will work about the same, except that the interface implementations will derive from QObject instead of vtkObject.
  • Qt macros will be used instead (Q_EXPORT_PLUGIN2, Q_DECLARE_INTERFACE, etc...)
What is the value added to using the Qt macros/plugin interface here? I could see how this would save on implementation time if we could always use it, but the server plugins need to be loaded without Qt. Using multiple mechanisms for loading plugins seems to add complexity in both the implementation and use of the plugin mechanism.
--Ken 19:20, 5 Feb 2007 (EST)
Some comments:
  • The type of extensions to the GUI are not as simple as XML with VTK filters. We need something more capable, and Qt's plugin system gets us there quicker.
  • After some thought, I'd like to do approach #2 for for server extensions. In which case, there really isn't two implementations.
  • Qt's plugin system does verification to prevent loading of mixed debug/release Qt libraries, and possibly more.
--Clinton 14:44, 6 Feb 2007 (EST)
After talking second-hand with Mark, I see now that there is a lot of things that the Qt plugins can provide that are not necessary with the server plugins (especially if going with implementation 2). Also, if server plugin implementation 2 is used, then the user is only exposed client plugin mechanism, so we could use whatever we want. My exception is withdrawn.
--Ken 17:37, 7 Feb 2007 (EST)

To implement a panel for a source proxy, one would implement this interface (which already exists in the code).

class PQCOMPONENTS_EXPORT pqObjectPanelInterface
{
 public:
  /// destructor
  virtual ~pqObjectPanelInterface() {}

  /// Returns true if this panel can be created for the given the proxy.
  virtual bool canCreatePanel(pqProxy* proxy) const = 0;
  /// Creates a panel for the given proxy
  virtual pqObjectPanel* createPanel(pqProxy* proxy, QWidget* p) = 0;

  virtual QString name() const = 0;
};

Q_DECLARE_INTERFACE(pqObjectPanelInterface, "com.kitware.paraview.objectpanel")
  • We still need some kind of bridge between interfaces plugins implement and where those may be applied in the GUI.

Some thoughts...

  • The ADD_PARAVIEW_PLUGIN macro as proposed in ParaView_Plugins#Definition_Mechanism has a WIDGETS parameter. How do we know whether it is a widget that goes in the object inspector? Or a widget that goes into the multiview, or some other kind of widget?
  • We could create CMake macros that implement each interface that the ParaView GUI accepts. ADD_CUSTOM_PANEL(...) ADD_CUSTOM_VIEW(...), etc... which have output variables that get fed back into ADD_PARAVIEW_PLUGIN(...).
  • When a plugin is loaded, all interfaces are queried and put in their respective places in the GUI. Custom panels are registered with the object inspector. Custom views are registered with the multi view manager. etc...

Client Plugins (Implementation 2)

Similar to Server Plugins (2), provide a couple C functions that can be resolved when the library is loaded.

  • Requires the equivalent of a proxy manager and maybe client/server interpreter. Neither of which exist right now.
  • Need to come up with a spec (xml, interfaces, etc...) to say what kind of implementation is accepted in certain places of the GUI.
  • We still need some kind of bridge between interfaces plugins implement and where those may be applied in the GUI.
It is unclear to me which client side implementation is the right way to go. Thinking alowd (in a virtual sense), here are things that need to be defined in a client plugin.
Readers, sources, filters, and writers
Each of these only requires the name of the appropriate server manager object. Introspection provides enough information to add the appropriate entries in menues and instantiate objects.
Views
I think everything required by a view is, again, encapsulated in a server manager object. We just need a list of server manager object names to add to the view list pulldown. We may need to get Berk to verify this.
Custom filters
A custom filter is simply defined with more server manager xml.
Lookmarks
Lookmarks are defined with xml. We should be able to embed and load that in the same way as server manager objects and custom filters.
Toolbars
A toolbar can be defined as set of buttons, each with an (optional) icon and an action that amounts to invoking a reader, source, filter, writer, custom filter, or lookmark.
Custom Qt widgets
The original intention is to allow a plugin to provide a custom object inspector panel. A view might also benifit from a custom display panel. In either case, the implementation appears to be messier that I hoped and the use cases may not be strong enough to justify them. Perhaps we should just punt on this feature for now.
The majority of these items can be completely specified in the CMakeLists.txt with xml files and lists of object names. Assuming we don't implement the Qt widget feature, the only thing left to specify is the toolbar. We could define those with either a custom xml specification or some interface code. Either approach is valid, although the interface code may make the plugins easier to expand to other GUI modifications later.
One final note: regardless of what the implementation for loading toolbars looks like, it would be nice if the readers, sources, filters, writers, views, custom filters, and lookmarks could be loaded in without the use of the Qt plugin mechanism. Already the PV mailing list has complaints about the Qt license, and I suspect that there will be several users that will want to create plugins without dealing with Qt licenses. It would be best if we enabled this as long as they did not directly modify the GUI.
--Ken 18:19, 7 Feb 2007 (EST)