02 March, 2013

Qt Designer: Использование собственных виджетов в качестве Promoting Widgets

Продолжаем развлекаться с Qt Designer, на это раз мы поговорим про использование собственных виджетов в Promoting Widgets. Promoting Widgets позволяют использовать базовый класс для представления дочернего на форме, то есть если у вас есть какой-либо наследник скажем QLineEdit, но вы не хотите писать для него плагин (например потому что наследник не имеет никаких новых свойств, а просто имеет другой внешний вид), то вы можете просто в форме показанной слева, выбрать базовым классом QLineEdit а Promoted классом указать своего наследника.



Проблема, которую мы будем решать заключается в том, что нет [задокументированного] пути указать в качестве базового класса, свой виджет имеющий плагин для дизайнера.


Чтобы не повторятся, давайте возьмем в качестве виджета который мы будем использовать базовым, наш виджет из предыдущего топика, который выглядит так, Давайте сделаем его наследника, который будет таким (справа)



GreenPanelWithButtons::GreenPanelWithButtons(QWidget *parent) :
    PanelWithButtons(parent)
{
    QPalette p = palette();
    p.setColor(QPalette::Window, Qt::green);
    setPalette(p);
}
Естественно мы не хотим писать еще один плагин для такого простого виджета, для того чтобы наш уже имеющийся родительский вижет смог представлять в дизайнере наш новый виджет нам нужно модифицировать код плагина:
void PanelWithButtonsPlugin::initialize(QDesignerFormEditorInterface *core)
{
    ...
    WidgetDataBaseItem *widgetItem = new WidgetDataBaseItem(name(), group());
    widgetItem->setIncludeFile(includeFile());
    widgetItem->setExtends("QWidget");
    widgetItem->setCustom(true);

    core->widgetDataBase()->append(widgetItem);

    ...
}
Проблема этого кода в том, что мы на самом деле не имеем доступа к классу WidgetDatabaseBaseItem. Но интерфейс от которого он наследуется QDesignerWidgetDataBaseItemInterface, публичен и поэтому мы можем написать реализацию сами (на самом деле я ее не писал, а умыкнул из исходников Qt Designer) и привожу ниже полностью, хотя она тривиальна:

class WidgetDataBaseItem: public QDesignerWidgetDataBaseItemInterface
{
public:
    explicit WidgetDataBaseItem(const QString &name = QString(),
                                const QString &group = QString());
    QString name() const;
    void setName(const QString &name);

    QString group() const;
    void setGroup(const QString &group);

    QString toolTip() const;
    void setToolTip(const QString &toolTip);

    QString whatsThis() const;
    void setWhatsThis(const QString &whatsThis);

    QString includeFile() const;
    void setIncludeFile(const QString &includeFile);

    QIcon icon() const;
    void setIcon(const QIcon &icon);

    bool isCompat() const;
    void setCompat(bool compat);

    bool isContainer() const;
    void setContainer(bool b);

    bool isCustom() const;
    void setCustom(bool b);

    QString pluginPath() const;
    void setPluginPath(const QString &path);

    bool isPromoted() const;
    void setPromoted(bool b);

    QString extends() const;
    void setExtends(const QString &s);

    void setDefaultPropertyValues(const QList<QVariant> &list);
    QList<QVariant> defaultPropertyValues() const;

    static WidgetDataBaseItem *clone(const QDesignerWidgetDataBaseItemInterface *item);
    QStringList fakeSlots() const;
    void setFakeSlots(const QStringList &);

    QStringList fakeSignals() const;
    void setFakeSignals(const QStringList &);

    QString addPageMethod() const;
    void setAddPageMethod(const QString &m);

private:
    QString m_name;
    QString m_group;
    QString m_toolTip;
    QString m_whatsThis;
    QString m_includeFile;
    QString m_pluginPath;
    QString m_extends;
    QString m_addPageMethod;
    QIcon m_icon;
    uint m_compat: 1;
    uint m_container: 1;
    uint m_form: 1;
    uint m_custom: 1;
    uint m_promoted: 1;
    QList<QVariant> m_defaultPropertyValues;
    QStringList m_fakeSlots;
    QStringList m_fakeSignals;
};
///////////////////////////////////////////////////////////////////////////////
WidgetDataBaseItem::WidgetDataBaseItem(const QString &name, const QString &group)
    : m_name(name),
      m_group(group),
      m_compat(0),
      m_container(0),
      m_form(0),
      m_custom(0),
      m_promoted(0)
{
}

QString WidgetDataBaseItem::name() const
{
    return m_name;
}

void WidgetDataBaseItem::setName(const QString &name)
{
    m_name = name;
}

QString WidgetDataBaseItem::group() const
{
    return m_group;
}

void WidgetDataBaseItem::setGroup(const QString &group)
{
    m_group = group;
}

QString WidgetDataBaseItem::toolTip() const
{
    return m_toolTip;
}

void WidgetDataBaseItem::setToolTip(const QString &toolTip)
{
    m_toolTip = toolTip;
}

QString WidgetDataBaseItem::whatsThis() const
{
    return m_whatsThis;
}

void WidgetDataBaseItem::setWhatsThis(const QString &whatsThis)
{
    m_whatsThis = whatsThis;
}

QString WidgetDataBaseItem::includeFile() const
{
    return m_includeFile;
}

void WidgetDataBaseItem::setIncludeFile(const QString &includeFile)
{
    m_includeFile = includeFile;
}

QIcon WidgetDataBaseItem::icon() const
{
    return m_icon;
}

void WidgetDataBaseItem::setIcon(const QIcon &icon)
{
    m_icon = icon;
}

bool WidgetDataBaseItem::isCompat() const
{
    return m_compat;
}

void WidgetDataBaseItem::setCompat(bool b)
{
    m_compat = b;
}

bool WidgetDataBaseItem::isContainer() const
{
    return m_container;
}

void WidgetDataBaseItem::setContainer(bool b)
{
    m_container = b;
}

bool WidgetDataBaseItem::isCustom() const
{
    return m_custom;
}

void WidgetDataBaseItem::setCustom(bool b)
{
    m_custom = b;
}

QString WidgetDataBaseItem::pluginPath() const
{
    return m_pluginPath;
}

void WidgetDataBaseItem::setPluginPath(const QString &path)
{
    m_pluginPath = path;
}

bool WidgetDataBaseItem::isPromoted() const
{
    return m_promoted;
}

void WidgetDataBaseItem::setPromoted(bool b)
{
    m_promoted = b;
}

QString WidgetDataBaseItem::extends() const
{
    return m_extends;
}

void WidgetDataBaseItem::setExtends(const QString &s)
{
    m_extends = s;
}

void WidgetDataBaseItem::setDefaultPropertyValues(const QList<QVariant> &list)
{
    m_defaultPropertyValues = list;
}

QList<QVariant> WidgetDataBaseItem::defaultPropertyValues() const
{
    return m_defaultPropertyValues;
}

QStringList WidgetDataBaseItem::fakeSlots() const
{
    return m_fakeSlots;
}

void WidgetDataBaseItem::setFakeSlots(const QStringList &fs)
{
    m_fakeSlots = fs;
}

QStringList WidgetDataBaseItem::fakeSignals() const
{
     return m_fakeSignals;
}

void WidgetDataBaseItem::setFakeSignals(const QStringList &fs)
{
    m_fakeSignals = fs;
}

QString WidgetDataBaseItem::addPageMethod() const
{
    return m_addPageMethod;
}

void WidgetDataBaseItem::setAddPageMethod(const QString &m)
{
    m_addPageMethod = m;
}

WidgetDataBaseItem *WidgetDataBaseItem::clone(const QDesignerWidgetDataBaseItemInterface *item)
{
    WidgetDataBaseItem *rc = new WidgetDataBaseItem(item->name(), item->group());
    rc->setToolTip(item->toolTip());
    rc->setWhatsThis(item->whatsThis());
    rc->setIncludeFile(item->includeFile());
    rc->setIcon(item->icon());
    rc->setCompat(item->isCompat());
    rc->setContainer(item->isContainer());
    rc->setCustom(item->isCustom() );
    rc->setPluginPath(item->pluginPath());
    rc->setPromoted(item->isPromoted());
    rc->setExtends(item->extends());
    rc->setDefaultPropertyValues(item->defaultPropertyValues());
    // container page method, fake slots and signals ignored here.y
    return rc;
}
Естественно стоит не забыть включить необходимые заголовки
#include <QDesignerWidgetDataBaseInterface>
#include <QDesignerWidgetDataBaseItemInterface>
Теперь скомпилируем наш плагин, запустим дизайнер и посмотрим, что получилось:
Как видим наш базовый класс появился в списке базовых классов. а это значит что теперь мы можем его использовать для представления его наследников:


На этом все.

No comments:

Post a Comment