TIE-11300 Tietotekniikan vaihtuva-alainen kurssi Graafisen käyttöliittymän ohjelmointi Syksy 2013 Luento 9 Qt model/view Juha-Matti Vanhatupa
Sisältö Qt:n MV mallin osat Mallin ja näkymän välinen kommunikointi Osien rajapinnat Standard item model Valintamalli (selection model) Datan suodatus (Proxy model)
Yleistä Perinteisestä MVC-mallista poiketen Qt:n model/view:ssä ei ole kontrolleria. Lisäksi käytössä on delegaatit.
Malli Käyttäytyy samoin kuin MVC:n malli Tarjoaa rajapinnan datan käsittelyyn. Joko säilöö sovelluksen datan itse tai kommunikoi varsinaisen säilytyspaikan (esim. tietokannan) kanssa.
Näkymä Toteuttaa yleisen layoutin, navigoinnin item:ien välillä ja datan valinnan. Valmiita näkymäluokkia: esim. ListView ja TableView Yhteen malliin voi liittyä useita eri näkymiä (tarkkailija-suunnittelumalli) Sisältää perinteisen MVC-mallin kontrollerin tehtäviä (tapahtumankäsittely)
Delegaatti Toteuttaa näkymän yksittäisen item:n ulkoasun ja niiden editoinnin Qt tarjoaa oletustoteutukset delegaateille - käytettävä delegaatti voidaan kysyä View luokilta itemdelegate() funktiolla. Oletusdelegaatti riittävä useimmille sovelluksille
Mallin ja näkymän välinen kommunikointi Osat toteuttavat valmiiksi määritellyt rajapinnat QAbstractItemModel QAbstractItemView QAbstractItemDelegate Kommunikointi tapahtuu signaalien avulla Signaalit mallilta informoivat näkymää mallin muutoksista (tarkkailija-suunnittelumalli) Signaalit näkymältä kertovat käyttäjän toimista näytetyille item:eille Signaaleita delegaatilta käytetään kertomaan mallille ja näkymälle editorin tilasta editoinnin aikana
QAbstractItemModel QAbstractItemModel rajapinta ei ota kantaa mallin rakenteeseen.
QAbstractItemModel Standardi rajapinta, jonka kautta näkymät käyttävät mallin dataa Esittää datan hierarkisena taulukkorakenteena Malli tiedottaa näkymää muutoksistaan signalslot mekanismin avulla (tarkkailija-malli).
Mallin ja näkymän välinen kommunikointi Dataan viitataan mallin indeksien avulla QModelIndex Dataa käsitellään variantteina QVariant
QModelIndex Tietorakenne, jolla viitataan mallin dataan - Sisältää pointterin indeksin luoneeseen malliin. Näkymä, delegaatit ja (valintamallit) käsittelevät mallin dataa näiden indeksien avulla (QModelIndex)
QModelIndex QModelIndex luodaan antamalla halutun rivin ja sarakkeen numero mallin index()-funktiolle. Index() -funktion kolmas parametri on parent-indeksi. Malleille joissa vain sarakkeita ja rivejä on parent aina QModelIndex(). QModelIndex:t on tarkoitettu käytettäväksi heti. Ne hajoavat jos mallin rakenne muuttuu. - QPersistentModelIndex QModelIndex indexa = model->index(0, 0, QModelIndex()); QModelIndex indexb = model->index(1, 1, QModelIndex()); QModelIndex indexc = model->index(2, 1, QModelIndex());
QVariant Malli ja näkymä käsittelevät dataa varianttyyppeinä. Qt:n tietotyypit voidaan muuntaa varianttyyppisiksi Myös osa Qt:n tietorakenteista QList, QMap ja QHash voidaan tallentaa varianttiin. Oletusrakentaja generoi Null-variantin QVariant v(123); int x = v.toint();
QVariant Variantti sisältää yleensä yhden arvon (esim int, string), mutta myös multi-variantit ovat mahdollisia QVariantList = QList<QVariant> QVariantList vlist; QVariant v(vlist);
Metatyypin rekisteröinti Myös omia tietotyyppejä voidaan muuttaa variant muotoon, kunhan ne rekisteröidään metaobject-järjestelmään. struct MyStruct { int i;... }; Q_DECLARE_METATYPE(MyStruct) MyStruct s; QVariant var; var.setvalue(s);
Datan lukeminen variantista Perustyypit voidaan muuttaa to-metodeilla (esim v.toint()) Muut tyypit template metodilla int i = var.value<int>(); MyCustomStruct c; if (v.canconvert<mycustomstruct>()) { c = v.value<mycustomstruct>(v); }
Mallin toteutus Käyttötarpeesta riippuen malli voidaan myös toteuttaa seuraavien luokkien avulla: QAbstractListModel (vain rowcount ja data) QAbstractTableModel (rowcount, columncount, data) Tai käyttää kirjaston valmista QStandardItemModel-luokkaa
QAbstractItemView Ylimääriteltävät pure virtual funktiot indexat(const QPoint point) Kertoo mikä itemi on koordinaattien kohdalla scrollto Toteuttaa ikkunan vierityksen QRect visualrect Kertoo itemin vievän tilan ruudulla Valmiit näkymät usein riittäviä QListView QTableView QTreeView
QAbstractItemDelegate Ylimääriteltävät pure virtual funktiot paint Piirtää itemin ruudulle sizehint Palauttaa itemin korkeuden ja leveyden Oletustoteutus QItemDelegate
Standardi-malli QstandardItemModel - Geneerinen malli - Toteuttaa QAbstactItemModel rajapinnan QStandardItem - Item, joita voidaan lisätä standard modeliin
QStandardItem Sisältää variant tyyppistä dataa QVariant QStandardItem::data ( int role = Qt::UserRole + 1 ) const void QStandardItem::setData ( const QVariant & value, int role = Qt::UserRole + 1 ) void QStandardItem::setFlags ( Qt::ItemFlags flags ) Qt::NoItemFlags Qt::ItemIsSelectable Qt::ItemIsEditable Qt::ItemIsDragEnabled Qt::ItemIsDropEnabled Qt::ItemIsUserCheckable Qt::ItemIsEnabled Qt::ItemIsTristate
Role arvo Määrittelee mitä tietoa ollaan hakemassa Qt::ItemDataRole Qt::DisplayRole (näytettävä teksti) Qt::DecorationRole (ikoni) Qt::ToolTipRole (toltipteksti) Qt::StatusTipRole (status palkissa näytettävä teksti) Qt::WhatsThisRole (pikaohje) QVariant data(qmodelindex ind, int role);
Omien role-arvojen määrittäminen #define NAME_ROLE Qt::UserRole+1; #define DIRECTOR_ROLE Qt::UserRole+2; #define PRODUCER_ROLE Qt::UserRole+3; #define WRITER_ROLE Qt::UserRole+4; class CMovie { public: QString name() const; QString director() const; QString producer() const; QString writer() const ; QStringList actorlist() const; }; class CMovieModel { QList<CMovie> m_data; }; modeliin
Omien role-arvojen määrittäminen modeliin QVariant CMovieModel::data(QModelIndex ind, int role) { QVariant result; if(ind.isvalid()) { switch(role) { case Qt::DisplayRole: case NAME_ROLE : result = QVariant( m_data[ind.row()].name() ); break; case WRITER_ROLE : result = QVariant( m_data[ind.row()].writer() ); break; case DIRECTOR_ROLE : result = QVariant( m_data[ind.row()].director() ); break; } } } return result;
QItemSelectionModel Pitää kirjaa valituista item:eistä Liittyy yhteen modeliin, mutta voidaan antaa usealle näkymälle Valmiit näkymäluokat tarjoavat default selectionmodel:n, joka voidaan kysyä selectionmodel() -funktiolla.
QItemSelectionModel Valintamalli voidaan myös asettaa näkymälle kutsumalla setselectionmodel(). Hyödyllinen kun halutaan pitää usean näkymän valitut item:it synkronoituina.
Datan suodatus Suodatuksella voidaan rajata näkymässä esitettävää dataa
Filter Käyttötarkoituksia: Näyttää vain osan mallin datasta käyttäjälle Järjestää datan alkuperäisestä poikkeavaan järjestykseen Toteuttaa saman rajapinnan kuin model (QAbstractItemModel)
QAbstractProxyModel Toteutettava rajapinta: QModelIndex mapfromsource(qmodelindex source) QModelIndex maptosource(qmodelindex source) Peritty QAbstractItemModel kantaluokasta
QSortFilterProxyModel QTreeView *treeview = new QTreeView; MyItemModel *sourcemodel = new MyItemModel(this); QSortFilterProxyModel *proxymodel = new QMySortFilterProxyModel(this); proxymodel->setsourcemodel(sourcemodel); treeview->setmodel(proxymodel);
Omien filterien teko Periyttämällä QSortFilterProxyModel tai QAbstractProxyModel filteracceptsrow() funktio kertoo tuleeko parametrina annettu rivi sisällyttää malliin. - vastaavasti filteracceptscolumn() Oletuksena vertailee item:in Qt:DisplayRole arvoa. lessthan funktio toimii < -operaattorina järjestettäessä item:eitä.