Регистрация расширения в Qt Designer без связанного плагина виджета

TL; DR

Я хочу зарегистрировать расширение Qt Designer, но не хочу плагин для виджетов, поэтому любое из следующего может решить мою проблему:

  • Как мне создать плагин в 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

Решение

Быстрый ответ

Чтобы скрыть виджет из поля виджета, просто верните пустой 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);
}
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]