0

TL;博士

我想注册一个 Qt Designer 扩展但不想要任何小部件插件,所以以下任何一个都可以解决我的问题:

  • 如何在 Qt Designer 中创建一个不会在小部件框中公开任何小部件但可以注册扩展的插件?
  • 如何在没有子类化的情况下注册扩展QDesignerCustomWidgetInterface

我正在为 Qt Designer 开发一组插件。这些插件向设计人员公开自定义小部件。所有小部件(几十个)都继承自一个公共类 ( CCommonWidget),例如:

CCommonWidget
|-> CLabel
|-> CPushButton
...

CCommonWidget为所有小部件定义一些通用属性。我想通过扩展(例如QDesignerTaskMenuExtension)将它们公开给 Qt Designer。

我从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;
}

它完美无缺,我正准备将这个想法扩展到其他插件。我没有复制/粘贴代码,而是从 a 开始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())中获取扩展管理器。

4

1 回答 1

2

快速回答

要从小部件框中隐藏小部件,只需返回一个空 XML(这是一个未记录的功能):

class CPluginCommon : public QObject, public QDesignerCustomWidgetInterface {
// ...
public:
    QString domXml() const { return QString(); }
};

查看Qt Designer的plugins manager的代码,发现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);
    }
}
于 2017-10-02T11:34:39.053 回答