QML and QSqlTableModel: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 1: Line 1:
=<span class="caps">QML</span> and QSqlTableModel=
[[Category:snippets]]<br />[[Category:Developing_with_Qt::Qt Quick::Tutorial]]


I wrote a simple class derived from QSqlRelationalTableModel to facilitate the use of such classes with <span class="caps">QML</span>, without manually defining the roles.
= QML and QSqlTableModel =


If you want to understand why roles are so important when working with <span class="caps">SQL</span> table models and <span class="caps">QML</span>, have a look at [[How to use a QSqlQueryModel in QML|this explained code snippet]] ''[qt.io]''
I wrote a simple class derived from QSqlRelationalTableModel to facilitate the use of such classes with QML, without manually defining the roles.


The data method returns the value of the role used. If there is a relationship in the table, i search the column with relation and return the correct value.. Note that empty string is returned when the item is not found and not QVariant value, in order to have a correct visualization in <span class="caps">QML</span>.
If you want to understand why roles are so important when working with SQL table models and QML, have a look at &quot;this explained code snippet&amp;quot;:http://wiki.qt.io/How_to_use_a_QSqlQueryModel_in_QML
 
<code>
 
class QLSqlTableModel : public QSqlRelationalTableModel<br />{<br /> Q_OBJECT<br />private:<br /> QHash&amp;lt;int, QByteArray&amp;gt; roles;
 
public:<br /> QLSqlTableModel(QObject *parent = 0);<br /> ~QLSqlTableModel();<br /> Q_INVOKABLE QVariant data(const QModelIndex &amp;index, int role=Qt::DisplayRole ) const;<br /> void generateRoleNames();<br />#ifdef HAVE_QT5<br /> virtual QHash&amp;lt;int, QByteArray&amp;gt; roleNames() const{return roles;}<br />#endif<br />}
 
QVariant QLSqlTableModel::data ( const QModelIndex &amp; index, int role ) const<br />{<br /> if(index.row() &gt;= rowCount())<br /> return QString(&quot;&quot;);<br /> }<br /> if(role &lt; Qt::UserRole)<br /> {<br /> return QSqlQueryModel::data(index, role);<br /> }<br /> else {<br /> // search for relationships<br /> for (int i = 0; i &lt; columnCount(); i+'') {<br /> if (this-&gt;relation(i).isValid()) {<br /> return record(index.row()).value(QString(roles.value(role)));<br /> }<br /> }<br /> // if no valid relationship was found<br /> return QSqlQueryModel::data(this-&gt;index(index.row(), role - Qt::UserRole - 1), Qt::DisplayRole);<br /> }
<br /></code>
<br />The data method returns the value of the role used. If there is a relationship in the table, i search the column with relation and return the correct value.. Note that empty string is returned when the item is not found and not QVariant value, in order to have a correct visualization in QML.
<br /><code><br />void QLSqlTableModel::generateRoleNames()<br />{<br /> roles.clear();<br /> int nbCols = this-&gt;columnCount();<br /> for (int i = 0; i &lt; nbCols; i) {<br /> roles[Qt::UserRole'' i + 1] = QVariant(this-&gt;headerData(i, Qt::Horizontal).toString()).toByteArray();
 
}<br />#ifndef HAVE_QT5<br /> setRoleNames(roles);<br />#endif<br />}
 
</code>


The generateRoleNames method creates the roles called as the table columns specified in the header.
The generateRoleNames method creates the roles called as the table columns specified in the header.
Line 12: Line 27:


Tables:
Tables:
<code><br />query.exec&amp;amp;#40;&quot;create table IF NOT EXISTS items (id integer primary key autoincrement,<br />name varchar(15&amp;amp;#41;, descr varchar(30))&quot;);<br /> query.exec&amp;amp;#40;&quot;create table IF NOT EXISTS lista (id integer primary key autoincrement,<br />qta varchar(30&amp;amp;#41;, item INTEGER, FOREIGN KEY (item) REFERENCES items(id))&quot;);<br /></code>


main.cpp
main.cpp


In qml file<br />
<code><br />QLSqlTableModel *model = new QLSqlTableModel;<br /> QLSqlTableModel *modelLista = new QLSqlTableModel;<br /> model-&gt;setTable(&quot;items&amp;quot;);<br /> model-&gt;generateRoleNames();<br /> model-&gt;select();<br /> modelList-&gt;setTable(&quot;lists&amp;quot;);<br /> modelList-&gt;setRelation(2, QSqlRelation(&quot;items&amp;quot;, &quot;id&amp;quot;, &quot;name&amp;quot;));<br /> modelList-&gt;select();<br /> modelList-&gt;generateRoleNames();<br /> QDeclarativeContext *ctxt = view.rootContext();<br /> ctxt-&gt;setContextProperty(&quot;modelListItems&amp;quot;, model);<br /> ctxt-&gt;setContextProperty(&quot;modelList&amp;quot;, modelLista);
 
</code>


——————————————————-<br /> Note1:<br /> Nice post, however the performance can be tweaked. data() will be called very often. Most of the processing and object instantiation should be done only once.
In qml file<br /><code><br />Text {<br /> id: name<br /> text: model.name<br /> font.bold: true; font.pointSize: 16<br /> color: &quot;white&amp;quot;<br /> }<br /> Text {<br /> text: &quot;Amount: &quot; + model.qta<br /> font.pointSize: 16<br /> opacity: 1<br /> color: &quot;white&amp;quot;<br /> }<br /></code>


Note2:<br /> I modified provided code according to [http://stackoverflow.com/questions/14613824/qsqltablemodel-inheritor-and-qtableview this working example] ''[stackoverflow.com]'' which was based on this wiki page


===Categories:===
-----


* [[:Category:Developing with Qt|Developing_with_Qt]]
Note1:<br />Nice post, however the performance can be tweaked. data() will be called very often. Most of the processing and object instantiation should be done only once.
** [[:Category:Developing with Qt::Qt-Quick|Qt Quick]]
* [[:Category:Developing with Qt::Qt-Quick::Tutorial|Tutorial]]


* [[:Category:snippets|snippets]]
Note2:<br />I modified provided code according to &quot;this working example&amp;quot;:http://stackoverflow.com/questions/14613824/qsqltablemodel-inheritor-and-qtableview which was based on this wiki page

Revision as of 14:44, 23 February 2015


QML and QSqlTableModel

I wrote a simple class derived from QSqlRelationalTableModel to facilitate the use of such classes with QML, without manually defining the roles.

If you want to understand why roles are so important when working with SQL table models and QML, have a look at "this explained code snippet&quot;:http://wiki.qt.io/How_to_use_a_QSqlQueryModel_in_QML

class QLSqlTableModel : public QSqlRelationalTableModel<br />{<br /> Q_OBJECT<br />private:<br /> QHash&amp;lt;int, QByteArray&amp;gt; roles;

public:<br /> QLSqlTableModel(QObject *parent = 0);<br /> ~QLSqlTableModel();<br /> Q_INVOKABLE QVariant data(const QModelIndex &amp;index, int role=Qt::DisplayRole ) const;<br /> void generateRoleNames();<br />#ifdef HAVE_QT5<br /> virtual QHash&amp;lt;int, QByteArray&amp;gt; roleNames() const{return roles;}<br />#endif<br />}

QVariant QLSqlTableModel::data ( const QModelIndex &amp; index, int role ) const<br />{<br /> if(index.row() &gt;= rowCount())<br /> return QString(&quot;&quot;);<br /> }<br /> if(role &lt; Qt::UserRole)<br /> {<br /> return QSqlQueryModel::data(index, role);<br /> }<br /> else {<br /> // search for relationships<br /> for (int i = 0; i &lt; columnCount(); i+'') {<br /> if (this-&gt;relation(i).isValid()) {<br /> return record(index.row()).value(QString(roles.value(role)));<br /> }<br /> }<br /> // if no valid relationship was found<br /> return QSqlQueryModel::data(this-&gt;index(index.row(), role - Qt::UserRole - 1), Qt::DisplayRole);<br /> }
<br />


The data method returns the value of the role used. If there is a relationship in the table, i search the column with relation and return the correct value.. Note that empty string is returned when the item is not found and not QVariant value, in order to have a correct visualization in QML.


<br />void QLSqlTableModel::generateRoleNames()<br />{<br /> roles.clear();<br /> int nbCols = this-&gt;columnCount();<br /> for (int i = 0; i &lt; nbCols; i) {<br /> roles[Qt::UserRole'' i + 1] = QVariant(this-&gt;headerData(i, Qt::Horizontal).toString()).toByteArray();

}<br />#ifndef HAVE_QT5<br /> setRoleNames(roles);<br />#endif<br />}

The generateRoleNames method creates the roles called as the table columns specified in the header.

Example:

Tables:

<br />query.exec&amp;amp;#40;&quot;create table IF NOT EXISTS items (id integer primary key autoincrement,<br />name varchar(15&amp;amp;#41;, descr varchar(30))&quot;);<br /> query.exec&amp;amp;#40;&quot;create table IF NOT EXISTS lista (id integer primary key autoincrement,<br />qta varchar(30&amp;amp;#41;, item INTEGER, FOREIGN KEY (item) REFERENCES items(id))&quot;);<br />

main.cpp

<br />QLSqlTableModel *model = new QLSqlTableModel;<br /> QLSqlTableModel *modelLista = new QLSqlTableModel;<br /> model-&gt;setTable(&quot;items&amp;quot;);<br /> model-&gt;generateRoleNames();<br /> model-&gt;select();<br /> modelList-&gt;setTable(&quot;lists&amp;quot;);<br /> modelList-&gt;setRelation(2, QSqlRelation(&quot;items&amp;quot;, &quot;id&amp;quot;, &quot;name&amp;quot;));<br /> modelList-&gt;select();<br /> modelList-&gt;generateRoleNames();<br /> QDeclarativeContext *ctxt = view.rootContext();<br /> ctxt-&gt;setContextProperty(&quot;modelListItems&amp;quot;, model);<br /> ctxt-&gt;setContextProperty(&quot;modelList&amp;quot;, modelLista);

In qml file

<br />Text {<br /> id: name<br /> text: model.name<br /> font.bold: true; font.pointSize: 16<br /> color: &quot;white&amp;quot;<br /> }<br /> Text {<br /> text: &quot;Amount: &quot; + model.qta<br /> font.pointSize: 16<br /> opacity: 1<br /> color: &quot;white&amp;quot;<br /> }<br />



Note1:
Nice post, however the performance can be tweaked. data() will be called very often. Most of the processing and object instantiation should be done only once.

Note2:
I modified provided code according to "this working example&quot;:http://stackoverflow.com/questions/14613824/qsqltablemodel-inheritor-and-qtableview which was based on this wiki page