tl; dr
我想注册QT设计师扩展程序,但不需要任何小部件插件,因此以下任何一个可以解决我的问题:
- 如何在QT Designer中创建一个不会在小部件框中展示任何小部件但可以注册扩展名的插件?
- 如何注册扩展名,而不子类别的
QDesignerCustomWidgetInterface
?
我正在为QT Designer的一组插件。这些插件将自定义小部件曝光到设计师。所有小部件(大约十几个)都从公共类(CCommonWidget
)继承,例如:
CCommonWidget
|-> CLabel
|-> CPushButton
...
CCommonWidget
定义了所有小部件的一些常见属性。我想通过扩展名将它们暴露于QT设计师(例如QDesignerTaskMenuExtension
)。
我从CLabel
插件中的测试开始。这里有两种相关方法:
// 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;
}
它完美无缺,我正将这个想法扩展到其余插件。而不是复制/粘贴代码,而是从CCommonPlugin
开始,然后使每个人都从中继承。为了使其尽可能重复使用,我将createExtension
方法更改为:
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;
}
在这里,我意识到,即使仅在插件上(CLabelPlugin
)注册了扩展工厂,也从CCommonWidget
继承的任何其他小部件都会显示菜单!(一旦我发现它很明显,但是在我没有考虑之前)。
现在更容易了,因为我没有更改所有插件(数十个),而只是为了创建一个新的插件,即a em phummy common Plugin ,它注册了扩展工厂。
我首次创建的虚拟插件:
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;
};
,但是在QT设计师的小部件框中显示一个空白小部件。我不想要一个空的小部件,我想要!
另一种选择是不使用这类插件,但是我正在努力寻找一种在没有QDesignerCustomWidgetInterface
的情况下注册扩展名的方法,但是我所能找到的就是在内部获取扩展管理器QDesignerCustomWidgetInterface::initialize(QDesignerFormEditorInterface *formEditor)
(使用formEditor->extensionManager()
)。
快速答案
要从小部件框隐藏小部件,只需返回一个空的XML(这是一个无证功能):
class CPluginCommon : public QObject, public QDesignerCustomWidgetInterface {
// ...
public:
QString domXml() const { return QString(); }
};
查看QT Designer的插件管理器的代码,我在QDesignerPluginManagerPrivate::addCustomWidget
方法中找到了以下方法(c
是QDesignerCustomWidgetInterface
的指针)
const QString domXml = c->domXml();
if (!domXml.isEmpty()) { // Legacy: Empty XML means: Do not show up in widget box.
鉴于,我看到domXml
的默认实现确实返回了通用窗口小部件的微小XML片段:
virtual QString domXml() const
{
return QString::fromUtf8("<widget class="%1" name="%2"/>")
.arg(name()).arg(name().toLower());
}
对于完整性,就我在QT设计师的插件管理器的源代码中所看到的,无法加载不从QDesignerCustomWidgetInterface
继承的插件:
// Load plugins into widget database and factory.
void QDesignerIntegration::initializePlugins(QDesignerFormEditorInterface *formEditor)
{
// load the plugins
WidgetDataBase *widgetDataBase = qobject_cast<WidgetDataBase*>(formEditor->widgetDataBase());
if (widgetDataBase) {
widgetDataBase->loadPlugins();
}
if (WidgetFactory *widgetFactory = qobject_cast<WidgetFactory*>(formEditor->widgetFactory())) {
widgetFactory->loadPlugins();
}
if (widgetDataBase) {
widgetDataBase->grabDefaultPropertyValues();
}
}
其中
void WidgetDataBase::loadPlugins()
{
// ...
// 2) create a list plugins
ItemList pluginList;
const QDesignerPluginManager *pm = m_core->pluginManager();
foreach(QDesignerCustomWidgetInterface* c, pm->registeredCustomWidgets())
pluginList += createCustomWidgetItem(c, pm->customWidgetData(c));
// ...
}
void WidgetFactory::loadPlugins()
{
m_customFactory.clear();
QDesignerPluginManager *pluginManager = m_core->pluginManager();
QList<QDesignerCustomWidgetInterface*> lst = pluginManager->registeredCustomWidgets();
foreach (QDesignerCustomWidgetInterface *c, lst) {
m_customFactory.insert(c->name(), c);
}
}