Elemi alkalmazások fejlesztése IV. C++/Qt adatbáziskezelő alkalmazás készítése Kdevelop környezetben I. Készítette: Szabóné Nacsa Rozália 1
MySql elindítása [nacsa@localhost nacsa]$ su Password:jelszó [root@localhost nacsa]# /usr/bin/safe_mysqld & [1] 1028 [root@localhost nacsa]# Starting mysqld daemon with databases from /var/lib/mysql exit [nacsa@localhost nacsa]$ /usr/bin/mysql -u nacsa -p Enter password:jelszó Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 to server version: 3.23.54 Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> use eaf; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A 2
Feladat Készítsünk adminisztrációs programot az Elemi alkalmazások fejlesztése tantárgyhoz. 3
Az alkalmazás adatbázisa 4
Félév tábla mysql> select * from felev; +----------+------+-------------+------+------+ felev_id szam kezdet fsz max +----------+------+-------------+------+------+ 37 1 2002/2003-2 4 2 38 3 2002/2003-2 4 3 39 2 2003/2004-1 4 2 40 4 2003/2004-1 4 3 +----------+------+-------------+------+------+ 4 rows in set (0.00 sec) create table felev ( felev_id int(4) not null unique, szam int(4) not null, kezdet varchar(20) not null, fsz int(4), max int(4), primary key (szam,kezdet)); 5
Csoport tábla mysql> select * from csoport; +------------+----------+------+------------+----------+ csoport_id nev max gyakvez_id felev_id +------------+----------+------+------------+----------+ 13 Csop 2/1 4 1 39 12 Csop 4/2 5 3 40 11 Csop 4/1 3 5 40 14 Csop 2/2 3 5 39 +------------+----------+------+------------+----------+ 4 rows in set (0.00 sec) create table csoport ( csoport_id int(4) not null primary key, nev varchar(20), max int(4), gyakvez_id int(4), felev_id int(4)); 6
Gyakvez tábla mysql> select * from gyakvez; +------------+---------------+ gyakvez_id nev +------------+---------------+ 1 Varga Péter 3 Kovács József 4 Molnár Virág 5 Kiss Katalin +------------+---------------+ 4 rows in set (0.00 sec) create table gyakvez ( gyakvez_id int(4) not null primary key, nev varchar(30)); 7
Diák tábla mysql> select * from diak; +---------+-------+----------------+ diak_id azon nev +---------+-------+----------------+ 1 KPETE Kovács Péter 2 KKATA Kiss Katalin 3 NKATA Nagy Katalin 5 CSVIR Cserép Virág 6 NJANO Nagy János 7 KJANO Kiss János 8 MADAM Molnár Ádám 9 KADAM Kovács Ádám 11 KBALA Kerekes Balázs 12 NSAND Nagy Sándor +---------+-------+----------------+ 10 rows in set (0.00 sec) create table diak ( diak_id int(4) not null primary key, azon varchar(20) unique, nev varchar(30)); 8
Tag tábla mysql> select * from tag; +---------+------------+-------+-------+-------+-------+ diak_id csoport_id pont1 pont2 pont3 pont4 +---------+------------+-------+-------+-------+-------+ 1 13 5 4 4 5 8 13 5 5 5 5 5 13 0 0 0 0 9 13 1 1 2 2 7 12 0 0 0 0 11 12 0 0 0 0 6 12 0 0 0 0 +---------+------------+-------+-------+-------+-------+ 7 rows in set (0.00 sec) create table tag ( diak_id int(4) not null, csoport_id int(4) not null, pont1 int(4), pont2 int(4), pont3 int(4), pont4 int(4), primary key (diak_id, csoport_id)); 9
zh tábla mysql> select * from zh; +-------+------+------+----------+ zh_id max ido felev_id +-------+------+------+----------+ 3 3 40 4 5 39 +-------+------+------+----------+ 2 rows in set (0.00 sec) create table zh ( zh_id int(4) not null primary key, max int(4), ido varchar(20), felev_id int(4)); 10
Jelentkezés tábla mysql> select * from jelentkezes; +-------+---------+-------+ zh_id diak_id eredm +-------+---------+-------+ 4 1 1 4 8 1 4 9 1 +-------+---------+-------+ 3 rows in set (0.00 sec) create table jelentkezes ( zh_id int(4) not null, diak_id int(4) not null, eredm int(1), primary key (zh_id,diak_id)); 11
Kezdet tábla mysql> select * from kezdet; +-----------+-------------+ kezdet_id kezdet +-----------+-------------+ 1 2000/2001-1 2 2000/2001-2 3 2001/2002-1 4 2001/2002-2 5 2002/2003-1 6 2002/2003-2 7 2003/2004-1 8 2003/2004-2 +-----------+-------------+ 8 rows in set (0.00 sec) create table kezdet ( kezdet_id int(4) not null primary key, kezdet varchar(20)); 12
Sequence tábla mysql> select * from sequence; +-----------+----------+ tablename sequence +-----------+----------+ felev 42 csoport 19 gyakvez 5 diak 13 zh 4 potzh 0 +-----------+----------+ 6 rows in set (0.00 sec) create table sequence ( tablename varchar(10) not null primary key, sequence int(4)); 13
Az alkalmazás néhány szolgáltatása 14
diak tábla A diak_id ne jelenjen meg a táblázatban. 15
diak tábla módosítása Jobb egér klikk Jobb egér klikk Csak akkor engedélyezzük a törlést, ha az adott diák még egyáltalán nem szerepel a nyilvántartásunkban. 16
gyakvez tábla Csak akkor engedélyezzük a törlést, ha az adott gyakorlatvezetőnek még nincs csoportja. 17
mysql> select * from felev; +----------+------+-------------+------+------+ felev_id szam kezdet fsz max +----------+------+-------------+------+------+ 37 1 2002/2003-2 4 2 38 3 2002/2003-2 4 3 39 2 2003/2004-1 4 2 40 4 2003/2004-1 4 3 +----------+------+-------------+------+------+ 4 rows in set (0.00 sec) A felev_id ne jelenjen meg a táblázatban. 18
mysql> select * from felev; +----------+------+-------------+------+------+ felev_id szam kezdet fsz max +----------+------+-------------+------+------+ 37 1 2002/2003-2 4 2 38 3 2002/2003-2 4 3 39 2 2003/2004-1 4 2 40 4 2003/2004-1 4 3 +----------+------+-------------+------+------+ 4 rows in set (0.00 sec) A táblázat fejléce különbözhet az adatbázisbeli tábla mező nevétől. 19
mysql> select * from felev; +----------+------+-------------+------+------+ felev_id szam kezdet fsz max +----------+------+-------------+------+------+ 37 1 2002/2003-2 4 2 38 3 2002/2003-2 4 3 39 2 2003/2004-1 4 2 40 4 2003/2004-1 4 3 +----------+------+-------------+------+------+ 4 rows in set (0.00 sec) A szám helyett egy kifejezőbb szöveget jelenítünk meg. 20
mysql> select * from felev; +----------+------+-------------+------+------+ felev_id szam kezdet fsz max +----------+------+-------------+------+------+ 37 1 2002/2003-2 4 2 38 3 2002/2003-2 4 3 39 2 2003/2004-1 4 2 40 4 2003/2004-1 4 3 +----------+------+-------------+------+------+ 4 rows in set (0.00 sec) Új (számított) oszlopok is megjelennek a táblázatban. 21
mysql> select * from felev; +----------+------+-------------+------+------+ felev_id szam kezdet fsz max +----------+------+-------------+------+------+ 37 1 2002/2003-2 4 2 38 3 2002/2003-2 4 3 39 2 2003/2004-1 4 2 40 4 2003/2004-1 4 3 +----------+------+-------------+------+------+ 4 rows in set (0.00 sec) A számított adat helyett megjeleníthetünk valamilyen kifejezőbb szöveget is. 22
mysql> select * from felev; +----------+------+-------------+------+------+ felev_id szam kezdet fsz max +----------+------+-------------+------+------+ 37 1 2002/2003-2 4 2 38 3 2002/2003-2 4 3 39 2 2003/2004-1 4 2 40 4 2003/2004-1 4 3 +----------+------+-------------+------+------+ 4 rows in set (0.00 sec) Igény szerint szűrhetjük a táblázatot. 23
A megfelelő eszközök kiválasztásával biztosíthatjuk az ellenőrzött adatbevitelt. 24
+------------+----------+------+------------+----------+ csoport_id nev max gyakvez_id felev_id +------------+----------+------+------------+----------+ 13 Csop 2/1 4 1 39 12 Csop 4/2 5 3 40 11 Csop 4/1 3 5 40 14 Csop 2/2 3 5 39 +------------+----------+------+------------+----------+ A megfelelő eszközök kiválasztásával biztosíthatjuk az ellenőrzött adatbevitelt. +----------+------+-------------+------+------+ felev_id szam kezdet fsz max +----------+------+-------------+------+------+ 37 1 2002/2003-2 4 2 38 3 2002/2003-2 4 3 39 2 2003/2004-1 4 2 40 4 2003/2004-1 4 3 +----------+------+-------------+------+------+ 25
Értékelés/Beadandó Táblázattal is szűrhetünk. Csak a beadandó pontszámait lehet módosítani. A megfelelő jogosultságok beállításával biztosíthatjuk az ellenőrzött adatbevitelt. 26
Kimutatás/Diák Készíthetünk kimutatásokat is. Összetett lista. Itt már nem engedélyezzük az adatbevitelt/módosítást. 27
Qt / Sql modul Az SQL modulban találhatók az adatbáziskezelő osztályok. 28
Adatbázis kapcsolat: connection.h, connection.cpp #define DB_SOURCE_DRIVER "QMYSQL3" #define DB_SOURCE_DBNAME "eaf" #define DB_SOURCE_USER "nacsa" #define DB_SOURCE_PASSWD "1234" #define DB_SOURCE_HOST "localhost" bool createconnections(); connection.h 1 2 3 #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( "Az adatbázist nem sikerült megnyitni: " + source >lasterror().drivertext() ); qwarning( source >lasterror().databasetext() ); return FALSE; } return TRUE; } connection.cpp 1.az adatbázist kezelő meghajtó aktivizálása 2.a kapcsolat adatainak beállítása adatbázis neve felhasználó neve jelszó host név 3.a kapcsolat megnyitása 29
Adatbázis kapcsolat: main.cpp... #include <qsqldatabase.h> #include "connection.h... int main( int argc, char *argv[] ) {... if ( createconnections() ) { // Az adatbázist sikeresen megnyitottuk. // Mostmár kiadhatunk Sql parancsokat. } return 0; } main.cpp 30
Adatbáziskezelő Qt osztályok Statikus adatkezelés Dinamikus adatkezelés QSqlQuery adat (tábla) reprezentálása QTable adat megjelenítése QSqlCursor adat (tábla) reprezentálása QDataTable adat megjelenítése 31
QSqlQuery QTable Az adatbázis diak táblája +---------+-------+----------------+ diak_id azon nev +---------+-------+----------------+ 1 KPETE Kovács Péter 2 KKATA Kiss Katalin 3 NKATA Nagy Katalin 5 CSVIR Cserép Virág 6 NJANO Nagy János 7 KJANO Kiss János 8 MADAM Molnár Ádám 9 KADAM Kovács Ádám 11 KBALA Kerekes Balázs 12 NSAND Nagy Sándor +----------------+-------+ nev azon +----------------+-------+ +---------+-------+----------------+ Kovács Péter KPETE Kiss Katalin KKATA Kiss János KJANO Kovács Ádám KADAM Kerekes Balázs KBALA +----------------+-------+ QSqlQuery query ( INSERT INTO diak (diak_id,azon,nev) VALUES (13,'UMAR','Kiss Mária'); ); QSqlQuery query ( SELECT nev, azon FROM diak WHERE nev LIKE 'K%'; ); QSqlQuery objektum Diák neve Kovács Péter Kiss Katalin Kiss János Kovács Ádám Kerekes Balázs QTable objektum Diak azonosítója KPETE KKATA KJANO KADAM KBALA 32
Az adatbázis diak táblája QSqlCursor QDataTable +---------+-------+----------------+ diak_id azon nev +---------+-------+----------------+ 1 KPETE Kovács Péter 2 KKATA Kiss Katalin 3 NKATA Nagy Katalin 5 CSVIR Cserép Virág 6 NJANO +---------+-------+----------------+ Nagy János 7 KJANO Kiss diak_id János azon nev 8 MADAM +---------+-------+----------------+ Molnár Ádám 9 KADAM Kovács Ádám 1 KPETE Kovács Péter 11 KBALA Kerekes 2 Balázs KKATA Kiss Katalin 12 NSAND Nagy Sándor 3 NKATA Nagy Katalin +---------+-------+----------------+ 5 CSVIR Cserép Virág 6 NJANO Nagy János 7 KJANO Kiss János 8 MADAM Molnár Ádám 9 KADAM Kovács Ádám 11 KBALA Kerekes Balázs 12 NSAND Nagy Sándor +---------+-------+----------------+ QSqlRecord *buffer = cur.primeinsert(); buffer >setvalue( "diak_id", 2); buffer >setvalue( "azon", "KKATA"); buffer >setvalue( "nev", "Kiss Katalin"); cur.insert(); Diák neve Kovács Péter Kiss Katalin Kiss János Kovács Ádám Kerekes Balázs QSqlCursor objektum QSqlCursor cur( "diak"); cur.select( nev LIKE 'K%' ); QDataTable objektum Diak azonosítója KPETE KKATA KJANO KADAM KBALA 33
QSqlCursor QDataTable alkalmazása #include <qapplication.h> #include <qsqldatabase.h> A mezőnév #include <qsqlcursor.h> #include <qdatatable.h> legyen #include "connection.h" int main( int argc, char *argv[] ) ugyanaz, mint { az adatbázisban QApplication app( argc, argv ); if ( createconnections() ) { QSqlCursor diakcursor( "diak"); QDataTable *diaktable = new QDataTable(&diakCursor, TRUE); app.setmainwidget(diaktable); //diakcursor.setmode( QSqlCursor::ReadOnly ); diaktable->refresh(); diaktable->show(); return app.exec(); return 0; } További szolgáltatás: származtatással 34
Táblák/Diák menüpont 35
Diák tábla karbantartása 36
EafAdmin osztály implementációja void EafAdmin::initActions(){ eafadmin.cpp } /** File Menu */ filequit = new QAction(tr("Exit"), tr("e&xit"), QAccel::stringToKey(tr("Ctrl+Q")), this); filequit >setstatustip(tr("quits the application")); filequit >setwhatsthis(tr("exit\n\nquits the application")); connect(filequit, SIGNAL(activated()), this, SLOT(slotFileQuit())); /** Tabla Menu */ tabladiak = new QAction(tr(QString::fromUtf8("Diák")), tr(qstring::fromutf8("&diák")), QAccel::stringToKey(tr("Ctrl+D")), this); tabladiak >seticonset( QIconSet( QPixmap::fromMimeSource( "./images/tabladiak.png" ) ) ); tabladiak >setstatustip(tr(qstring::fromutf8("diák tábla karbantartása"))); tabladiak >setwhatsthis(tr(qstring::fromutf8("diák tábla karbantartása"))); connect(tabladiak, SIGNAL(activated()), this, SLOT(slotTablaDiak()));... 37
Táblák/Diák menüpont aktualizálása #include "diakdatatable.h" void EafAdmin::slotTablaDiak() { statusbar() >message(tr(qstring::fromutf8("diák tábla betöltése..."))); setcaption(tr(qstring::fromutf8("elemi Alkalmazások fejlesztése: Diák tábla karbantartása "))); DiakDataTable *diakdatatable = new DiakDataTable(this, "DiakDataTable"); diakdatatable >show(); setcentralwidget(diakdatatable); statusbar() >message(tr(qstring::fromutf8("kész"))); } eafadmin.cpp 38
A DiakDataTable osztály QSqlCursor QDataTable QMainWindow DiakDataTable EafAdmin main.cpp 39
#include <qdatatable.h> #include <qsqlcursor.h> DiakDataTable: osztály deklaráció diakdatatable.h class DiakDataTable : public QDataTable { Q_OBJECT public: DiakDataTable(QWidget * parent =0, const char * name =0 ); public slots: void slotprimeinsert(qsqlrecord*); private: QSqlCursor *cursor; QDataTable signals: }; void currentchanged ( QSqlRecord * record ) void primeinsert ( QSqlRecord * buf ) void primeupdate ( QSqlRecord * buf ) void primedelete ( QSqlRecord * buf ) void beforeinsert ( QSqlRecord * buf ) void beforeupdate ( QSqlRecord * buf ) void beforedelete ( QSqlRecord * buf ) void cursorchanged ( QSql::Op mode ) 40
DiakDataTable: konstruktor #include "diakdatatable.h" DiakDataTable::DiakDataTable(QWidget * parent, const char * name) : QDataTable( parent, name ) { cursor = new QSqlCursor("diak"); setsqlcursor(cursor); //addcolumn( "diak_id", "Kód" ); addcolumn( "azon", tr(qstring::fromutf8("azonosító")) ); addcolumn( "nev", tr(qstring::fromutf8("név")) ); setcolumnwidth(2,200); refresh(); setconfirmdelete(true); setautoedit(true); // signals and slots connections connect( this, SIGNAL( primeinsert(qsqlrecord*) ), this, SLOT( slotprimeinsert(qsqlrecord*) ) ); } diakdatatable.cpp 41
DiakDataTable slotprimeinsert void DiakDataTable::slotPrimeInsert(QSqlRecord * buffer) { diakdatatable.cpp QSqlQuery query; query.exec("update sequence SET sequence = sequence + 1 WHERE tablename ='diak';"); query.exec("select sequence FROM sequence WHERE tablename ='diak';"); if (query.next()) { buffer >setvalue("diak_id", query.value(0)); } } 42
Ellenőrzött adatbevitel #include <qdatatable.h> #include <qsqlcursor.h> class DiakDataTable : public QDataTable { Q_OBJECT public: DiakDataTable(QWidget * parent =0, const char * name =0 ); public slots: void slotprimeinsert(qsqlrecord*); void slotcurrentchanged(qsqlrecord* buffer); private: void setmode(qsqlrecord* buffer); QSqlCursor *cursor; }; 43
DiakDataTable slotcurrentchanged void DiakDataTable::slotCurrentChanged(QSqlRecord* buffer) { setmode(buffer); } 44
DiakDataTable setmode void DiakDataTable::setMode(QSqlRecord* buffer) { if (buffer == 0) return; QSqlQuery query; int count_tag=0; query.exec( "SELECT count(*) FROM tag WHERE diak_id=" + buffer >value("diak_id").tostring() + ";" ); if (query.next()) count_tag = query.value(0).toint(); int count_jelentkezes=0; query.exec("select count(*) FROM jelentkezes WHERE diak_id=" + buffer >value("diak_id").tostring() + ";"); if (query.next()) count_jelentkezes = query.value(0).toint(); if ( count_tag == 0 and count_jelentkezes == 0 ) cursor >setmode( QSqlCursor::Insert QSqlCursor::Delete QSqlCursor::Update ); else cursor >setmode( QSqlCursor::Insert QSqlCursor::Update ); } diakdatatable.cpp 45
main.cpp #include <qapplication.h> #include <qobject.h> #include "eafadmin.h" #include "connection.h" int main( int argc, char ** argv ) { } QApplication a( argc, argv ); if (!createconnections()) return 1; EafAdmin * mw = new EafAdmin(); mw >setcaption(qobject::tr(qstring::fromutf8("elemi Alkalmazások fejlesztése "))); mw >show(); a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) ); return a.exec(); 46
Futtatás 47
Folytatása következik... 48