c++ gui programming with qt 3 · creating the „videoteka” project file/new 20 creating the main...
TRANSCRIPT
1
1
C++ GUI Programming with Qt 3
Rozália Szabó NacsaEötvös Loránd University, Budapest
Faculty of [email protected]
2
The Task
3
The „Tricks”
ComboBox
Modificationwith controls
Calculated field
Calculatedfield with
„info”
Read Only
4
The Tables
5
Database Managament using API calls
Database1
Application
API1calls
API1
Database2
Alkalmazás
API2calls
API2
Database specificfunction calls. 6
Database Management using SQL commands
Database1API1
Database2
Application
SQLcommands
API2
SQL
SQL
Database specificfunction calls Standard Query
Language
2
7
Database Management using ODBC
Database1API1 Application
SQLcommands
ODBCfunction calls
SQL
ODBCfunctions
Database2API1
SQL
ODBCfunctions
ODBCdriver1
ODBCdriver1
ODBCdriver2
Database specificfunction calls
Standard QueryLanguage
Standard functions
8
Database Management using ODBC
Database1API1 Application
SQLcommands
ODBCfunction calls
SQL
ODBCfunctions
Database2API1
SQL
ODBCfunctions
ODBCdriver2
ODBCdriver1
ODBCdriver2
9
videoteka
Registration
Videoteka„MySQL” driver
DSN (Data Source Name)Driver
10
Vezérlőpult/Felügyeleti eszközök
Registration
11
ODBC datasource
12
3
13
Identification of„physical”database.
14
15
Available Drivers in Qt
•QDB2 - IBM DB2 Driver (v7.1 and higher) •QIBASE - Borland Interbase Driver •QMYSQL3 - MySQL Driver•QOCI8 - Oracle Call Interface Driver, version 8 and 9 •QODBC3 - Open Database Connectivity Driver•QPSQL7 - PostgreSQL v6.x and v7.x Driver •QSQLITE - SQLite Driver •QTDS7 - Sybase Adaptive Server and Microsoft SQL Server Driver
16
Qt / SQL module
DBMS classes canbe found in SQL
Module .
17
Database Related Classes
QSqlQuery QSqlCursor
QDataTableQTable
„Represent” data
„Display” data18
4
19
Creating the „Videoteka” project
File/New
20
Creating the Main Window
File/New
21
Wizard: Choose menus and toolbars
We don’t needthese „services”.
22
Wizard: Setup Toolbar
23
Wizard: Finish
24
Previewing the Project
Ctrl+T
1. qmake –o Makefile videoteka.pro2. nmake3. quit
OR: Build
5
25
The Starting Project
26
Adding main program to the project
File/New
27
The generated main program
28
Compile & Run
1. qmake –o Makefile videoteka.pro2. nmake3. quit
29
Connecting to the Database
connection.cpp
connection.h
main.cpp
30
Adding Source File to the Project
File/New
File/Save as …
6
31
Adding Header File to the Project
File/New
File/Save as …
32
Database Connection: connection.h, connection.cpp
#define DB_SOURCE_DRIVER "QODBC3"#define DB_SOURCE_DBNAME „videoteka"#define DB_SOURCE_USER "nacsa"#define DB_SOURCE_PASSWD "1234"#define DB_SOURCE_HOST "localhost"bool createConnections();
#include <qsqldatabase.h>#include "connection.h"bool createConnections() {
QSqlDatabase *source = QSqlDatabase::addDatabase( DB_SOURCE_DRIVER);source->setDatabaseName( DB_SOURCE_DBNAME );source->setUserName( DB_SOURCE_USER );source->setPassword( DB_SOURCE_PASSWD );source->setHostName( DB_SOURCE_HOST );if ( ! source->open() ) {qWarning( „Failed to open database: " +source->lastError().driverText() );qWarning( source->lastError().databaseText() );return FALSE;
}return TRUE;
}
1.Activate driver2.Set connection’s properties3.Open connection
connection.h
connection.cpp
Only the driver has tobe modified changingthe databaseenvironment.
33
Database Connection: main.cpp
. . .#include <qsqldatabase.h>#include "connection.h. . .int main( int argc, char *argv[] ) {
. . .if ( createConnections() ) {
// We have opened the database connections.// Ready to perform SQL commands
}return 0;}
main.cpp
34
35
Creating New Action – Tables/Customers
36
tableCustomersAction: Properties
7
37
tableFilmsAction: Properties
38
tableRentsAction: Properties
39
Adding Actions to the Menu
Drag & Drop
40
Creating CustomersForm
File/New
41
Drag & Drop & . . .
42
Data Table Wizard: Choose Database & Table
1
23
8
43
Data Table Wizard: Choose Database & Table
customersfilmsrentssequence
44
Data Table Wizard: Displayed Fields
nameaddresscode
45
Data Table Wizard: Table Properties
46
Data Table Wizard: SQL
You can add a valid WHERE clause here.
47 48
Double Click ontable to edit it.
9
49
Bringing up the CustomersForm
CustomersForm
50
Creating a New Slot
Function: slotTableCustomers()Return type: voidSpecifier: virtualAccess: publicType: slot
51
Connections
Sender: tableCustomersActionSignal: activated()Receiver: MainFormSlot:slotTableCustomers()
52
Further Slots
Function: slotTableFilms()Return type: voidSpecifier: virtualAccess: publicType: slot
Function: slotTableRents()Return type: voidSpecifier: virtualAccess: publicType: slot
53
Further Connections
Sender: tableFilmsActionSignal: activated()Receiver: MainFormSlot:slotTableFilms()
Sender: tableRentsActionSignal: activated()Receiver: MainFormSlot:slotTableRents()
54
Implementation: slotTableCustomers
void MainForm::slotTableCustomers(){statusBar()->message(tr(QString::fromUtf8("Loading Table of Customers . . .")));setCaption(tr(QString::fromUtf8("Videoteka: Table of Customers ")));CustomersForm *customersForm = new CustomersForm(this, "CustomersForm");customersForm->show();setCentralWidget(customersForm);statusBar()->message(tr(QString::fromUtf8("Ready")));
}
mainform.ui.h
10
55
Implementation: slotTableFilms()
void MainForm::slotTableFilms(){
QMessageBox::information( this, "Videoteka Manager","Sorry! Not implemented yet." );
}
mainform.ui.h
Implementation: slotTableRents()
void MainForm::slotTableRents(){
QMessageBox::information( this, "Videoteka Manager","Sorry! Not implemented yet." );
}
mainform.ui.h
56
DataTable: Signals
57
New Slot: slotPrimeInsert()
Function: slotPrimeInsert(QSqlRecord*)Return type: voidSpecifier: virtualAccess: publicType: slot
Edit/Slots …
58
Connection
Sender: dataTableSignal: primeInsert(QSqlRecord*)Receiver: MainFormSlot:slotPrimeInsert(QSqlRecord*)
59
Implementation
void CustomersForm::slotPrimeInser( QSqlRecord *buffer ){
QSqlQuery query;query.exec("UPDATE sequence SET sequence = sequence + 1 WHERE tablename
='customers';");query.exec("SELECT sequence FROM sequence WHERE tablename ='customers';");if (query.next()) {
buffer->setValue("customer_id", query.value(0));}
}
customerform.ui.h
60
Controlling Data Entry
11
61
Slot: slotCurrentChanged()
Function: slotCurrentChanged(QSqlRecord*)Return type: voidSpecifier: virtualAccess: publicType: slot
62
Function: setMode()
Function: setMode(QSqlRecord*)Return type: voidSpecifier: virtualAccess: protectedType: function
Edit/Slots …
63
Implementation: slotCurrentChanged(), setMode()
void CustomersForm::slotCurrentChanged( QSqlRecord * buffer ){
setMode(buffer);}
void CustomersForm::setMode( QSqlRecord * buffer ){
if (buffer == 0) return;QSqlQuery query;int count_rent=0;query.exec( "SELECT count(*) FROM rents WHERE customer_id=" +
buffer->value("customer_id").toString() + ";" );if (query.next())
count_rent = query.value(0).toInt();if ( count_rent == 0)
dataTable->sqlCursor ()->setMode( QSqlCursor::Insert | QSqlCursor::Delete | QSqlCursor::Update );
elsedataTable->sqlCursor ()->setMode( QSqlCursor::Insert | QSqlCursor::Update );
}
customerform.ui.h
64
Compile & Run
65
Compile & Run
66
12
67
ComboBox
Modificationwith controls
Calculated field
Calculatedfield with
„info”
Read Only
68
Classes
QSqlCursor
FilmSqlCursorQDataTable
FilmDataTable
QMainWindow
Videoteka
main.cpp
69
Classes
QSqlCursor
FilmSqlCursorQDataTable
FilmDataTable
QMainWindow
Videoteka
main.cpp70
FilmSqlCursor - Definition
#include <qsqlcursor.h>
class FilmSqlCursor : public QSqlCursor {public:FilmSqlCursor();
protected:
QVariant calculateField(const QString &name);
};
filmsqlcursor.h
Protected virtual function which is called whenever a field needs to be calculated. If calculated fields are being used, derived classes must reimplement this function.
71
FilmSqlCursor - Implementation#include "filmsqlcursor.h"
FilmSqlCursor::FilmSqlCursor(): QSqlCursor("films"){
QSqlFieldInfo available("available", QVariant::Int);append(available);setCalculated(available.name(),TRUE);
}
QVariant FilmSqlCursor::calculateField(const QString &name){
if (name == "available") {QSqlQuery query;int available=0;query.exec("SELECT (amount - rented) FROM films WHERE film_id=" +
field("film_id")->value().toString() + ";");if (query.next())
available = query.value(0).toInt();return QVariant(QString::number(available));
}return QVariant(QString::null);
}
filmsqlcursor.cpp
The field „available” is a calculated field.
72
Classes
QSqlCursor
FilmSqlCursorQDataTable
FilmDataTable
QMainWindow
Videoteka
main.cpp
13
73
Preparing FilmDataTable Class
File/New/C++ Cource FileSave As:filmdatatable.cpp
File/New/C++ Cource FileSave As:filmdatatable.h
74
FilmDataTable: Definitionclass FilmSqlCursor;
class FilmDataTable : public QDataTable{Q_OBJECTpublic:FilmDataTable(QWidget * parent =0 , const char * name =0 );void paintField(
QPainter * p, const QSqlField* field, const QRect & cr, bool );
public slots:void slotPrimeInsert(QSqlRecord*);void slotCurrentChanged(QSqlRecord* buffer);void slotBeforeUpdate(QSqlRecord* buffer);
private:void setMode(QSqlRecord* buffer);
private:FilmSqlCursor *cursor;QSqlPropertyMap *propMap;FilmSqlEditorFactory *editorFactory;
};
filmdatatable.h
#include <qdatatable.h>#include <qpainter.h>#include <qsqleditorfactory.h>#include <qsqlpropertymap.h>
75
FilmDataTable: Constructor /BasicsFilmDataTable::FilmDataTable(
QWidget * parent, const char * name) :QDataTable( parent, name )
{cursor = new FilmSqlCursor();setSqlCursor(cursor);//addColumn( "film_id", "Id" );addColumn( "title", tr(QString::fromUtf8("Title")) );addColumn( "type", tr(QString::fromUtf8("Type")) );addColumn( "amount", tr(QString::fromUtf8("Amount")) );addColumn( "rented", tr(QString::fromUtf8("Rented")) );addColumn( "available", tr(QString::fromUtf8("Available")) );//setColumnWidth(1,200);refresh();setConfirmDelete(TRUE);setAutoEdit(TRUE);. . .
}
filmdatatable.cpp
#include "filmdatatable.h"#include "filmsqlcursor.h"#include <qmessagebox.h>
#include "typepicker.h"#include "readonlyedit.h"
76
FilmDataTable: Constructor /Property & Factory
FilmDataTable::FilmDataTable(QWidget * parent, const char * name) :QDataTable( parent, name )
{. . .propMap = new QSqlPropertyMap();propMap->insert( "TypePicker", "type" );installPropertyMap( propMap );
editorFactory = new FilmSqlEditorFactory();installEditorFactory( editorFactory );
. . .
}
filmdatatable.cpp
#include "filmdatatable.h"#include "filmsqlcursor.h"#include <qmessagebox.h>
#include "typepicker.h"#include "readonlyedit.h"
77
FilmDataTable: Constructor / ConnectionsFilmDataTable::FilmDataTable(
QWidget * parent, const char * name) :QDataTable( parent, name )
{. . .// signals and slots connectionsconnect( this, SIGNAL( primeInsert(QSqlRecord*) ),
this, SLOT( slotPrimeInsert(QSqlRecord*) ) );connect( this, SIGNAL( currentChanged(QSqlRecord*) ),
this, SLOT( slotCurrentChanged(QSqlRecord*) ) );connect( this, SIGNAL(beforeUpdate(QSqlRecord*) ),
this, SLOT(slotBeforeUpdate(QSqlRecord*) ) );}
filmdatatable.cpp
78
FilmDataTable: Destructor
FilmDataTable::~FilmDataTable(){
if (propMap) delete propMap;if (editorFactory) delete editorFactory;if (cursor) delete cursor; //May be it’s not necessary.
}
filmdatatable.cpp
FilmDataTable::FilmDataTable(. . .){cursor = new FilmSqlCursor();. . .propMap = new QSqlPropertyMap();. . .editorFactory = new FilmSqlEditorFactory();. . .
}
filmdatatable.cpp
14
79
FilmDataTable: slotPrimeInsert()void FilmDataTable::slotPrimeInsert(QSqlRecord * buffer){
QSqlQuery query;query.exec("UPDATE sequence SET sequence = sequence + 1 WHERE tablename
='films';");query.exec("SELECT sequence FROM sequence WHERE tablename ='films';");if (query.next()) {
buffer->setValue("film_id", query.value(0));buffer->setValue("amount",1);buffer->setValue("rented",0);buffer->setValue("available",1);buffer->setValue("type","DVD");
}
}
filmdatatable.cpp
Default values starting insertion.
Default calculatedvalue must be done, TOO, otherwise thisvalue remains zero.
80
FilmDataTable: slotBeforeUpdate()
void FilmDataTable::slotBeforeUpdate(QSqlRecord* buffer){if(buffer->value("amount").toInt() < buffer->value("rented").toInt()) {buffer->setValue("amount",buffer->value("rented"));QMessageBox::information( this,
tr(QString::fromUtf8("Videoteka: Updating Table of Films")),tr(QString::fromUtf8("Amount can not be less then number of rented films.!")));
}}
filmdatatable.cpp
81
FilmDataTable: setMode()void FilmDataTable::setMode(QSqlRecord* buffer){
if (buffer == 0) return;QSqlQuery query;int count_rented=0;query.exec( "SELECT rented FROM films WHERE film_id=" +
buffer->value("film_id").toString() + ";" );if (query.next())
count_rented = query.value(0).toInt();if ( count_rented == 0)
cursor->setMode( QSqlCursor::Insert | QSqlCursor::Delete | QSqlCursor::Update );else
cursor->setMode( QSqlCursor::Insert | QSqlCursor::Update );}
filmdatatable.cpp
82
Reimplementation of paintField()void FilmDataTable::paintField( QPainter * p, const QSqlField* field,const QRect & cr, bool b){
if ( !field )return;
if ( field->name() == "available" ) {QString text;if(field->value().toInt() == 0)text="* Out of stock*";
elsetext = field->value().toString();p->drawText( 2,2, cr.width()-4, cr.height()-4, fieldAlignment( field ), text );
} else {QDataTable::paintField( p, field, cr, b) ;
}}
filmdatatable.cpp
83
FilmSqlEditorFactory: Definition(embedded!)
class FilmSqlEditorFactory : public QSqlEditorFactory{
Q_OBJECTpublic:
QWidget *createEditor( QWidget *parent, const QSqlField *field );};
filmdatatable.h
To create „custom” editor you haveto reimlement createEditor() function.
84
FilmSqlEditorFactory: Implementation (embedded!)
. . .QWidget *FilmSqlEditorFactory::createEditor(
QWidget *parent, const QSqlField *field ){
if ( field->name() == "rented" ) {QWidget *editor = new ReadOnlyEdit( parent );return editor;
}if ( field->name() == "type" ) {
QWidget *editor = new TypePicker( parent );return editor;
}if ( field->name() == "available" ) {
QWidget *editor = new ReadOnlyEdit( parent );return editor;
} return QSqlEditorFactory::createEditor( parent, field );
}. . .
filmdatatable.cpp
For these three fields we wan to touse „custom” editor.(These two classes will be given later!)
TypePicker Editor
15
85
ReadOnlyEdit Class
#include <qlineedit.h>class ReadOnlyEdit : public QLineEdit {
Q_OBJECTpublic:
ReadOnlyEdit( QWidget *parent=0, const char *name=0 );};
readonlyedit.h
#include "readonlyedit.h"ReadOnlyEdit::ReadOnlyEdit( QWidget *parent, const char *name ) : QLineEdit( parent, name ){
setReadOnly(TRUE);
}
readonlyedit.cpp
86
TypePicker Class: Definition#include <qcombobox.h>class TypePicker : public QComboBox{Q_OBJECT
Q_PROPERTY( QString type READ Type WRITE setType )
public:TypePicker( QWidget *parent=0, const char *name=0 );QString Type() const;void setType( QString type );
};
typepicker.h
memberread() write()
87
#include "typepicker.h"#include <qsqlcursor.h>TypePicker::TypePicker( QWidget *parent, const char *name ) : QComboBox( parent, name ){
insertItem("DVD");insertItem("VHS");setCurrentText("DVD");
}
QString TypePicker::Type() const{
return currentText();}
void TypePicker::setType( QString type ){
setCurrentText( type );}
TypePicker Class: Definition
typepicker.h
read()
write()
88
Reads and writesReadingGenerates#includesToolGenerated source fileRevision controlled source file
SummaryQt
designer
UIC
form.cpp main.cpp
form.ui
form.h
form.ui
Application specific functions can be given
in form.ui.h file.
form.ui.h
89
Summary: Creating Dialogs
90
Summary: Creating Main Windows
16
91
Summary: Database Related Application
92