TL; DR
我想注册一个Qt Designer扩展程序,但不想要任何小部件插件,所以以下任何一个都可以解决我的问题:
QDesignerCustomWidgetInterface
我正在为Qt Designer开发一组插件。这些插件向设计人员公开自定义小部件。所有小部件(几十个)都从公共类(CCommonWidget
)继承,例如:
CCommonWidget
|-> CLabel
|-> CPushButton
...
CCommonWidget
定义所有小部件的一些常用属性。我想通过扩展程序将它们公开给Qt Designer(例如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
的其他小部件也会显示菜单! (很明显,一旦我发现它,但在我没想到之前)。
现在它变得更容易,因为我没有更改所有插件(数十个),只是为了创建一个新的,一个虚拟公共插件,它注册了扩展工厂。
我首先创建的虚拟插件:
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 Designer的小部件框中会显示一个空白小部件。我不想要一个空小部件,我想没有小部件!
另一个选择是不使用这些插件,但我很难找到一种方法来注册扩展而不用一个QDesignerCustomWidgetInterface
,但我能找到的只是在QDesignerCustomWidgetInterface::initialize(QDesignerFormEditorInterface *formEditor)
内使用formEditor->extensionManager()
获取扩展程序管理器。
答案 0 :(得分:2)
快速回答
要从窗口小部件框中隐藏窗口小部件,只需返回一个空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 Designer的插件管理器的源代码中看到的那样,没有办法加载不从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);
}
}