Elemi alkalmazások fejlesztése IV. C++/Qt adatbáziskezel ő alkalmazás készítése Kdevelop környezetben I. 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. Készítette: Szabóné Nacsa Rozália 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 1 2 Feladat Készítsünk adminisztrációs programot az Elemi alkalmazások fejlesztése tantárgyhoz. Az alkalmazás adatbázisa 3 4
Félév tábla Csopor t 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 +------------+----------+------+------------+----------+ 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)); 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)); 5 6 Gyakvez tábla Diák 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 +------------+---------------+ create table gyakvez ( gyakvez_id int(4) not null primary key, nev varchar(30)); 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) 7 create table diak ( diak_id int(4) not null primary key, azon varchar(20) unique, nev varchar(30)); 8
Tag tábla zh 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) 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 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 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 Kezdet 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) 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 jelentkezes ( zh_id int(4) not null, diak_id int(4) not null, eredm int(1), primary key (zh_id,diak_id)); create table kezdet ( kezdet_id int(4) not null primary key, kezdet varchar(20)); 11 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) Az alkalmazás néhány szolgáltatása create table sequence ( tablename varchar(10) not null primary key, sequence int(4)); 13 14 diak tábla módosítása diak tábla A diak_id ne jelenjen meg a táblázatban. Jobb egér klikk 15 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. A felev_id ne jelenjen meg a táblázatban. 17 18 A táblázat fejléce különbözhet az adatbázisbeli tábla mez őnevétől. A szám helyett egy kifejezőbb szöveget jelenítünk meg. 19 20
Új (számított) oszlopok is megjelennek a táblázatban. A számított adat helyett megjeleníthetünk valamilyen kifejezőbb szöveget is. 21 22 Igény szerint szűrhetjük a táblázatot. A megfelel ő eszközök kiválasztásával biztosíthatjuk az ellenőrzött adatbevitelt. 23 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. Ér tékelés/beadandó Táblázattal is szűrhetünk. 25 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 Qt / Sql modul Készíthetünk kimutatásokat is. Összetett lista. Itt már nem engedélyezzük az adatbevitelt/módosítást. 27 Az SQL modulban találhatók az adatbáziskezel ő osztályok. 28
Adatbázis kapcsolat: connection.h, connection.cpp 1 2 3 #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(); #include <qsqldatabase.h> #include "connection.h" connection.cpp 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.h 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 29 3.a kapcsolat megnyitása 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 QSqlQuer y QSqlCur sor adat (tábla) reprezentálása adat (tábla) reprezentálása QTable QDataTable adat megjelenítése adat megjelenítése 31 QSqlQuer y 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 QSqlQuery objektum +----------------+-------+ 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ár ia'); ); QSqlQuery query ( SELECT nev, azon FROM diak WHERE nev LIKE 'K% '; ); QTable objektum 32
QSqlCursor QDataTable 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 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 QSqlCursor objektum QSqlCursor cur( "diak"); cur.select( nev LIKE 'K% ' ); QDataTable objektum QSqlCursor QDataTable alkalmazása #include <qapplication.h> #include <qsqldatabase.h> #include <qsqlcursor.h> #include <qdatatable.h> #include "connection.h" int main( int argc, char *argv[] ) 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; A mezőnév legyen ugyanaz, mint az adatbázisban QSqlRecord *buffer = cur.primeinsert(); További szolgáltatás: származtatással buffer->setvalue( "diak_id", 2); buffer->setvalue( "azon", "KKATA"); buffer->setvalue( "nev", "Kiss Katalin"); cur.insert(); 33 34 Táblák/Diák menüpont Diák tábla kar bantar tása 35 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()));... Táblák/Diák menüpont aktualizálása #include "diakdatatable.h" eafadmin.cpp 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"))); 37 38 A DiakDataTable osztály QSqlCursor QDataTable DiakDataTable QMainWindow EafAdmin main.cpp 39 #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*); private: QSqlCursor *cursor; ; DiakDataTable: osztály deklaráció diakdatatable.h 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.cpp 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); DiakDataTable - slotprimeinser t 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)); // signals and slots connections connect( this, SIGNAL( primeinsert(qsqlrecord*) ), this, SLOT( slotprimeinsert(qsqlrecord*) ) ); 41 42 Ellenőrzött adatbevitel DiakDataTable slotcur rentchanged #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 DiakDataTable::slotCurrentChanged(QSqlRecord* buffer) setmode(buffer); void slotcurrentchanged(qsqlrecord* buffer); private: void setmode(qsqlrecord* buffer); QSqlCursor *cursor; ; 43 44
DiakDataTable setmode void DiakDataTable::setMode(QSqlRecord* buffer) diakdatatable.cpp 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 ); #include <qapplication.h> #include <qobject.h> #include "eafadmin.h" #include "connection.h" int main( int argc, char ** argv ) main.cpp 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(); 45 46 Futtatás Folytatása következik... 47 48