1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** GNU Free Documentation License
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms
** and conditions contained in a signed written agreement between you
** and Nokia.
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\example sql/cachedtable
\title Cached Table Example
\brief The Cached Table example shows how a table view can be used to access a database,
caching any changes to the data until the user explicitly submits them using a
push button.
\image cachedtable-example.png
The example consists of a single class, \c TableEditor, which is a
custom dialog widget that allows the user to modify data stored in
a database. We will first review the class definiton and how to
use the class, then we will take a look at the implementation.
\section1 TableEditor Class Definition
The \c TableEditor class inherits QDialog making the table editor
widget a top-level dialog window.
\snippet examples/sql/cachedtable/tableeditor.h 0
The \c TableEditor constructor takes two arguments: The first is a
pointer to the parent widget and is passed on to the base class
constructor. The other is a reference to the database table the \c
TableEditor object will operate on.
Note the QSqlTableModel variable declaration: As we will see in
this example, the QSqlTableModel class can be used to provide data
to view classes such as QTableView. The QSqlTableModel class
provides an editable data model making it possible to read and
write database records from a single table. It is build on top of
the lower-level QSqlQuery class which provides means of executing
and manipulating SQL statements.
We are also going to show how a table view can be used to cache
any changes to the data until the user explicitly requests to
submit them. For that reason we need to declare a \c submit() slot
in additon to the model and the editor's buttons.
\table 100%
\header \o Connecting to a Database
\row
\o
Before we can use the \c TableEditor class, we must create a
connection to the database containing the table we want to edit:
\snippet examples/sql/cachedtable/main.cpp 0
The \c createConnection() function is a helper function provided
for convenience. It is defined in the \c connection.h file which
is located in the \c sql example directory (all the examples in
the \c sql directory use this function to connect to a database).
\snippet examples/sql/connection.h 0
The \c createConnection function opens a connection to an
in-memory SQLITE database and creates a test table. If you want
to use another database, simply modify this function's code.
\endtable
\section1 TableEditor Class Implementation
The class implementation consists of only two functions, the
constructor and the \c submit() slot. In the constructor we create
and customize the data model and the various window elements:
\snippet examples/sql/cachedtable/tableeditor.cpp 0
First we create the data model and set the SQL database table we
want the model to operate on. Note that the
QSqlTableModel::setTable() function does not select data from the
table; it only fetches its field information. For that reason we
call the QSqlTableModel::select() function later on, populating
the model with data from the table. The selection can be
customized by specifying filters and sort conditions (see the
QSqlTableModel class documentation for more details).
We also set the model's edit strategy. The edit strategy dictates
when the changes done by the user in the view, are actually
applied to the database. Since we want to cache the changes in the
table view (i.e. in the model) until the user explicitly submits
them, we choose the QSqlTableModel::OnManualSubmit strategy. The
alternatives are QSqlTableModel::OnFieldChange and
QSqlTableModel::OnRowChange.
Finally, we set up the labels displayed in the view header using
the \l {QSqlQueryModel::setHeaderData()}{setHeaderData()} function
that the model inherits from the QSqlQueryModel class.
\snippet examples/sql/cachedtable/tableeditor.cpp 1
Then we create a table view. The QTableView class provides a
default model/view implementation of a table view, i.e. it
implements a table view that displays items from a model. It also
allows the user to edit the items, storing the changes in the
model. To create a read only view, set the proper flag using the
\l {QAbstractItemView::editTriggers}{editTriggers} property the
view inherits from the QAbstractItemView class.
To make the view present our data, we pass our model to the view
using the \l {QAbstractItemView::setModel()}{setModel()} function.
\snippet examples/sql/cachedtable/tableeditor.cpp 2
The \c {TableEditor}'s buttons are regular QPushButton objects. We
add them to a button box to ensure that the buttons are presented
in a layout that is appropriate to the current widget style. The
rationale for this is that dialogs and message boxes typically
present buttons in a layout that conforms to the interface
guidelines for that platform. Invariably, different platforms have
different layouts for their dialogs. QDialogButtonBox allows a
developer to add buttons to it and will automatically use the
appropriate layout for the user's desktop environment.
Most buttons for a dialog follow certain roles. When adding a
button to a button box using the \l
{QDialogButtonBox}{addButton()} function, the button's role must
be specified using the QDialogButtonBox::ButtonRole
enum. Alternatively, QDialogButtonBox provides several standard
buttons (e.g. \gui OK, \gui Cancel, \gui Save) that you can
use. They exist as flags so you can OR them together in the
constructor.
\snippet examples/sql/cachedtable/tableeditor.cpp 3
We connect the \gui Quit button to the table editor's \l
{QWidget::close()}{close()} slot, and the \gui Submit button to
our private \c submit() slot. The latter slot will take care of
the data transactions. Finally, we connect the \gui Revert button
to our model's \l {QSqlTableModel::revertAll()}{revertAll()} slot,
reverting all pending changes (i.e., restoring the original data).
\snippet examples/sql/cachedtable/tableeditor.cpp 4
In the end we add the button box and the table view to a layout,
install the layout on the table editor widget, and set the
editor's window title.
\snippet examples/sql/cachedtable/tableeditor.cpp 5
The \c submit() slot is called whenever the users hit the \gui
Submit button to save their changes.
First, we begin a transaction on the database using the
QSqlDatabase::transaction() function. A database transaction is a
unit of interaction with a database management system or similar
system that is treated in a coherent and reliable way independent
of other transactions. A pointer to the used database can be
obtained using the QSqlTableModel::database() function.
Then, we try to submit all the pending changes, i.e. the model's
modified items. If no error occurs, we commit the transaction to
the database using the QSqlDatabase::commit() function (note that
on some databases, this function will not work if there is an
active QSqlQuery on the database). Otherwise we perform a rollback
of the transaction using the QSqlDatabase::rollback() function and
post a warning to the user.
\table 100%
\row
\o
\bold {See also:}
A complete list of Qt's SQL \l {Database Classes}, and the \l
{Model/View Programming} documentation.
\endtable
*/
|