<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>C++ on Gryt</title><link>https://gryt.io/tags/c++/</link><description>Recent content in C++ on Gryt</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>robin@gryt.io (Robin Penea)</managingEditor><webMaster>robin@gryt.io (Robin Penea)</webMaster><lastBuildDate>Thu, 25 Oct 2018 15:00:12 +0200</lastBuildDate><atom:link href="https://gryt.io/tags/c++/index.xml" rel="self" type="application/rss+xml"/><item><title>Qt Model / View</title><link>https://gryt.io/posts/understanding-qt-modelview-read/</link><pubDate>Thu, 25 Oct 2018 15:00:12 +0200</pubDate><author>robin@gryt.io (Robin Penea)</author><guid>https://gryt.io/posts/understanding-qt-modelview-read/</guid><description>The Shock The first time I&amp;rsquo;ve read the Qt Model / View documentation, I was shocked. Flabbergasted. Blown away. I started with a vague idea of the purpose of the Model / View, and finished convinced that I understood even less. My first implementation of the pattern was an utter failure: it looked like a Frankenstein implementation of a boilerplate code written by a crazy monkey. This was not right, the Qt documentation is known to be of quality — detailed, explanatory and coherent.</description><content>&lt;h2 id="the-shock">The Shock&lt;/h2>
&lt;p>&lt;strong>The first time I&amp;rsquo;ve read the &lt;a href="http://doc.qt.io/qt-5/model-view-programming.html">Qt Model / View documentation&lt;/a>, I was shocked. Flabbergasted. Blown away. I started with a vague idea of the purpose of the Model / View, and finished convinced that I understood even less. My first implementation of the pattern was an utter failure: it looked like a Frankenstein implementation of a boilerplate code written by a crazy monkey. This was not right, the Qt documentation is known to be of quality — detailed, explanatory and coherent&lt;/strong>.&lt;/p>
&lt;p>After multiple attempts and many hours reading and re-reading the doc, I started to grasp the concept. The deep understanding came when I had to write about this topic. Heck, I&amp;rsquo;ve written &lt;a href="https://www.amazon.com/Mastering-Qt-stunning-cross-platform-applications/dp/1786467127/">whole chapters&lt;/a> on the Model / View!&lt;/p>
&lt;p>I entertain myself imagining how this marathon-length documentation came to be:&lt;/p>
&lt;blockquote>
&lt;p>A Qt framework developer glances over the Model / View documentation and utters to himself &lt;strong>&amp;ldquo;This is not right. It makes no sense at all&amp;rdquo;&lt;/strong>. He then pounds on his keyboard in a sweated rush of the documentation-muse inspiration. He looks at his masterpiece and proudly says &lt;strong>&amp;ldquo;It&amp;rsquo;s now much clearer! Let&amp;rsquo;s add my stone to the cathedral and update the official doc&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;/blockquote>
&lt;p>After several iterations of this episode, the current doc now takes longer to read than The Lord Of the Rings. And boy, it&amp;rsquo;s a long story! Don&amp;rsquo;t get me wrong, the documentation is exhaustive in the deepest sense of exhaustiveness. But, it&amp;rsquo;s also exhausting when you discover the Model / View pattern. The underlying principle is drown in a plethora of details which are useless at the beginning.&lt;/p>
&lt;p>This article aims for exactly that, &lt;strong>understanding the Model / View pattern with a simple example&lt;/strong>. I won&amp;rsquo;t cover all the bells and whistles that you can implement with Model / View.&lt;/p>
&lt;h2 id="tldr--show-me-the-code">TL;DR — Show me the code!&lt;/h2>
&lt;p>You just want the source code to understand all by yourself? Everything is available on &lt;a href="https://github.com/synapticvoid/sample-qt-model-view">GitHub&lt;/a>. Don&amp;rsquo;t worry, it&amp;rsquo;s less than 150 lines of C++.&lt;/p>
&lt;h2 id="the-goal">The Goal&lt;/h2>
&lt;p>The goal is simple: build a simple Model / View example of a list of countries. It will be a read-only Model, no editing to keep things really simple (the edition will be covered in a separate post). We&amp;rsquo;ll display a list of countries and upon a country selection, a country details widget will be updated.&lt;/p>
&lt;figure class="left" >
&lt;img src="https://gryt.io/img/qt-modelview-read/model-view-read-countries.png"
onclick="openLightbox('\/img\/qt-modelview-read\/model-view-read-countries.png')"
style="cursor: pointer;" />
&lt;figcaption class="center" >The final Model / View application&lt;/figcaption>
&lt;/figure>
&lt;p>A country is composed of 3 pieces of data:&lt;/p>
&lt;ul>
&lt;li>Name&lt;/li>
&lt;li>Flag&lt;/li>
&lt;li>Capital&lt;/li>
&lt;/ul>
&lt;h2 id="the-principle">The Principle&lt;/h2>
&lt;p>In my mind, the Model / View has 2 main goals:&lt;/p>
&lt;ol>
&lt;li>Cleanly separate the model&amp;rsquo;s data source from the display. This makes the update of the data source less prone to impact the View side.&lt;/li>
&lt;li>Leverage the Qt signal / slot mechanism to update multiple views from a unified data source.&lt;/li>
&lt;/ol>
&lt;p>Here&amp;rsquo;s a simplified diagram of the Model / View architecture:&lt;/p>
&lt;figure class="left" >
&lt;img src="https://gryt.io/img/qt-modelview-read/model-view.svg"
onclick="openLightbox('\/img\/qt-modelview-read\/model-view.svg')"
style="cursor: pointer;" />
&lt;figcaption class="center" >Model / View architecture diagram&lt;/figcaption>
&lt;/figure>
&lt;ul>
&lt;li>&lt;strong>You feed the Model with your data source&lt;/strong>. It can be a CSV file, rows from a database query or the result of an HTTP request. The &lt;em>Model&lt;/em> name is misleading, it actually handles your &lt;em>model classes&lt;/em>. In our example, we&amp;rsquo;ll create a &lt;code>CountryModel&lt;/code> that will be the owner of a &lt;code>Country&lt;/code> list. The real data is in the &lt;code>Country&lt;/code> class, the &lt;code>CountryModel&lt;/code> just loads it and makes it available for potential clients.&lt;/li>
&lt;li>&lt;strong>The data is provided to the View through the Model&lt;/strong>. The View can be a Qt type : &lt;code>QListView&lt;/code>, or &lt;code>QTableView&lt;/code>. It really depends on what your model can offer (rows and/or columns) and what type of display your want. To enforce the separation, the format is completely domain agnostic. Here, there&amp;rsquo;s no &lt;code>Country&lt;/code> class at all, only a generic bundle. We&amp;rsquo;ll come back soon to this.&lt;/li>
&lt;li>&lt;strong>The user interacts with the View to produce events&lt;/strong> — select a row, delete a row, etc. Each event triggers an exchange between the View and the Model. The user wants to delete a row? Tell the Model about it and wait for the result with a slot.&lt;/li>
&lt;/ul>
&lt;p>The beauty of this architecture is that it fulfills our 2 goals:&lt;/p>
&lt;ol>
&lt;li>The data source can be completely changed from CSV values to Database queries, the View would not have any idea about it.&lt;/li>
&lt;li>Because the Model provides signals and slots, we can even connect multiple Views on a single Model. Each View will connect to the Model&amp;rsquo; slots and get any update.&lt;/li>
&lt;/ol>
&lt;h2 id="the-model">The Model&lt;/h2>
&lt;p>The code is done inside a Qt Widget project. We&amp;rsquo;ll start the basic build block — the &lt;code>Country.h&lt;/code> class:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;QString&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">Country&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QString&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QString&lt;/span> &lt;span class="n">capital&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QString&lt;/span> &lt;span class="n">flagIcon&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Country&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">QString&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">QString&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">capital&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">QString&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">flagIcon&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">capital&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">capital&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">flagIcon&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">flagIcon&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;p>The &lt;code>flagIcon&lt;/code>is the path to the PNG icon stored in a &lt;code>.qrc&lt;/code> file, nothing fancy. The real deal starts with &lt;code>CountryModel.h&lt;/code>, the owner of a &lt;code>Country&lt;/code> list:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">CountryModel&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">public&lt;/span> &lt;span class="n">QAbstractListModel&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Q_OBJECT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">enum&lt;/span> &lt;span class="nc">CountryRoles&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CapitalRole&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Qt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UserRole&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CountryModel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QObject&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">parent&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">~&lt;/span>&lt;span class="n">CountryModel&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="nf">rowCount&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">QModelIndex&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">parent&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QModelIndex&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="k">override&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QVariant&lt;/span> &lt;span class="nf">data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">QModelIndex&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">role&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="k">override&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">private&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QVector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Country&lt;/span>&lt;span class="o">*&amp;gt;&lt;/span> &lt;span class="n">countries&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s break it down. &lt;code>CountryModel&lt;/code>extends &lt;a href="http://doc.qt.io/qt-5/qabstractlistmodel.html">QAbstractListModel&lt;/a>, which is a kind of Model that provides rows of data. The View displaying &lt;code>CountryModel&lt;/code>&amp;rsquo;s data will configure itself by calling:&lt;/p>
&lt;ul>
&lt;li>&lt;code>rowCount()&lt;/code> to measure its widget size according to the number of rows.&lt;/li>
&lt;li>&lt;code>data()&lt;/code> to retrieve the actual data. It returns a &lt;a href="http://doc.qt.io/qt-5/qvariant.html">QVariant&lt;/a>, the generic Qt union type to transfer data back and forth without being restricted by a strong C++ type.&lt;/li>
&lt;/ul>
&lt;p>These functions come from &lt;code>QAbstractListModel&lt;/code>, so we have to override them to provide the real data size and content. For our purpose, the data is simply a &lt;code>QVector&lt;/code> of &lt;code>Country*&lt;/code>.&lt;/p>
&lt;p>Now, &lt;code>rowCount()&lt;/code> and &lt;code>data()&lt;/code> both take a special argument: a &lt;code>QModelIndex&lt;/code>. We&amp;rsquo;ll dive in greater length about this topic in the post about the editable Model / View. For now, just consider it as an opaque object that handles data indexes from the Model&amp;rsquo;s perspective. To retrieve a &lt;code>Country&lt;/code> from &lt;code>countries&lt;/code> at a specific index, we&amp;rsquo;ll do an &lt;code>index.row()&lt;/code>. Things get hairy when we update the data — adding, deleting lines — because this will mess up the index. That&amp;rsquo;s why Qt uses an internal index handler to keep track of what moved with &lt;code>QModelIndex&lt;/code>.&lt;/p>
&lt;p>Finally, the &lt;code>enum CountryRoles&lt;/code>. We&amp;rsquo;ll skip it for now. It will come to light in the implementation of the function &lt;code>data()&lt;/code>.&lt;/p>
&lt;div style="text-align: center; margin: 2em 0; clear: both;">
&lt;span style="font-size: 1.5em; color: #666;">• • •&lt;/span>
&lt;/div>
&lt;p>Let&amp;rsquo;s switch the &lt;code>CountryModel.cpp&lt;/code>, with &lt;code>CountryModel&lt;/code>&amp;rsquo;s contructor &amp;amp; destructor:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;QIcon&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">CountryModel&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">CountryModel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QObject&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">parent&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QAbstractListModel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">parent&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">countries&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">countries&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">Country&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;France&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Paris&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;:/flags/fr.png&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">Country&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Great Britain&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;London&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;:/flags/gb.png&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">Country&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Japan&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Tokyo&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;:/flags/jp.png&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">Country&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;United States of America&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Washington, D.C&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;:/flags/us.png&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">CountryModel&lt;/span>&lt;span class="o">::~&lt;/span>&lt;span class="n">CountryModel&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qDeleteAll&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">countries&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>countries&lt;/code> is initialized in the constructor. You can replace it with whatever your data source is: database, CSV file, etc. The country&amp;rsquo;s icon is a path pointing to a &lt;code>.qrc&lt;/code> resource stored in the project. The destructor just cleans up the &lt;code>Country*&lt;/code>stored in countries.&lt;/p>
&lt;p>The meat of the class lies in the following functions, starting with &lt;code>rowCount()&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="n">CountryModel&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">rowCount&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">QModelIndex&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">parent&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Q_UNUSED&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">parent&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">countries&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The function takes a &lt;code>QModelIndex&amp;amp; parent&lt;/code>, because you data source could be tree (think of a directory / files structure). Each directory would be a &lt;code>parent&lt;/code>, and its size would be different from its neighbors. As our model is a flat list, we can safely ignore the &lt;code>parent&lt;/code> and return &lt;code>countries.size()&lt;/code>.&lt;/p>
&lt;p>Next, the implementation of &lt;code>data()&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="n">QVariant&lt;/span> &lt;span class="n">CountryModel&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">QModelIndex&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">role&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="n">Country&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">country&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">countries&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">at&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">index&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">row&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">switch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">case&lt;/span> &lt;span class="n">Qt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="nl">DisplayRole&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">country&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">case&lt;/span> &lt;span class="n">Qt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="nl">DecorationRole&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">QIcon&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">country&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">flagIcon&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">case&lt;/span> &lt;span class="n">CountryRoles&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="nl">CapitalRole&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">country&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">capital&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">default&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">QVariant&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>So, &lt;code>data()&lt;/code> takes 2 parameters:&lt;/p>
&lt;ul>
&lt;li>&lt;code>index&lt;/code> to know the index of the requested data — the country index in our case.&lt;/li>
&lt;li>&lt;code>role&lt;/code> to indicate the type of the data it wants to retrieve.&lt;/li>
&lt;/ul>
&lt;p>&lt;code>data()&lt;/code> &lt;em>is not called to retrieve a whole row&lt;/em> (i.e. a full &lt;code>Country&lt;/code> object). It&amp;rsquo;s &lt;strong>&lt;em>called for each piece of data it wants to display&lt;/em>&lt;/strong>. How does it know which piece of data it wants to display? That&amp;rsquo;s the point of the &lt;code>role&lt;/code> parameter! There are &lt;a href="http://doc.qt.io/qt-5/qt.html#ItemDataRole-enum">predefined roles&lt;/a> that can be requested by the View. In a &lt;code>QListView&lt;/code>, the content of a displayed row will be &lt;code>Qt::DisplayRole&lt;/code>.&lt;/p>
&lt;p>First, we retrieve the &lt;code>Country&lt;/code> for a given &lt;code>index.row()&lt;/code>. Then, the &lt;code>switch(role) { … }&lt;/code> block comes into play. if the View want&amp;rsquo;s to see the &lt;code>Qt::DisplayRole&lt;/code>, we return the &lt;code>country.name&lt;/code>. If the View wants to see the &lt;code>Qt::DecorationRole&lt;/code> (the icon just at the left of the row label), we return a &lt;code>QIcon(contry.flagIcon)&lt;/code>. Every return value must be able to be converted to a &lt;code>QVariant&lt;/code>, this lets &lt;code>data()&lt;/code> to have a generic signature.&lt;/p>
&lt;p>Alright, the principle seems sound. But what if we want to display custom data? Here, a &lt;code>Country&lt;/code> also owns a &lt;code>capital&lt;/code>, which could — and will — be used by the View. That&amp;rsquo;s where the forgotten &lt;code>enum CountryRoles&lt;/code> strikes back. Let me avoid you some scrolling:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">enum&lt;/span> &lt;span class="nc">CountryRoles&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">CapitalRole&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Qt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">UserRole&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we defined a custom role, &lt;code>CapitalRole&lt;/code> that takes the &lt;code>Qt::UserRole&lt;/code> value. &lt;code>Qt::UserRole&lt;/code> is simply the starting value (&lt;code>0x0100&lt;/code>) for user defined roles. If you have more data to provide in your Model, just continue to add custom roles in your &lt;code>enum&lt;/code>.&lt;/p>
&lt;p>A last important detail —&lt;code>data()&lt;/code> is &lt;code>const&lt;/code>. In other words, it cannot change&lt;code>CountryModel&lt;/code>, and can only call&lt;code>const&lt;/code> functions. If you want to generate thumbnails on the fly for a country&amp;rsquo;s flag, you&amp;rsquo;re in for a world of pain. By design, the &lt;code>data()&lt;/code> functions expects to retrieve const-data and returns a &lt;code>QVariant&lt;/code> to be copied by value. There are possible workarounds with a &lt;a href="http://doc.qt.io/qt-5/qidentityproxymodel.html">QIdentityProxyModel&lt;/a>. If you&amp;rsquo;re going with QML, the Qt folks were thoughtful with &lt;a href="http://doc.qt.io/qt-5/qquickimageprovider.html">QQuickImageProvider&lt;/a>.&lt;/p>
&lt;h2 id="the-view">The View&lt;/h2>
&lt;p>The View is straightforward, in a usual &lt;code>MainWindow&lt;/code> class, The form looks like this:&lt;/p>
&lt;figure class="left" >
&lt;img src="https://gryt.io/img/qt-modelview-read/model-view-read-ui-form.png"
onclick="openLightbox('\/img\/qt-modelview-read\/model-view-read-ui-form.png')"
style="cursor: pointer;" />
&lt;figcaption class="center" >UI Form of the MainWindow&lt;/figcaption>
&lt;/figure>
&lt;ul>
&lt;li>On the left, the most important widget is &lt;code>countryListView&lt;/code>, a &lt;code>QListView&lt;/code> that will display the data coming from &lt;code>CountryModel&lt;/code>.&lt;/li>
&lt;li>On the right, &lt;code>countryCapitalLabel&lt;/code> and &lt;code>countryNameLabel&lt;/code> will be updated with the currently selected &lt;code>Country&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>The source is short, starting with &lt;code>MainWindow.h&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#ifndef MAINWINDOW_H
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#define MAINWINDOW_H
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;QMainWindow&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;QItemSelection&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;CountryModel.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">namespace&lt;/span> &lt;span class="n">Ui&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">    &lt;span class="k">class&lt;/span> &lt;span class="nc">MainWindow&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MainWindow&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">public&lt;/span> &lt;span class="n">QMainWindow&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">     &lt;span class="n">Q_OBJECT&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">     &lt;span class="k">explicit&lt;/span> &lt;span class="n">MainWindow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QWidget&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">parent&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">     &lt;span class="o">~&lt;/span>&lt;span class="n">MainWindow&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">private&lt;/span> &lt;span class="nl">slots&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">     &lt;span class="kt">void&lt;/span> &lt;span class="n">onSelectionChanged&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">QItemSelection&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">selected&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">QItemSelection&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">deselected&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">private&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">     &lt;span class="n">Ui&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">MainWindow&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">ui&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">     &lt;span class="n">CountryModel&lt;/span> &lt;span class="n">countryModel&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#endif &lt;/span>&lt;span class="c1">// MAINWINDOW_H
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>onSelectionChanged()&lt;/code> will be called each time a selection changes on &lt;code>countryListView&lt;/code>.&lt;/li>
&lt;li>&lt;code>countryModel&lt;/code> is the &lt;code>CountryModel&lt;/code> member variable that will feed the data to &lt;code>countryListView&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>The last piece of the puzzle hides in &lt;code>MainWindow.cpp&lt;/code>, starting with the constructor:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;MainWindow.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;ui_MainWindow.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;QItemSelectionModel&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">MainWindow&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">MainWindow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">QWidget&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">parent&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QMainWindow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">parent&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ui&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">Ui&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">MainWindow&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">countryModel&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ui&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">setupUi&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">this&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">setWindowTitle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Model / View sample - countries&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ui&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">countryListView&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">setModel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">countryModel&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QItemSelectionModel&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">selectionModel&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ui&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">countryListView&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">selectionModel&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">connect&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">selectionModel&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">QItemSelectionModel&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">selectionChanged&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">this&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">MainWindow&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">onSelectionChanged&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The whole magic happens when &lt;code>countryListView-&amp;gt;setModel(&amp;amp;countryModel)&lt;/code> is called. Because &lt;code>CountryModel&lt;/code> extends &lt;code>QAbstractListModel&lt;/code>, this call is generic from &lt;code>countryListView&lt;/code>&amp;rsquo;s perspective. If we decide to update &lt;code>CountryModel&lt;/code> to store the countries in a database, &lt;code>countryListView&lt;/code> couldn&amp;rsquo;t care less.&lt;/p>
&lt;p>The next lines are here to update our custom country name / capital labels. The selection of a &lt;code>QListView&lt;/code> is also handled by a Model, this time it&amp;rsquo;s a &lt;a href="http://doc.qt.io/qt-5/qitemselectionmodel.html">QItemSelectionModel&lt;/a>. The implementation of &lt;code>onSelectionChanged()&lt;/code> looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="n">MainWindow&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">onSelectionChanged&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">QItemSelection&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">selected&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">QItemSelection&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">deselected&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Q_UNUSED&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">deselected&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QModelIndexList&lt;/span> &lt;span class="n">list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">selected&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">indexes&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="n">QModelIndex&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">index&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">list&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">first&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QString&lt;/span> &lt;span class="n">countryName&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Qt&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">DisplayRole&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="n">toString&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ui&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">countryNameLabel&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">setText&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">countryName&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">QString&lt;/span> &lt;span class="n">countryCapital&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CountryModel&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">CapitalRole&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="n">toString&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ui&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">countryCapitalLabel&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">setText&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">countryCapital&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The parameters &lt;code>selected&lt;/code> &amp;amp; &lt;code>deselected&lt;/code> encapsulate the current state of the &lt;code>countryListView&lt;/code>. From here, we retrieve the currently selected indexes (&lt;code>QListView&lt;/code> can support multiple selections). We take the first index, and start working with our now-old-friend, &lt;code>QModelIndex&lt;/code>.&lt;/p>
&lt;p>To update &lt;code>countryNameLabel&lt;/code>, we get the data from the Model, using the &lt;code>index.data()&lt;/code> function. Remember &lt;code>CountryModel::data()&lt;/code> with the &lt;code>role&lt;/code> parameter? Here it is, in all its glory! The returned &lt;code>QVariant&lt;/code> is converted to a &lt;code>QString&lt;/code> and then passed to &lt;code>countryNameLabel&lt;/code>. The same pattern is used for &lt;code>countryCapitalLabel&lt;/code>, although we rely on our custom role — &lt;code>CountryModel::CapitalRole&lt;/code> — to target the right piece of data.&lt;/p>
&lt;div style="text-align: center; margin: 2em 0; clear: both;">
&lt;span style="font-size: 1.5em; color: #666;">• • •&lt;/span>
&lt;/div>
&lt;p>As you can see, there&amp;rsquo;s still no trace of &lt;code>CountryModel&lt;/code> around, even though it&amp;rsquo;s working behind the scene. It took &lt;strong>less than 150 lines of C++ code to scaffold a generic data source that can be plugged in a standard &lt;code>QListView&lt;/code>&lt;/strong>. In my humble opinion, it&amp;rsquo;s quite a treat to achieve this much with so little code.&lt;/p>
&lt;p>Again, everything is available on &lt;a href="https://github.com/synapticvoid/sample-qt-model-view">GitHub&lt;/a>, go and take a look.&lt;/p>
&lt;p>The first time I really understood Model / View like so, I wondered. Is the documentation size inversely proportional to the simplicity of the concept it tries to explain? Is it a just a smokescreen, some kind of conspiration? &lt;em>Is life like the Model / View documentation, so simple and yet so hard to explain?&lt;/em>&lt;/p>
&lt;h2 id="going-deeper">Going deeper&lt;/h2>
&lt;p>If you want to dig deeper in Qt, I co-wrote a whole book about the Qt framework, &lt;a href="https://www.packtpub.com/web-development/mastering-qt-5-second-edition">Mastering Qt 5&lt;/a>. The Model / View is covered inside out, with the full data CRUD explanation, QML implementation to connect to a Model — it takes 3 chapters to cover the material.&lt;/p>
&lt;figure class="left" >
&lt;img src="https://gryt.io/img/qt-modelview-read/mastering-qt5-cover.png"
onclick="openLightbox('\/img\/qt-modelview-read\/mastering-qt5-cover.png')"
style="cursor: pointer;" />
&lt;figcaption class="center" >Mastering Qt 5 cover&lt;/figcaption>
&lt;/figure>
&lt;p>The book aims to teach you how to be a well-rounded Qt developer. We took our years of experience, frustrations, discoveries and joys about Qt and poured them into these 500 page. We explore the inner working of the Qt signal / slot system, build advanced multi-threaded applications, explain how Qt can work with C++11/14 and much more.&lt;/p></content></item></channel></rss>