SQL Widget Mapper Example▲

In the Combo Widget Mapper Example, we showed how to use a named mapping between a widget mapper and a QComboBox widget with a special purpose model to relate values in the model to a list of choices.
Again, we create a Window class with an almost identical user interface, providing a combo box to allow their addresses to be classified as "Home", "Work" or "Other". However, instead of using a separate model to hold these address types, we use one database table to hold the example data and another to hold the address types. In this way, we store all the information in the same place.
Window Class Definition▲
The class provides a constructor, a slot to keep the buttons up to date, and a private function to set up the model:
class
Window : public
QWidget
{
Q_OBJECT
public
:
Window(QWidget *
parent =
nullptr
);
private
slots:
void
updateButtons(int
row);
private
:
void
setupModel();
QLabel *
nameLabel;
QLabel *
addressLabel;
QLabel *
typeLabel;
QLineEdit *
nameEdit;
QTextEdit *
addressEdit;
QComboBox *
typeComboBox;
QPushButton *
nextButton;
QPushButton *
previousButton;
QSqlRelationalTableModel *
model;
QItemSelectionModel *
selectionModel;
QDataWidgetMapper *
mapper;
int
typeIndex;
}
;
In addition to the QDataWidgetMapper object and the controls used to make up the user interface, we use a QStandardItemModel to hold our data and a QStringListModel to hold information about the types of address that can be applied to each person's data.
Window Class Implementation▲
The first act performed by the Window class constructor is to set up the model used to hold the example data. Since this is a key part of the example, we will look at this first.
The model is initialized in the window's setupModel() function. Here, we create a SQLite database containing a "person" table with primary key, name, address and type fields.
void
Window::
setupModel()
{
QSqlDatabase db =
QSqlDatabase::
addDatabase("QSQLITE"
);
db.setDatabaseName(":memory:"
);
if
(!
db.open()) {
QMessageBox::
critical(0
, tr("Cannot open database"
),
tr("Unable to establish a database connection.
\n
"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information how "
"to build it."
), QMessageBox::
Cancel);
return
;
}
QSqlQuery query;
query.exec("create table person (id int primary key, "
"name varchar(20), address varchar(200), typeid int)"
);
query.exec("insert into person values(1, 'Alice', "
"'<qt>123 Main Street<br/>Market Town</qt>', 101)"
);
query.exec("insert into person values(2, 'Bob', "
"'<qt>PO Box 32<br/>Mail Handling Service"
"<br/>Service City</qt>', 102)"
);
query.exec("insert into person values(3, 'Carol', "
"'<qt>The Lighthouse<br/>Remote Island</qt>', 103)"
);
query.exec("insert into person values(4, 'Donald', "
"'<qt>47338 Park Avenue<br/>Big City</qt>', 101)"
);
query.exec("insert into person values(5, 'Emma', "
"'<qt>Research Station<br/>Base Camp<br/>"
"Big Mountain</qt>', 103)"
);
On each row of the table, we insert default values for these fields, including values for the address types that correspond to the address types are stored in a separate table.

We create an "addresstype" table containing the identifiers used in the "person" table and the corresponding strings:
query.exec("create table addresstype (id int, description varchar(20))"
);
query.exec("insert into addresstype values(101, 'Home')"
);
query.exec("insert into addresstype values(102, 'Work')"
);
query.exec("insert into addresstype values(103, 'Other')"
);
model =