9.7.  Designer Integration with Code

[ fromfile: designer-integration.xml id: designer-integration ]

Figure 9.17.  Product and Its Form

Product and Its Form

Using Designer to Design the Form

Figure 9.18.  Designer to Code

Designer to Code

Example 9.10. src/designer/productform/ui_ProductForm.h

[ . . . . ]
class Ui_ProductForm
{
public:
    QVBoxLayout *verticalLayout;
    QFormLayout *formLayout;
    QLabel *label;
    QDoubleSpinBox *priceSpinbox;
    QLabel *label_2;
    QLabel *label_3;
    QLineEdit *nameLineEdit;
    QLabel *label_4;
    QTextEdit *descriptionEdit;
    QDateEdit *dateEdit;
    QSpacerItem *verticalSpacer;
    QDialogButtonBox *buttonBox;

    void setupUi(QDialog *ProductForm)
[ . . . . ]
};
namespace Ui {
    class ProductForm: public Ui_ProductForm {};
} // namespace Ui
[ . . . . ]

[Important] What Is a Ui Class?

A Ui class is a class that contains only auto-generated code produced by the uic tool. It can be used as a base class, or as a data member of the custom form. Its members are initialized from the setupUi() method.

[Note] QDialog accept() and reject()

Designer initially connects a couple of signals from the QDialogButtonBox to the QDialog accept() and reject() slots. You can see this from the Signals and Slots Editor dockable. What this means is that as long as the underlying Product object is not changed until OK is pressed, the reject() base class behavior closes the dialog, as you probably want. You still might want to override accept(), but you do not need to connect any button's signal to it. The base class version also closes the dialog.

Approaches to Integration

  1. Aggregation as a pointer member

  2. Multiple (private) Inheritance

  3. Aggregation as an embedded object

Example 9.11. src/designer/delegation/productform.h

[ . . . . ]
#include <QDialog>
class Product;
class Ui_ProductForm;
class QWidget;
class QAbstractButton;
class ProductForm : public QDialog {
        Q_OBJECT
public:
    explicit ProductForm(Product* product = 0, QWidget* parent=0); 1
    void setModel(Product* model);

public slots:
    void accept();
    void commit();
    void update();

private:
    Ui_ProductForm *m_ui;
    Product* m_model;
};
[ . . . . ]

1

Mark explicit to avoid implicit conversions between pointers!


Example 9.12. src/designer/delegation/productform.cpp

#include <QtGui>
#include "productform.h"
#include "ui_ProductForm.h"
#include "product.h"

ProductForm::ProductForm(Product* product, QWidget* parent)
: QDialog(parent), m_ui(new Ui::ProductForm),  m_model(product) {
    m_ui->setupUi(this); 1
    update();
}

void ProductForm::setModel(Product* p) {
    m_model =p;
}

void ProductForm::accept() {
    commit();
    QDialog::accept();  2
}

void ProductForm::commit() {
    if (m_model == 0) return;
    qDebug() << "commit()";
    m_model->setName(m_ui->nameLineEdit->text());
    QTextDocument* doc = m_ui->descriptionEdit->document();
    m_model->setDescription(doc->toPlainText());
    m_model->setDateAdded(m_ui->dateEdit->date());
    m_model->setPrice(m_ui->priceSpinbox->value());
}

void ProductForm::update() {
    if (m_model ==0) return;
    qDebug() << "update()";
    m_ui->nameLineEdit->setText(m_model->name());
    m_ui->priceSpinbox->setValue(m_model->price());
    m_ui->dateEdit->setDate(m_model->dateAdded());
    m_ui->descriptionEdit->setText(m_model->description());
}

1

Populate the UI object with valid instances with properties set from values in the .ui file.

2

Closes the dialog.