Monday, December 16, 2013

Qt Application Plugins

Link for Code on Google Drive.
As it happens, recently I was needed to learn about Qt Plugins. The problem scenario was as follows: We have an application which has a number of dialogs. There's one dialog we customize for each client. We have to branch the application in SVN. Normally this would not be a problem but we are introducing incremental functionality into the core of the app and it becomes tiring to sync all the changes into all the branches.
So it's decided that we would separate the single dialog which differs from client to client, into a plugin and make branches for that. This way we will be saved from headache of syncing so much code across all the branches. Instead the branches will contain only the dialog which is different for every client.
So as a primary R&D on Qt plugins I prepared a basic application which shows a PluginContainer class which supports plugins and couple of plugin classes namely FivePlugin and SixPlugin.
Following is my journey to this solution.

1. I declared an interface class which will be used to access all the plugins from PluginContainer class.
It's definition is as follows:

class TrueNumberInterface
{

public:

virtual ~TrueNumberInterface() { }

virtual float getTrueNumber() = 0;

};

Q_DECLARE_INTERFACE(TrueNumberInterface,"com.compMy.mathPlugins.TrueNumberInterface/1.0");

What we have here is a virtual public destructor which the compiler needs otherwise the program crashes at runtime. Next to it is a virtual function which will be implemented in the plugin. It's this function which will provide us with the plugin functionality. At present here I have only one function, but depending on total functionality, you can have a number of functions providing various functionality. This functionality is common between all plugins that implement this (TrueNumberInterface) interface.
Lastly we use Q_DECLARE_INTERFACE macro which is declared in QtPlugins headers to associate an identifier with our plugin.

Next we have PluginContainer, we have loadPlugins() function using which we load all available plugins in the plugins directory.

QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
if (TrueNumberInterface *interface =

qobject_cast<TrueNumberInterface *>(loader.instance()))

interfaces.append(interface);

Here we use a QList<TrueNumberInterface*> interfaces; to load all plugins. We use QPluginLoader class to access the plugins one by one; then caste the retrieved plugin to interface so that we can use it as an object of TrueNumberInterface.

Upto this point we have loaded the plugins. To use them we can use the individual TrueNumberInterface objects as follows.

foreach (TrueNumberInterface *interface, interfaces)
{

ui->cbPluginResults->addItem(QString::number(interface->getTrueNumber()));

}

This way we access various functionality provided by plugins. This is just a startup with Qt Plugins and there is a lot of other functionality provided by Qt plugins e.g. a plugin may implement two or more interfaces thus providing a lot of functionality in one single package etc.

No comments:

Post a Comment