Author: David Garcia Garzon / Wiki source
When I was developing widgets plugins for Qt Designer, I encountered too many of reasons for a plugin to not work properly. Even worse, all that reasons are really obscure and silent. Designer, at least in its vanila version, doesn't offer any hint why it is not loading a given plugin. This article tries to give some light to those reasons and gives some tricks to spot them.
The context of this article is Qt4 and Linux. Feel free to send me your own experiences on other contexts.
This error should be the first to be explained because a symbol missing in the plugin is so common and you won't get any feedback when it happens. When you build the plugin, the linker won't complaint about missing symbols as it is a dynamic library pending to be linked on runtime. Later, when the plugin host (either designer or a QUiLoader based app) tries to load it and fails, it does not complain at all neither. Just that the plugin won't be available but no error message is displayed.
Fortunately there is a quick way of checking if this is happening. Just build an empty main function like this:
// plugintest.cxx int main() { return 0; } and do: $ g++ plugintest.cxx libMyPlugin.so
If the linker complains about missing symbols, those missing symbols are the ones preventing the plugin to load.
Remember that Qt plugins must be linked to any symbols they use. So you must link also:
The plugin must be in some place that designer or a QUiLoader based app could find it. Of course, no message will be given to you if you place it in the wrong location.
There is a good way to check whether you are not placing the plugin on the proper location. Take some of the plugins designer already loads (see About/Plugins) and move it to the location you are placing your own widget. If you stop seeing it, you have a location problem.
Hosts search for plugins in a sequence of locations. Designer plugins must be placed inside the 'designer' folder within such location. For example, if the host looks for plugins at /some/location/for/plugins, designer plugins should be at /some/location/for/plugins/designer. So don't forget the designer folder!
Which are those locations?
The first location is the standard path where the plugins are placed on your system. Normally at $QTDIR/plugins, which depends on the actual value of QTDIR environment variable in your system. So the final path for your widgets plugin libMyPlugin.so will be
$QTDIR/plugins/designer/libMyPlugin.so If you don't know where the QTDIR var points to, just look for some plugin that comes with Qt such as libqt3supportplugin.so.
The second location to place the plugin is in the same path where the host is. So, if you binary is in /some/path/hostbinary, the designer plugin you should be at /some/path/designer/libMyPlugin.so. In Unix, this is not useful to run Designer because you cannot place a 'designer' folder in the same folder that the 'designer' binary is. But it is very useful for a host application while you are developing it, because you don't have to install the plugin as root every time.
Finally, qt uses an environment variable named 'QT_PLUGIN_PATH'. It contains a list of plugin directories using the same syntax than the PATH variable in your system, that is separated by colons in Linux and semicolons in windows. Beware that such paths should be the ones without the 'designer' folder. If you place your plugin at /the/location/designer/libMyPlugin.so, the QT_PLUGIN_PATH should contain /the/location without the designer path.
If you don't want to rely on those paths you can force a path using QCoreApplication::addLibraryPath or QUiLoader::addPluginPath. See QCoreApplication and QUiLoader API's for details.
If you want to know the complete list of paths your plugins are being searched in execute the following code in your host:
QStringList paths = QCoreApplication::libraryPaths(); for (QStringList::iterator it = paths.begin(); it!=paths.end(); it++) { std::cout << "Looking for plugins at path: " << it->toStdString() << std::endl; }
Because different locations are available, is common that different versions of the library are placed in different places. This generates no problem when they are the same version. But when different versions are available all of them are loaded.
To spot this reason, remove the library. If after that it still loads, it is loading a dupped library anywhere else.
Double check whether you are compiling with the same Qt debug or Qt release mode than the host application. Normally designer is compiled in release mode, that means that your plugin and your host should be both compiled with the -DQT_NO_DEBUG option enabled and that they must be linked against the release version of the Qt libraries. Note that debug version of Qt4 libraries normally has a suffix ('d' on windows, or '_debug' in linux).
In Linux, you can use the ldd command to list the libraries a built binary is linking to.
Maybe your plugin loads but you don't see some of the widgets. Note that if you do not return a correct xml on the reimplementation of the QDesignerCustomWidgetInterface::domXml method, your widget may be instanciated but it won't appear on the designer widget toolbox.
That means that an .ui file containing the widget will display it properly but that the widget toolbox has no entry to add it. So, the spotting procedure is a little trickier:
Sometimes your plugin loads well and you can even use it from the designer. But once you save the .ui file and you try to load it again, you see that your widget has promoted to some base class such as QWidget, loosing any any specific properties.
This is a symptom that you didn't place the Q_OBJECT macro on the widget class declaration.
A widget without Q_OBJECT macro in its declaration may work properly. It just uses the Metaobject information of the base class. But designer uses such metaobject information to writedown the ui file. It takes the class name, the properties... But the metaobject information says that it is a QWidget and not YourWidget and this is what the ui file will contain. When you load it, any trace of YourWidget has dissapeared.
While trying to find out the reasons the plugins don't load, I also tried some apparent failure reasons. After having the plugin working i tried again most of the hypothesis. Here is a list with the things that do not interfere with the loading. (Tested just in Linux)
Qt comes with a lot of examples that work out the box. But as soon you try to modify them, you come up with those problems. This is more noticeable, when you are using a different build chain than qmake as it was my case.
Of course that 'a hundred reasons' was an exaggeration. But when you have no feedback on what's happening even one reason is worth ten. It would be nicer that Qt would give you some kind of warning when any of the problems is happening, such as the missing symbols or the bad xml one. Meanwhile, I hope the insight collected in this article will help you to solve your Qt plugins problems.