TL;DR
I want to register a Qt Designer extension but don't want any widget plugin, so any of the following can solve my problem:
- How do I create a plugin in Qt Designer that doesn't expose any widget in the widget box but that can register extensions?
- How do I register the extension without subclassing of
QDesignerCustomWidgetInterface
?
I'm working on a set of plugins for Qt Designer. These plugins expose custom widgets to the designer. All widgets (some dozens) inherit from a common class (CCommonWidget
), such as:
CCommonWidget
|-> CLabel
|-> CPushButton
...
CCommonWidget
define some common properties for all widgets. I'd like to expose them to Qt Designer through extensions (for example, the QDesignerTaskMenuExtension
).
I started with a test in the CLabel
plugin. Here the two relevant methods:
// Register the extensions in Qt Designer
void CLabelPlugin::initialize(QDesignerFormEditorInterface *formEditor)
{
if (m_initialized) return;
auto extensionManager = formEditor->extensionManager();
Q_ASSERT(extensionManager);
extensionManager->registerExtensions(new CLabelPluginFactory(extensionManager), Q_TYPEID(QDesignerTaskMenuExtension));
m_initialized = true;
}
// The factory creates the menu extension if the widget is a CLabel
QObject* CLabelPluginFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
{
if (iid != Q_TYPEID(QDesignerTaskMenuExtension)) return nullptr;
if (auto label = dynamic_cast<CLabel*>(object))
return new CLabelPluginMenu(label, parent);
return nullptr;
}
It worked flawlessly and I was about to extend the idea to the rest of the plugins. Instead of copy/pasting the code I started with a CCommonPlugin
and make every one to inherit from it. In order to make it as re-usable as possible I changed the createExtension
method to:
QObject* CCommonPluginFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
{
if (iid != Q_TYPEID(QDesignerTaskMenuExtension)) return nullptr;
if (auto label = dynamic_cast<CCommonWidget*>(object))
return new CCommnPluginMenu(label, parent);
return nullptr;
}
Here I realized that even if only on plugin (CLabelPlugin
) was registering the extension factory, any other widget which inherits from CCommonWidget
will show the menu! (It was pretty obvious once I discovered it but before I just didn't think on it).
Now it was easier since I hadn't to change all the plugins (dozens) but just to create a new one, a dummy common plugin, that registers the extension factory.
The dummy plugin I've first created:
class CPluginCommon : public QObject, public QDesignerCustomWidgetInterface {
Q_OBJECT
Q_INTERFACES( QDesignerCustomWidgetInterface )
public:
explicit CPluginCommon( QObject* parent=0 );
public: // QDesignerCustomWidgetInterface
QWidget* createWidget( QWidget* parent ) { return nullptr; }
QString group() const { return QString(); }
QIcon icon() const { return QIcon(); }
QString includeFile() const { return QString(); }
bool isContainer() const { return false; }
QString name() const { return QString(); }
QString toolTip() const { return QString(); }
QString whatsThis() const { return QString(); }
virtual bool isInitialized() const override {
return m_initialized;
}
virtual void initialize(QDesignerFormEditorInterface *formEditor) override;
private:
bool m_initialized;
};
But a blank widget is displayed in the widget box of Qt Designer. I don't want an empty widget, I want no widget!
Another option is not to use these kind of plugins but I'm struggling to find a way to register the extension without a QDesignerCustomWidgetInterface
, but all that I can find is to get the extensions manager within QDesignerCustomWidgetInterface::initialize(QDesignerFormEditorInterface *formEditor)
(using formEditor->extensionManager()
).
Quick answer
To hide the widget from the widget box just return an empty XML (this is an undocumented feature):
Reviewing the code of the plugins manager of Qt Designer, I found in the
QDesignerPluginManagerPrivate::addCustomWidget
method the following (c
is a pointer toQDesignerCustomWidgetInterface
)Given that, I saw that the default implementation of
domXml
does return a tiny XML fragment for a generic widget:For completeness, as far as I have seen in the source code of the plugins manager of the Qt Designer, there is no way to load a plugin that doesn't inherits from
QDesignerCustomWidgetInterface
:where