QDataTables may be placed on any form to provide browsing of database tables and views. QDataTables can also be used to update or delete records in-place, i.e. inside the cells themselves. Inserting records via a QDataTable usually requires connecting to the primeInsert() signal, so that we can generate primary keys for example, or provide default values. If we wish to present records using a form view (perhaps combining data from several tables and views) we might use several QDataBrowsers and QDataViews.
This example, along with all the other examples in this chapter, has the project name 'book' and uses the database created by the book.sql script. As we work through the chapter we will build the 'book' application step by step. Create or copy the qt/tools/designer/examples/book/book1/main.cpp file shown earlier. The project file for this first example is qt/tools/designer/examples/book/book1/book.pro. Start a new project by clicking File|New Project. Complete the Project Settings dialog by entering a project name and a project file name. Now click Edit|Database Connections. Fill in the connection information appropriate to your database then press Connect. The connection name should now appear in the left hand list box. (If this doesn't happen you'll need to contact your database systems administrator for help.) Close the dialog.
We will now create a new form with a QDataTable that's connected to one of our database tables.
Click File|New. The New Form dialog presents us with a number of form templates to choose from. Choose the 'Dialog' form and click OK. Now click File|Save. You will be prompted for a filename, call it book.ui.
To place a QDataTable widget on the form either click Tools|Views|QDataTable or click the QDataTable toolbar button. Click on the form and the SQL Table Wizard will appear.
The Database Connection and Table wizard page is used to set up a connection if one doesn't exist and to choose the table or view for the QDataTable. (See the section called Setting Up Qt Designer's Connections "Setting Up Qt Designer's Connections".)
Click the connection you wish to use, listed in the left hand list box, e.g. "(default)". The available tables and views will appear in the right hand Table list box. Click the 'author' table and then click the Next button.
The Displayed Fields wizard page provides a means of selecting which fields should be displayed in the QDataTable and in what order. By default all fields except the primary key (if there is one) are in the Displayed Fields list box. The left- and right-pointing blue arrow buttons can be used to move fields between the Displayed Fields and the Available Fields list boxes. The blue up and down pointing arrow buttons are used to select the display order of the displayed fields.
The default settings are the ones we want so simply click Next.
The Table Properties wizard page provides convenient access to some of the database-related properties of the QDataTable.
Make sure the Confirm Deletes checkbox is checked, then click Next.
The SQL wizard page is used to set the QDataTable's Filter and Sort properties. The Filter is an SQL WHERE clause (without the word 'WHERE'). For example, to only list authors whose surnames begin with 'P', we would enter title LIKE 'P%'. We'll leave the filter empty. The Available Fields list box lists all the fields. The Sort By list box lists the fields that the QDataTable is to sort by and the direction of their sorting (ASCending or DESCending). The left and right blue arrows are used to move fields between the two list boxes. The up and down blue arrows move fields up and down within the Sort By list box. The ASC or DESC setting is changed with the 'sort order' toolbar button.
Move the surname and forename fields into the Sort By list box and click Next.
The Finish wizard page gives us the opportunity to go back and change any of our settings. We will be able to change them later through the QDataTable's properties so we can finish with the wizard.
Click Finish.
The table will appear on the form with each column labelled with a default column name. If you wish to change the settings then most of them are available in the property window. The display names, the fields they are based upon, and the order of appearance of the columns can be changed using the Edit Table dialog (explained later) by right clicking the QDataTable and left clicking Edit.
Click on the form and click the Lay Out Vertically toolbar button. Now click Preview|Preview Form; the form will run and the table will automatically display all the records.
To turn the form we've created into an executable application we must add the main.cpp file to the project file and make the project. We should also do some renaming to make things easier to understand.
Click on the form and change its name to 'BookForm' and its caption to 'Book'. Click on the QDataTable and change its name to 'AuthorDataTable'.
Click File|Save All.
Open the project file, e.g. book.pro, in a plain text editor and add the line: SOURCES += main.cpp at the end of the file.
Run qmake to generate the make file, e.g. qmake -o Makefile book.pro, then make and run the book program.
This example shows how easy it is to use QDataTable to show the contents of a database table or view. You can use the application we've just built to update and delete author records. In the examples that follow we will cover insertions, setting up master-detail relationships, drilldown and foreign key lookups.
Record insertion into a relational database usually requires the generation of a primary key value which uniquely identifies the record in the table. Also we often want to create default values for some fields to minimize the user's work. We will create a slot to capture the QDataTables primeInsert() signal and populate the QSqlRecord insertion buffer with a unique primary key.
Click Edit|Slots to invoke the Edit Slots dialog. Click New Slot, then enter the slot name primeInsertAuthor(QSqlRecord*) into the Slot Properties' Slot line edit box. Click OK.
Click the Connect Signals/Slots toolbar button, then click the AuthorDataTable, drag to the form and release the mouse. The Edit Connections dialog will now appear. Click the primeInsert() signal and then the primeInsertAuthor() slot to make the connection. Now click OK.
Click the Source tab of the Object Hierarchy window (click Window|Object Hierarchy to make the window visible if necessary). Click the primeInsertAuthor() slot and an editor window will appear.
We must change the BookForm::primeInsertAuthor() slot to specify the parameter name and perform the necessary action:
void BookForm::primeInsertAuthor( QSqlRecord * buffer ) { QSqlQuery query; query.exec( "UPDATE sequence SET sequence = sequence + 1 WHERE tablename='author';" ); query.exec( "SELECT sequence FROM sequence WHERE tablename='author';" ); if ( query.next() ) { buffer->setValue( "id", query.value( 0 ) ); } } |
If we rebuild the application it will now support INSERT as well as UPDATE and DELETE. We could easily have added additional code to insert default values, e.g. today's date into a date field, if necessary.
Browsing is supported by clicking records and by using the arrow keys. Once a record is active (highlighted) we can edit the it. Press the Insert key to INSERT a new record; press F2 to UPDATE the current record; press the Del key to DELETE the current record. All these operations take place immediately. Users can be given the opportunity to confirm their edits by setting the QDataTable's confirmEdits property to True. If the confirmEdits property is True then user confirmation will be required for all insertions, updates and deletes. For finer control you can set the confirmInsert, confirmUpdate and confirmDelete properties individually.
Databases often have pairs of tables that are related. For example, an invoice table might list the numbers, dates and customers for invoices, but not the actual invoice items, which an invoice item table might store. In the 'book' application we wish to have a QDataTable that we can use to browse through the authors table and a second QDataTable to show the books they've written.
Open the book project if it isn't already open Qt Designer. We will modify this project to show two QDataTables that relate the author table to the book table.
Click the author QDataTable and then click the Break Layout toolbutton.
Resize the QDataTable so that it only occupies the top half of the form.
Now click on the QDataTable toolbutton and click on the bottom half of the form. The SQL Table Wizard will appear. (This Wizard is explained in the section called Quickly Viewing a Database Table "Quickly Viewing a Database Table".)
Click the connection you're using and click the book table. Click the Next button.
Since we do not want them visible, make sure the authorid and id fields are moved to the Available Fields list box by using the arrow buttons. Move the title field to the top of the Displayed Fields, and move the price field above the notes field. Click the Next button.
On the Table Properties page click the Read Only checkbox then click the Next button.
On the SQL page we will leave the Filter (WHERE clause) empty. Move the title field to the Sort By list box and click Next. Now click Finish.
Change this QDataTable's name to "BookDataTable".
Shift+Click the top QDataTable so that both QDataTables are selected and then click the Lay Out Vertically (in Splitter) toolbar button.
Click on the form and click the Lay Out Vertically toolbar button.
Run the form by clicking Preview|Preview Form. All the authors are displayed in the top QDataTable and all the books are displayed in the bottom QDataTable. However we only want the books of the currently selected author showing in the bottom QDataTable. We will deal with this by filtering the records in the book table according to the author selected in the author table.
To filter the book table's records we need to capture the author QDataTable's currentChanged() signal and change the BookDataTable's filter accordingly.
Click Edit|Slots. In the Edit Slots dialog click New Slot and enter a slot name of newCurrentAuthor(QSqlRecord*). Click OK.
Click Connect Signals/Slots, then click the AuthorDataTable QDataTable and drag to the form; release the mouse on the form. The Edit Connections dialog will appear. Click the currentChanged() signal and the newCurrentAuthor slot. Click OK.
Click the Source tab of the Object Hierarchy window (click Window|Object Hierarchy to make the window visible if necessary). Click the newCurrentAuthor() slot and an editor window will appear.
We must change the BookForm::newCurrentAuthor() slot to specify the parameter name and perform the necessary action:
void BookForm::newCurrentAuthor( QSqlRecord *author ) { BookDataTable->setFilter( "authorid=" + author->value( "id" ).toString() ); BookDataTable->refresh(); } |
We can now browse and edit authors and see their books in the BookDataTable. In the next section we explore QDataBrowser, which will allow us to drill down to a dialog through which we can edit books. For now we will add some buttons to the main BookForm which we will use to invoke the book editing dialog.
Click the form, then click the Break Layout toolbar button. Resize the form to make room for some buttons at the bottom.
Add two buttons to the bottom of the form. Change their names and labels to the following:
EditPushButton -- &Edit Books
QuitPushButton -- &Quit
We will provide the Quit button with functionality now and work on the rest shortly. Click Connect Signals/Slots, then click the Quit button and drag to the form; release the mouse on the form. The Edit Connections dialog will appear. Click the clicked() signal and the accept() slot. Click OK.