Eseményvezérelt alkalmazások fejlesztése I 11. előadás. Adatkezelés speciális eszközökkel. Giachetta Roberto

Hasonló dokumentumok
Adatok speciális megjelenítése

Eseményvezérelt alkalmazások fejlesztése I 10. előadás. Adatbázis-kezelés modell/nézet architektúrában. Giachetta Roberto

Eseményvezérelt alkalmazások fejlesztése I 8. előadás. Adatbázis-kezelés modell/nézet architektúrában

Adatbáziskezelés M/V architektúrában

Elemi alkalmazások fejlesztése IV. Adatbázis-kezelő GUI alkalmazás készítése 3. Összetett tábla karbantartása

Elemi alkalmazások fejlesztése III.

3. Beadandó feladat dokumentáció

Alkalmazások fejlesztése III. Qt 4 /C++ alapú MDI alkalmazás: Számlakészítő program 2/3

Webes alkalmazások fejlesztése 4. előadás. Megjelenítés és tartalomkezelés (ASP.NET Core) Cserép Máté

Webes alkalmazások fejlesztése 4. előadás. Megjelenítés és tartalomkezelés (ASP.NET)

Webes alkalmazások fejlesztése 4. előadás. Megjelenítés és tartalomkezelés (ASP.NET) Cserép Máté.

2. Beadandó feladat dokumentáció

Fogalmak: Adatbázis Tábla Adatbázis sorai: Adatbázis oszlopai azonosító mező, egyedi kulcs Lekérdezések Jelentés Adattípusok: Szöveg Feljegyzés Szám

3. Beadandó feladat dokumentáció

Választó lekérdezés létrehozása

Elemi alkalmazások fejlesztése IV.

MySql elindítása. Elemi alkalmazások fejlesztése IV. Feladat. Az alkalmazás adatbázisa

2. Beadandó feladat dokumentáció

Adatbázis-kezelés ActiveX vezérl kkel 2.rész

Adabáziselérés ODBC-n keresztül utasításokkal C#-ban

Swing GUI készítése NetBeans IDE segítségével

HVK Adminisztrátori használati útmutató

Adatbázis-kezelés az Excel 2013-ban

DKÜ ZRT. A Portál rendszer felületének általános bemutatása. Felhasználói útmutató. Támogatott böngészők. Felületek felépítése. Információs kártyák

Bevezetés a Programozásba II 8. előadás. Polimorfizmus Giachetta Roberto

Java Programozás 9. Gy: Java alapok. Adatkezelő 5.rész

Adatbáziskezelés alapjai. jegyzet

Eseményvezérelt alkalmazások fejlesztése II 12. előadás. Objektumrelációs adatkezelés (ADO.NET) Giachetta Roberto

ABAP dictionary objektumok SAP adatmodell Táblák kezelése. Az SAP programozása 1. Tarcsi Ádám

MTMT adminisztrátori felület és teendők. Mátyás Melinda, Szabó Panna november 4. ELTE Egyetemi Könyvtár

Programozási technikák Pál László. Sapientia EMTE, Csíkszereda, 2009/2010

Bizonylatok felvitele mindig a gazdasági eseménnyel kezdődik, majd ezután attól függően jelennek meg dinamikusan a további adatmezők.

ReszlAd fájl, kitöltési útmutató:

SEGÉDLET ADATKEZELÉS MS EXCEL-BEN. Tároljuk az adatokat Excel munkalapon. Megjegyzés: A feladatokat MS Office Excel ban oldottuk meg.

Tartalom Képernyő részei... 2

FELHASZNÁLÓI ÚTMUTATÓ

Egyéni párbeszédpanel Excelben

Programozási technológia

MS ACCESS 2010 ADATBÁZIS-KEZELÉS ELMÉLET SZE INFORMATIKAI KÉPZÉS 1

Az MS Excel táblázatkezelés modul részletes tematika listája

A Paint program használata

Access gyakorlati feladatok lépésről lépésre

az adatbevitel szabályozása, alapok

Adatbázis-kezelés Access XP-vel. Tanmenet

Alkalmazott Modul III 6. gyakorlat. Objektumorientált programozás: öröklődés és polimorfizmus

Egységes és objektumközpontú adatbázis-kezelés (2. rész)

Adatbázis kezelés Delphiben. SQL lekérdezések

OOP: Java 8.Gy: Abstract osztályok, interfészek

A gyakorlat során az alábbi ábrán látható négy entitáshoz kapcsolódó adatbevitelt fogjuk megoldani.

POSZEIDON dokumentáció (1.2)

Választó lekérdezések

BME MOGI Gépészeti informatika 7.

Webes alkalmazások fejlesztése 10. előadás. Webszolgáltatások tesztelése (ASP.NET Core) Cserép Máté

ALAPOK. 0 és 255 közé eső számértékek tárolására. Számértékek, például távolságok, pontszámok, darabszámok.

Programozási nyelvek Java

Felhasználó által definiált adattípus

Eseményvezérelt alkalmazások fejlesztése I 11. előadás. Szoftverek tesztelése

Oktatási anyag az MLSZ-IFA rendszerhez

A főképernyő felső ikonsorába kerültek a sajátmappa különböző füleire vezérlő ikonok, valamint a gyakran használt műveletek.

RBLDNS DNS-based blocklists management felhasználói kézikönyv

Elemi alkalmazások fejlesztése IV. Adatbáziskezel alkalmazás készítése QtDesignerben. Készítette: Szabóné Nacsa Rozália

CabMap hálózat-dokumentáló rendszer

A feladatok megoldásához felhasználandó osztályok leírásait az alábbi URL-en találja meg:

Webes alkalmazások fejlesztése 8. előadás. Webszolgáltatások megvalósítása (ASP.NET WebAPI)

Java Programozás 6. Gy: Java alapok. Adatkezelő 2.rész

A jobboldalon a pnlright egy Stacked Widget Állítsuk be az első lapot és nevezzük el pnldraw-ra:

munkafüzet open eseményéhez

Thermo1 Graph. Felhasználói segédlet

FELHASZNÁLÓI ÚTMUTATÓ

Banki export leírás. A modul egy erre használatos termékszám aktiválása után érhető el.

Diagram készítése. Diagramok formázása

INFORMATIKAI ALAPISMERETEK

Általános szoftver architektúrák

Bevezetés a Programozásba II 11. előadás. Adatszerkezetek megvalósítása. Adatszerkezetek megvalósítása Adatszerkezetek

ETA tárgyfelelős. Munka az ETA-ban tárgyfelelősként

Webes alkalmazások fejlesztése 3. előadás. Objektumrelációs adatkezelés (ASP.NET)

Könyvtári nyilvántartás

Webes kurzus kezelés folyamata Oktatói felületek

A beszámoló készítés lépéseinek bemutatása egy mintacég Egyszerű Kft. segítségével

TABULÁTOROK TÁBLÁZATOK KÉSZÍTÉSE. A táblázatok készítésének lehetőségei:

Adatintegritás ellenőrzés Felhasználói dokumentáció verzió 2.0 Budapest, 2008.

Felhasználói kézikönyv a WEB EDInet rendszer használatához

Programozás BMEKOKAA146. Dr. Bécsi Tamás 10. Előadás

Tervezett fakitermelések bejelentése

Táblázatok kezelése. 1. ábra Táblázat kezelése menüből

Dokumentum létrehozása/módosítása a portálon:

NEPTUN_GOLYA. (Felvételi konvertáló modul) Budapest, 2002

A program telepítése

JLR EPC. Gyors kezdés útmutatója. Tartalom. Hungry Version 2.0. Lépésenkénti gyakorlati útmutató Képernyős útmutató

Verziószám 2.2 Objektum azonosító (OID) Hatálybalépés dátuma szeptember 2.

Cikktípusok készítése a Xarayában

VARIO Face 2.0 Felhasználói kézikönyv

ECDL Táblázatkezelés A táblázatkezelés első lépései Beállítások elvégzése

Elemi alkalmazások fejlesztése III.

Adatbázisok. 8. gyakorlat. SQL: CREATE TABLE, aktualizálás (INSERT, UPDATE, DELETE), SELECT október október 26. Adatbázisok 1 / 17

LBRA6i integrált rendszer

SAP HR Általános lekérdező Ad-hoc-query

Szöveges műveletek. Mielőtt nekikezdenénk első szövegünk bevitelének, tanuljunk meg néhány alapvető műveletet a 2003-as verzió segítségével:

Egészítsük ki a Drupal-t. Drupal modul fejlesztés

Átírás:

Eötvös Loránd Tudományegyetem Informatikai Kar Eseményvezérelt alkalmazások fejlesztése I 11. előadás Adatkezelés speciális eszközökkel Giachetta Roberto http://people.inf.elte.hu/groberto

Az adatkezelés lehetőségei Adatbázis tartalom alkalmazáson keresztüli kezelése számos problémát felvet, amit figyelembe kell vennünk, pl.: adatok helyességének ellenőrzése (pl. tartomány, formátum) adatok meglétének ellenőrzése (kötelezően kitöltendő mezők esetén), esetleges kitöltése alapértelmezett értékkel speciális adatmegjelenítés (pl. mértékegységek) kapcsolt táblák adatainak együttes, vagy külön kezelése, szerkesztése adatbázisban indirekt tárolt adatok megjelenítése (pl. aggregált információk kapcsolt táblából), esetlegesen szerkesztése ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:2

Változások követése Az adatmodellek lehetőségek adnak az adatokban, illetve a szerkezetben történt változások követésére, amelyeket felhasználhatunk ellenőrzések, vagy automatikus kitöltések végrehajtására, pl.: kezelhetjük adatok változását közvetlenül a változást követően a datachanged(<tartomány bal felső indexe>, <jobb alsó indexe>) eseménnyel kezelhetjük a sorok (rekordok) változását az adatbázisba történő mentéskor (submit() és submitall() lefutásakor) a beforeinsert(<rekord>), beforedelete(<sorszám>) és beforeupdate(<sorszám>, <rekord>) eseményekkel ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:3

Változások követése A változáskövetést célszerű manuális szerkesztési stratégiával használni, mivel így a változtatások visszavonhatóak (revertall()) mentés előtt Pl.: model_datachanged(const QModelIndex topleft, ) { if (topleft.column() == 3 && model.value(topleft).isnull()) // ha a 3-as oszlopban vagyunk, és // elfelejtettük kitölteni model.setdata(topleft, 0); // utólag kitölthetjük 0-ra } ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:4

Feladat: Módosítsuk az épületek szerkesztését úgy, hogy ellenőrizze a tengerpart távolság értékét (csak pozitív szám lehet), és mentéskor minden új sorhoz szúrja be az új hirdetés megjegyzést. Ezen felül lehessen a városokat is hozzáadni, törölni (feltéve, hogy a városban nincs épület). az ellenőrzést és az automatikus beírást a modell beforeinsert és DataChanged eseményeivel kezeljük a városokat külön dialógusablakban (CityEditorDialog) szerkeszthetjük (mivel csak a nevüket kell, elég egy ListView nézet) úgy, hogy a modellt az épületek modell relációjából olvassuk ki (relationmodel(2)) az épület azonosítóját rejtsük el (úgyis generálódik) ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:5

Tervezés (adatbázis): ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:6

Tervezés (alkalmazás): BuildingTableDialog - _addbutton :QPushButton* - _buttonbox :QDialogButtonBox* - _citytabledialog :CityTableDialog* - _model :QSqlRelationalTableModel* - _removebutton :QPushButton* - _revertbutton :QPushButton* - _submitbutton :QPushButton* - _tableview :QTableView* + BuildingTableDialog(QWidget*) + ~BuildingTableDialog() - setupmodel() :void - setupui() :void QDialog «slot» - addbutton_clicked() :void - model_beforeinsert(qsqlrecord&) :void - model_datachanged(qmodelindex&, QModelIndex&) :void - removebutton_clicked() :void - submitbutton_clicked() :void - tableview_doubleclicked(qmodelindex) :void -_citytabledialog CityEditorDialog QDialog - _listview :QListView* - _model :QSqlTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* + CityEditorDialog(QWidget*) + ~CityEditorDialog() + setmodel(qsqltablemodel*) :void - setupmodel() :void - setupui() :void «slot» - addbutton_clicked() :void - removebutton_clicked() :void ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:7

Megvalósítás (buildingeditordialog.cpp): connect(_model, SIGNAL(beforeInsert(QSqlRecord&)), this, SLOT(model_BeforeInsert(QSqlRecord&))); // beszúrás előtti esemény társítása connect(_model, SIGNAL(beforeUpdate(int, QSqlRecord&)), this, SLOT(model_BeforeUpdate(int, QSqlRecord&))); // adatváltoztatás esemény társítása tableview->setcolumnhidden(0, true); // első oszlop elrejtése ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:8

Megvalósítás (buildingeditordialog.cpp): void BuildingEditorDialog:: model_beforeinsert(qsqlrecord& record){ if (record.value("comment").isnull()) // ha a komment oszlop üres record.setvalue("comment", trutf8("új hirdetés")); } void BuildingEditorDialog:: tableview_doubleclicked(qmodelindex index){ if (index.isvalid() && index.column() == 2) _cityeditordialog->show(); // megjelenítjük a városszerkesztőt } ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:9

Speciális adatmegjelenítés A modell és a megjelenítő közötti kapcsolatot a delegált (QAbstractItemDelegate leszármazott) osztályok biztosítják, amelyek szabályozzák a megjelenítés módját az alap megjelenítést a QItemDelegate, a relációk kezelését a QSqlRelationalDelegate, egyedi megjelenítést pedig a QStyledItemDelegate szolgáltatja QAbstractItemDelegate QItemDelegate QStyledItemDelegate QSqlRelationalDelegate ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:10

Egyedi delegáltak létrehozása Lehetőségünk van bármely osztályból történő származtatással további speciális megjelenítési módok definiálásra a delegált paint( ) művelete szolgál a kirajzolás végrehajtására, ezt kell felüldefiniálnunk paraméterben megkapja a kirajzoló objektumot (QPainter), a kirajzolási stílust (QStyleOptionViewItem), valamint a kirajzolandó adatot (QModelIndex) a stílusban megfogalmazhatunk különböző módokat (tagolás, igazítás), illetve méretet a paint műveletben a drawdisplay művelettel tudjuk a felületet rajzolni, a drawfocus művelettel pedig rárajzolni a fókuszt ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:11

Egyedi delegáltak létrehozása Pl.: class MyDelegate : public QItemDelegate { void paint(qpainter *painter,, const QModelIndex &index) const { if (index.column() == 2) // kettes oszlopra { // speciális rajzolást végzünk drawdisplay( ); // adat kirajzolása drawfocus( ); // fókusz kirajzolása } else { // a többire az alapértelmezettet QItemDelegate::paint( ); } ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:12

Feladat: Módosítsuk az épületek kezelését úgy, hogy a tengerpart távolságnál a szám után a mértékegységet (méter) is odaírjuk, illetve jelenítsük meg a jellemzőket szám helyett szövegesen ehhez egy egyedi delegált osztályt (BuildingDelegate) származtatunk a QSqlRelationalDelegate-ből, és felüldefiniáljuk a paint műveletet a távolságnak csak hozzá kell vennünk az m szöveget a számhoz, illetve 1 esetén azt írjuk ki, hogy közvetlen a jellemzőknél a számérték alapján fűzzük össze a megjelenítendő szöveget (ehhez bitenként kell feldolgoznunk a számot) ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:13

Tervezés: BuildingDelegate QSqlRelationalDelegate + BuildingDelegate(QObject*) + paint(qpainter*, QStyleOptionViewItem&, QModelIndex&) :void {query} - valuetofeatures(int) :QString {query} BuildingEditorDialog - _tableview :QTableView* - _model :QSqlRelationalTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* - _submitbutton :QPushButton* - _revertbutton :QPushButton* - _cityeditordialog :CityEditorDialog* + BuildingEditorDialog(QWidget*) + ~BuildingEditorDialog() - setupmodel() :void - setupui() :void QDialog «slot» - addbutton_clicked() :void - model_beforeinsert(qsqlrecord&) :void - model_datachanged(qmodelindex&, QModelIndex&) :void - removebutton_clicked() :void - submitbutton_clicked() :void - tableview_doubleclicked(qmodelindex) :void -_cityeditordialog CityEditorDialog QDialog - _listview :QListView* - _model :QSqlTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* + CityEditorDialog(QWidget*) + ~CityEditorDialog() + setmodel(qsqltablemodel*) :void - setupmodel() :void - setupui() :void «slot» - addbutton_clicked() :void - removebutton_clicked() :void ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:14

Megoldás (buildingdelegate.cpp): void BuildingDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { switch (index.column()) { case 4: // tengerpart távolság oszlop QString text; int shoredistance = index.data().toint(); // adat lekérdezése if (shoredistance == 1) text = "közvetlen"; else text = QString::number(shoreDistance) + " m"; ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:15

Megoldás (buildingdelegate.cpp): QStyleOptionViewItem optionviewitem = option; // kiírás módjának beállítása optionviewitem.displayalignment = Qt::AlignRight Qt::AlignVCenter; // jobbra és középre tagolt drawdisplay(painter, optionviewitem, optionviewitem.rect, text); // adat kirajzolása drawfocus(painter, optionviewitem, optionviewitem.rect); // fókusz kirajzolása break; ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:16

Megoldás (buildingdelegate.cpp): default: // alapértelmezett rajzolás QItemDelegate::paint(painter, option, index); break; QString BuildingDelegate::valueToFeatures(int value) const { QString result; if (value % 2 == 1) result += trutf8("főút, "); if ((value >> 1) % 2 == 1) result += trutf8("parti szolgálat, "); ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:17

Egyedi szerkesztőmezők Az egyedi delegált segítségével nem csak a kiírást, de a szerkesztés módját is változtathatjuk az alapértelmezett szerkesztőmezőt tetszőlegesre cserélhetjük a createeditor( ) művelet felelős a szerkesztőmező létrehozásáért, ebben visszaadhatunk egy tetszőleges QWidget leszármazottat, vagyis bármilyen vezérlőt behelyezhetünk szerkesztőnek a seteditordata( ) felelős a szerkesztőmező kitöltéséért, hogy az megfeleljen a modellbeli adatnak a setmodeldata( ) felelős a szerkesztőmezőben történt módosítás visszaírásáért a modellbe ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:18

Feladat: Módosítsuk az épületek kezelését úgy, hogy a tengerpart típust egy legördülő menü segítségével lehessen kijelölni. tengerpart típusok: homokos (0), sziklás (1), kavicsos (2), apró kavicsos (3) módosítjuk a BuildingDelegate osztályt az egyedi vezérlővel, amely QComboBox típusú lesz, ennek elemeit egy konstans lista (shorelist) segítségével töltjük fel, amely tartalmazza a parttípusokat a listában az index segítségével állítjuk a parttípust, így könnyen számolható a legördülő menüben kiválasztott elem (a currentindex segítségével), valamint az adatbázisban visszaírandó érték is ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:19

Tervezés: BuildingDelegate QSqlRelationalDelegate + BuildingDelegate(QObject*) + paint(qpainter*, QStyleOptionViewItem&, QModelIndex&) :void {query} + createeditor(qwidget*, QStyleOptionViewItem&, QModelIndex&) :QWidget * {query} + seteditordata(qwidget*, QModelIndex&) :void {query} + setmodeldata(qwidget*, QAbstractItemModel*, QModelIndex&) :void {query} - shorelist() :QStringList {query} - valuetofeatures(int) :QString {query} BuildingEditorDialog - _tableview :QTableView* - _model :QSqlRelationalTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* - _submitbutton :QPushButton* - _revertbutton :QPushButton* - _cityeditordialog :CityEditorDialog* QDialog -_cityeditordialog CityEditorDialog QDialog - _listview :QListView* - _model :QSqlTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* + BuildingEditorDialog(QWidget*) + ~BuildingEditorDialog() + addbutton_clicked() :void + removebutton_clicked() :void + submitbutton_clicked() :void + tableview_doubleclicked(qmodelindex) :void + model_beforeinsert(qsqlrecord&) :void + model_datachanged(qmodelindex&, QModelIndex&) :void - setupmodel() :void - setupui() :void + CityEditorDialog(QWidget*) + ~CityEditorDialog() + setmodel(qsqltablemodel*) :void + addbutton_clicked() :void + removebutton_clicked() :void - setupmodel() :void - setupui() :void ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:20

Megoldás (buildingdelegate.cpp): QWidget* BuildingDelegate::createEditor( Qwidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.column() == 5) { // a tengerpart oszlopnál legördülő menü QComboBox *shorecombobox = new QComboBox(parent); shorecombobox->additems(shorelist()); // felvesszük a lista által tartalmazott // elemeket return shorecombobox; ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:21

Megoldás (buildingdelegate.cpp): void BuildingDelegate::setEditorData(Qwidget *editor, const QModelIndex &index) const { if (index.column() == 5) { int i = index.data().toint(); QComboBox *shorecombobox = qobject_cast<qcombobox*>(editor); // konverzió szükséges shorecombobox->setcurrentindex(i); // szerkesztőmező elemének beállítása } ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:22

Feladat: Javítsunk a épületek jellemzőinek módosításán úgy, hogy ne egy számot kelljen beírni, hanem egy listából lehessen kiválasztani az érvényes jellemzőket. a jellemzők bináris formában tárolják az épület tulajdonságait (kert, parkoló, ) annak érdekében, hogy a későbbiekben könnyen fel tudjunk venni új tulajdonságokat a táblaszerkezet módosítása nélkül pl.: parti szolgálat kert 9 = 0 1 0 0 1 főút úszómedence saját parkoló ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:23

Tervezés: mivel az adatbázisban továbbra is a szám lesz eltárolva, szükségünk lesz egy egyedi lista vezérlőre (FeatureEditorListWidget), amely a szám-szöveg konverziót (setfeatures, getfeatures), illetve a szöveges formában történő kiírást (getfeaturesstring) elvégzi, és listaszerűen jeleníti meg az adatokat ehhez a QListWidget vezérlőből származtatunk, amelyben lehetőség van az elemek kijelölésére, így közvetlenül tárolhatjuk a jellemzők állapotát az egyedi vezérlőnket a delegált (BuildingDelegate) segítségéhez helyezzük a szerkezetbe ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:24

Tervezés: QListWidget FeatureEditorListWidget BuildingDelegate QSqlRelationalDelegate + FeatureEditorListWidget(QWidget*) + setfeatures(int) :void + getfeatures() :int {query} + getfeaturesstring() :QString {query} + BuildingDelegate(QObject*) + paint(qpainter*, QStyleOptionViewItem&, QModelIndex&) :void {query} + createeditor(qwidget*, QStyleOptionViewItem&, QModelIndex&) :QWidget * {query} + seteditordata(qwidget*, QModelIndex&) :void {query} + setmodeldata(qwidget*, QAbstractItemModel*, QModelIndex&) :void {query} - shorelist() :QStringList {query} BuildingEditorDialog - _tableview :QTableView* - _model :QSqlRelationalTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* - _submitbutton :QPushButton* - _revertbutton :QPushButton* - _cityeditordialog :CityEditorDialog* QDialog -_cityeditordialog CityEditorDialog QDialog - _listview :QListView* - _model :QSqlTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* + BuildingEditorDialog(QWidget*) + ~BuildingEditorDialog() + addbutton_clicked() :void + removebutton_clicked() :void + submitbutton_clicked() :void + tableview_doubleclicked(qmodelindex) :void + model_beforeinsert(qsqlrecord&) :void + model_datachanged(qmodelindex&, QModelIndex&) :void - setupmodel() :void - setupui() :void + CityEditorDialog(QWidget*) + ~CityEditorDialog() + setmodel(qsqltablemodel*) :void + addbutton_clicked() :void + removebutton_clicked() :void - setupmodel() :void - setupui() :void ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:25

Megoldás (featureeditorlistwidget.cpp): void FeatureEditorListWidget::setFeatures(int features) { for (int i = 0; i < 5; i++){ if (((features >> i) % 2 == 1)) // kijelölés beállítása a bit értéke // szerint item(i)->setcheckstate(qt::checked); else item(i)->setcheckstate(qt::unchecked); } } ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:26

Megoldás (featureeditorlistwidget.cpp): int FeatureEditorListWidget::getFeatures() const { int featuresint = 0; for (int i = 0; i < 5; i++) if (item(i)->checkstate() == Qt::Checked) featuresint += pow(2, i); // megfelelő hatványozás a beíráshoz return featuresint; } ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:27

Számított adatok kezelése Lehetőségünk van a modellben a tényleges adatbázisbeli tartalom mellett, vagy helyett tetszőleges számított adat megjelenítésére ehhez egy új, speciális modellt kell származtatnunk, amelyben felüldefiniáljuk az adatlekérdezést végző data(<index>, <szerep>) metódust, amelyben a pozíció (index) alapján pontosan megállapíthatjuk a megjeleníteni kívánt adatot az oszlopok számát megadó columncount() metódust, ahol általában növeljük az értéket mindkét műveletben tovább hívhatjuk az ősbeli örökölt műveletet, így az eredeti viselkedést is visszakaphatjuk ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:28

Számított adatok kezelése Pl.: class MyTableModel : public QSqlTableModel { Qvariant data(const QModelIndex&, int) const; int columncount() const; }; QVariant MyTableModel::data(const QModelIndex& index, int role) const { if (index.column() == 6) // ha a számított oszlopban vagyunk // kiszámítjuk az értéket else // különben az ősbeli értéket adjuk vissza return QSqlTableModel::data(index, role); } ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:29

Számított adatok kezelése int MyTableModel::columnCount() const { return QSqlTableModel::columnCount() + 1; // egy oszloppal bővítettük a táblát } A data metódusban szerep (role) paraméter állapítja meg, milyen információ lekérdezése kapcsán hívták meg a műveletet, a leggyakoribb szerepek: Qt::DisplayRole: a modell által megjelenített érték (amelyet tovább változtathatunk a delegáltban) Qt::EditRole: a szerkesztett érték, amely általában megegyezik a megjelenítettel (meghatározott esetekben különbözhet, pl. relációk esetén) ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:30

Számított adatok kezelése Qt::ToolTipRole: előugró üzenet Qt::CheckStateRole: az adott elem kijelölési állapota (lehet kijelölt, kijelöletlen), ennek használatával a cella alapértelmezetten kijelölő mezőként fog megjelenni a nézetben Qt::SizeHintRole: szabályozza a megjelenítendő cella méretét, egyedi szerkesztőmezők esetén módosítható Qt::TextAligmentRole: szövegigazítás az adathoz Qt::ForegroundRole, Qt::BackgroundRole, Qt::TextColorRole, : különböző megjelenítési beállítások, amelyek szabályozhatóak a modell szintjén, illetve a delegált szintjén is ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:31

Számított adatok kezelése Pl.: QVariant MyTableModel::data( ) const { if (index.column() == 6){ switch (role){ case Qt::TestAlignmentRole: // igazítás return QVariant(Qt::AlignLeft Qt::AlignVCenter); case Qt::DisplayRole: case Qt::EditRole: // megjelenítendő adat return ; case Qt:ToolTipRole: // előugró üzenet return QVariant("You cannot modify this!"); ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:32

Feladat: Egészítsük ki az épületek táblát három számított oszloppal, az épületben lévő apartmanok számával, valamint a minimális, és maximális árral. származtatunk a relációs modellből egy egyedi modellt (BuildingTableModel), amelyben felüldefiniáljuk az adatlekérdezést, az oszlopok számát, illetve az új sor beszúrását (az alapértelmezett érékek beszúrása végett) a három új értéket megfelelő lekérdezések segítségével hozzuk létre (pl. ár esetén a apartment és a price tábla alapján) a delegált osztályban az árak megjelenítését kiegészítjük a pénznem megjelölésével is ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:33

Tervezés (adatbázis): ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:34

Tervezés (alkalmazás): QSqlRelationalTableModel BuildingTableModel + BuildingTableModel(QObject*) + insertrow(int) :void + data(qmodelindex&, int) :QVariant {query} + columncount(qmodelindex&) :int {query} + onbeforeinsert(qsqlrecord&) :void + ondatachanged(qmodelindex&, QModelIndex&) :void -_model BuildingDelegate QSqlRelationalDelegate + BuildingDelegate(QObject*) + paint(qpainter*, QStyleOptionViewItem&, QModelIndex&) :void {query} + createeditor(qwidget*, QStyleOptionViewItem&, QModelIndex&) :QWidget * {query} + seteditordata(qwidget*, QModelIndex&) :void {query} + setmodeldata(qwidget*, QAbstractItemModel*, QModelIndex&) :void {query} - shorelist() :QStringList {query} BuildingEditorDialog - _tableview :QTableView* - _model :BuildingTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* - _submitbutton :QPushButton* - _revertbutton :QPushButton* - _cityeditordialog :CityEditorDialog* QDialog + BuildingEditorDialog(QWidget*) + ~BuildingEditorDialog() + addbutton_clicked() :void + removebutton_clicked() :void + submitbutton_clicked() :void + tableview_doubleclicked(qmodelindex) :void - setupui() :void -_cityeditordialog CityEditorDialog QDialog - _listview :QListView* - _model :QSqlTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* + CityEditorDialog(QWidget*) + ~CityEditorDialog() + setmodel(qsqltablemodel*) :void + addbutton_clicked() :void + removebutton_clicked() :void - setupmodel() :void - setupui() :void QListWidget FeatureEditorListWidget + FeatureEditorListWidget(QWidget*) + setfeatures(int) :void + getfeatures() :int {query} + getfeaturesstring() :QString {query} ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:35

Megoldás (buildingtablemodel.cpp): QVariant BuildingTableModel::data(const QModelIndex &index, int role) const { if (!index.isvalid()) return QVariant(); // ha nem érvényes az index, üres adatot // adunk vissza if (index.column() >= 8 && index.column() <= 10 && role == Qt::TextAlignmentRole ) // szövegigazítás return QVariant(Qt::AlignRight Qt::AlignVCenter); ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:36

Megoldás (buildingtablemodel.cpp): if (index.column() == 8 && ( role == Qt::DisplayRole role == Qt::EditRole)) { // apartmanok számának számítása QSqlQuery query; query.exec("select count(*) from apartment where building_id = " + this->data( this->index(index.row(), 0)).toString()); if (query.next()) return QVariant(query.value(0).toInt()); else return QVariant(0); ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:37

Számított adatok szerkesztése A táblamodell nem csak a számított adatok lekérdezését, de szerkesztését is lehetővé teszi az adatok szerkesztését specializálhatjuk a setdata(<index>, <érték>, <szerep>) művelet felüldefiniálásával, amelyben megadhatjuk a számított adatok módosításának tényleges tevékenységét a számított oszlopot a szerkesztés előtt szerkeszthetővé kell tenni, ehhez felül kell definiálni az oszlopok állapotjelzőit visszaadó flags(<index>) műveletet a számított adott oszlopnak kiválaszthatónak (ItemIsSelectable) és szerkeszthetőnek (ItemIsEditable) kell lennie ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:38

Számított adatok szerkesztése Pl.: class MyTableModel : public QSqlTableModel { bool setdata(const QModelIndex&, const QVariant&, int); Qt::ItemFlags flags(const QModelIndex&) const; }; Qt::ItemFlags MyTableModel::flags(const QModelIndex&) const { if (<számított oszlopban vagyunk>) return Qt::ItemIsEditable } ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:39

Feladat: Egészítsük ki az épületek táblát egy állapot oszloppal, amely jelöli, hogy van-e tatarozás az épületben. Az állapot normál, ha mindegyik apartman kiadható, lezárt, ha mindegyik apartman tatarozás alatt van, egyébként felújítás alatt. Lehessen állítani az értéket úgy, hogy normál, vagy lezárt állapotba tudjuk helyezni az épületet. felveszünk a számított oszlopot, amely az adatot a apartmanok táblából gyűjti a megjelenítéshez egy legördülő menüt használunk, amely csak két értéket kap meg, nem mind a hármat felüldefiniáljuk az adatbeállítást, ahol az értékeket az apartman táblába írjuk ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:40

Tervezés: QSqlRelationalTableModel BuildingTableModel + BuildingTableModel(QObject*) + insertrow(int) :void + flags(qmodelindex&) :Qt::ItemFlags {query} + columncount(qmodelindex&) :int {query} + data(qmodelindex&, int) :QVariant {query} + setdata(qmodelindex&, QVariant&, int) :bool + onbeforeinsert(qsqlrecord&) :void + ondatachanged(qmodelindex&, QModelIndex&) :void -_model BuildingDelegate QSqlRelationalDelegate + BuildingDelegate(QObject*) + paint(qpainter*, QStyleOptionViewItem&, QModelIndex&) :void {query} + createeditor(qwidget*, QStyleOptionViewItem&, QModelIndex&) :QWidget * {query} + seteditordata(qwidget*, QModelIndex&) :void {query} + setmodeldata(qwidget*, QAbstractItemModel*, QModelIndex&) :void {query} - shorelist() :QStringList {query} BuildingEditorDialog - _tableview :QTableView* - _model :BuildingTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* - _submitbutton :QPushButton* - _revertbutton :QPushButton* - _cityeditordialog :CityEditorDialog* QDialog + BuildingEditorDialog(QWidget*) + ~BuildingEditorDialog() + addbutton_clicked() :void + removebutton_clicked() :void + submitbutton_clicked() :void + tableview_doubleclicked(qmodelindex) :void - setupui() :void -_cityeditordialog CityEditorDialog QDialog - _listview :QListView* - _model :QSqlTableModel* - _buttonbox :QDialogButtonBox* - _addbutton :QPushButton* - _removebutton :QPushButton* + CityEditorDialog(QWidget*) + ~CityEditorDialog() + setmodel(qsqltablemodel*) :void + addbutton_clicked() :void + removebutton_clicked() :void - setupmodel() :void - setupui() :void QListWidget FeatureEditorListWidget + FeatureEditorListWidget(QWidget*) + setfeatures(int) :void + getfeatures() :int {query} + getfeaturesstring() :QString {query} ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:41

Megoldás (buildingtablemodel.cpp): Qt::ItemFlags BuildingTableModel::flags(const QModelIndex& index) const { Qt::ItemFlags flag = QSqlTableModel::flags(index); // lekérdezzük az alap állapotjelzőt if (index.column() == 4) // a negyedik oszlop számított flag = Qt::ItemIsSelectable Qt::ItemIsEditable; // szerkeszthetővé tesszük } return flag; ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:42

Megoldás (buildingtablemodel.cpp): bool BuildingTableModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (index.column() == 4) { if (value.toint() == 0) { // az appartment táblát kell módosítanunk QSqlQuery query; return (query.exec("update appartment set renovation = 0 where building_id = " + this->data(this->index(index.row(), 0)).toString())); ELTE IK, Eseményvezérelt alkalmazások fejlesztése I 11:43