Sophie

Sophie

distrib > Mageia > 6 > x86_64 > by-pkgid > 2cba8df17162abb32fcb8e6852f3eacc > files > 1672

qtdeclarative5-doc-5.9.4-1.mga6.noarch.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- dynamicview-tutorial.qdoc -->
  <title>QML Dynamic View Ordering Tutorial 4 - Sorting Items | Qt Quick 5.9</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td >Qt 5.9</td><td ><a href="qtquick-index.html">Qt Quick</a></td><td >QML Dynamic View Ordering Tutorial 4 - Sorting Items</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right">Qt 5.9.4 Reference Documentation</td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
  <link rel="prev" href="qtquick-tutorials-dynamicview-dynamicview3-example.html" />
<p class="naviNextPrevious headerNavi">
<a class="prevPage" href="qtquick-tutorials-dynamicview-dynamicview3-example.html">QML Dynamic View Ordering Tutorial 3 - Moving Dragged Items</a>
</p><p/>
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level2"><a href="#walkthrough">Walkthrough</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">QML Dynamic View Ordering Tutorial 4 - Sorting Items</h1>
<span class="subtitle"></span>
<!-- $$$tutorials/dynamicview/dynamicview4-description -->
<div class="descr"> <a name="details"></a>
<p>Drag and drop isn't the only way items in a view can be re-ordered, using a DelegateModel it is also possible to sort items based on model data. To do that we extend our DelegateModel instance like this:</p>
<pre class="qml">

      <span class="type">DelegateModel</span> {
          <span class="name">id</span>: <span class="name">visualModel</span>
          property <span class="type">var</span> <span class="name">lessThan</span>: [
              <span class="keyword">function</span>(<span class="name">left</span>, right) { <span class="keyword">return</span> <span class="name">left</span>.<span class="name">name</span> <span class="operator">&lt;</span> <span class="name">right</span>.<span class="name">name</span> },
              <span class="keyword">function</span>(<span class="name">left</span>, right) { <span class="keyword">return</span> <span class="name">left</span>.<span class="name">type</span> <span class="operator">&lt;</span> <span class="name">right</span>.<span class="name">type</span> },
              <span class="keyword">function</span>(<span class="name">left</span>, right) { <span class="keyword">return</span> <span class="name">left</span>.<span class="name">age</span> <span class="operator">&lt;</span> <span class="name">right</span>.<span class="name">age</span> },
              <span class="keyword">function</span>(<span class="name">left</span>, right) {
                  <span class="keyword">if</span> (<span class="name">left</span>.<span class="name">size</span> <span class="operator">==</span> <span class="string">&quot;Small&quot;</span>)
                      <span class="keyword">return</span> <span class="number">true</span>
                  <span class="keyword">else</span> <span class="keyword">if</span> (<span class="name">right</span>.<span class="name">size</span> <span class="operator">==</span> <span class="string">&quot;Small&quot;</span>)
                      <span class="keyword">return</span> <span class="number">false</span>
                  <span class="keyword">else</span> <span class="keyword">if</span> (<span class="name">left</span>.<span class="name">size</span> <span class="operator">==</span> <span class="string">&quot;Medium&quot;</span>)
                      <span class="keyword">return</span> <span class="number">true</span>
                  <span class="keyword">else</span>
                      <span class="keyword">return</span> <span class="number">false</span>
              }
          ]

          property <span class="type">int</span> <span class="name">sortOrder</span>: <span class="name">orderSelector</span>.<span class="name">selectedIndex</span>
          <span class="name">onSortOrderChanged</span>: <span class="name">items</span>.<span class="name">setGroups</span>(<span class="number">0</span>, <span class="name">items</span>.<span class="name">count</span>, <span class="string">&quot;unsorted&quot;</span>)

          <span class="keyword">function</span> <span class="name">insertPosition</span>(<span class="name">lessThan</span>, item) {
              var <span class="name">lower</span> = <span class="number">0</span>
              var <span class="name">upper</span> = <span class="name">items</span>.<span class="name">count</span>
              <span class="keyword">while</span> (<span class="name">lower</span> <span class="operator">&lt;</span> <span class="name">upper</span>) {
                  var <span class="name">middle</span> = <span class="name">Math</span>.<span class="name">floor</span>(<span class="name">lower</span> <span class="operator">+</span> (<span class="name">upper</span> <span class="operator">-</span> <span class="name">lower</span>) <span class="operator">/</span> <span class="number">2</span>)
                  var <span class="name">result</span> = <span class="name">lessThan</span>(<span class="name">item</span>.<span class="name">model</span>, <span class="name">items</span>.<span class="name">get</span>(<span class="name">middle</span>).<span class="name">model</span>);
                  <span class="keyword">if</span> (<span class="name">result</span>) {
                      <span class="name">upper</span> <span class="operator">=</span> <span class="name">middle</span>
                  } <span class="keyword">else</span> {
                      <span class="name">lower</span> <span class="operator">=</span> <span class="name">middle</span> <span class="operator">+</span> <span class="number">1</span>
                  }
              }
              <span class="keyword">return</span> <span class="name">lower</span>
          }

          <span class="keyword">function</span> <span class="name">sort</span>(<span class="name">lessThan</span>) {
              <span class="keyword">while</span> (<span class="name">unsortedItems</span>.<span class="name">count</span> <span class="operator">&gt;</span> <span class="number">0</span>) {
                  var <span class="name">item</span> = <span class="name">unsortedItems</span>.<span class="name">get</span>(<span class="number">0</span>)
                  var <span class="name">index</span> = <span class="name">insertPosition</span>(<span class="name">lessThan</span>, <span class="name">item</span>)

                  <span class="name">item</span>.<span class="name">groups</span> <span class="operator">=</span> <span class="string">&quot;items&quot;</span>
                  <span class="name">items</span>.<span class="name">move</span>(<span class="name">item</span>.<span class="name">itemsIndex</span>, <span class="name">index</span>)
              }
          }

          <span class="name">items</span>.includeByDefault: <span class="number">false</span>
          <span class="name">groups</span>: <span class="name">VisualDataGroup</span> {
              <span class="name">id</span>: <span class="name">unsortedItems</span>
              <span class="name">name</span>: <span class="string">&quot;unsorted&quot;</span>

              <span class="name">includeByDefault</span>: <span class="number">true</span>
              <span class="name">onChanged</span>: {
                  <span class="keyword">if</span> (<span class="name">visualModel</span>.<span class="name">sortOrder</span> <span class="operator">==</span> <span class="name">visualModel</span>.<span class="name">lessThan</span>.<span class="name">length</span>)
                      <span class="name">setGroups</span>(<span class="number">0</span>, <span class="name">count</span>, <span class="string">&quot;items&quot;</span>)
                  <span class="keyword">else</span>
                      <span class="name">visualModel</span>.<span class="name">sort</span>(<span class="name">visualModel</span>.<span class="name">lessThan</span>[<span class="name">visualModel</span>.<span class="name">sortOrder</span>])
              }
          }
          <span class="name">model</span>: <span class="name">PetsModel</span> {}
          <span class="name">delegate</span>: <span class="name">dragDelegate</span>
      }

</pre>
<a name="walkthrough"></a>
<h3 >Walkthrough</h3>
<p>Items in a DelegateModel are filtered into groups represented by the DelegateModelGroup type, normally all items in the model belong to a default items group but this default can be changed with the includeByDefault property. To implement our sorting we want items to first be added to an unsorted group from where we can transfer them to a sorted position in the items group. To do that we clear includeByDefault on the items group and set it on a new group name 'unsorted'.</p>
<pre class="qml">

          <span class="name">items</span>.includeByDefault: <span class="number">false</span>
          <span class="name">groups</span>: <span class="name">VisualDataGroup</span> {
              <span class="name">id</span>: <span class="name">unsortedItems</span>
              <span class="name">name</span>: <span class="string">&quot;unsorted&quot;</span>

              <span class="name">includeByDefault</span>: <span class="number">true</span>
          }

</pre>
<p>We sort the items by first finding the position in the items group to insert the first unsorted item and then transfer the item to the items group before moving it to the pre-determined index and repeat until the unsorted group is empty.</p>
<p>To find the insert position for an item we request a handle for the item from the unsorted group with the get() function. Through the model property on this handle we can access the same model data that is available in a delegate instance of that item and compare against other items to determine relative position.</p>
<pre class="qml">

          <span class="keyword">function</span> <span class="name">insertPosition</span>(<span class="name">lessThan</span>, item) {
              var <span class="name">lower</span> = <span class="number">0</span>
              var <span class="name">upper</span> = <span class="name">items</span>.<span class="name">count</span>
              <span class="keyword">while</span> (<span class="name">lower</span> <span class="operator">&lt;</span> <span class="name">upper</span>) {
                  var <span class="name">middle</span> = <span class="name">Math</span>.<span class="name">floor</span>(<span class="name">lower</span> <span class="operator">+</span> (<span class="name">upper</span> <span class="operator">-</span> <span class="name">lower</span>) <span class="operator">/</span> <span class="number">2</span>)
                  var <span class="name">result</span> = <span class="name">lessThan</span>(<span class="name">item</span>.<span class="name">model</span>, <span class="name">items</span>.<span class="name">get</span>(<span class="name">middle</span>).<span class="name">model</span>);
                  <span class="keyword">if</span> (<span class="name">result</span>) {
                      <span class="name">upper</span> <span class="operator">=</span> <span class="name">middle</span>
                  } <span class="keyword">else</span> {
                      <span class="name">lower</span> <span class="operator">=</span> <span class="name">middle</span> <span class="operator">+</span> <span class="number">1</span>
                  }
              }
              <span class="keyword">return</span> <span class="name">lower</span>
          }

          <span class="keyword">function</span> <span class="name">sort</span>(<span class="name">lessThan</span>) {
              <span class="keyword">while</span> (<span class="name">unsortedItems</span>.<span class="name">count</span> <span class="operator">&gt;</span> <span class="number">0</span>) {
                  var <span class="name">item</span> = <span class="name">unsortedItems</span>.<span class="name">get</span>(<span class="number">0</span>)
                  var <span class="name">index</span> = <span class="name">insertPosition</span>(<span class="name">lessThan</span>, <span class="name">item</span>)

                  <span class="name">item</span>.<span class="name">groups</span> <span class="operator">=</span> <span class="string">&quot;items&quot;</span>
                  <span class="name">items</span>.<span class="name">move</span>(<span class="name">item</span>.<span class="name">itemsIndex</span>, <span class="name">index</span>)
              }
          }

</pre>
<p>The lessThan argument to the sort function is a comparsion function which will determine the order of the list. In this example it can be one of the following:</p>
<pre class="qml">

          property <span class="type">var</span> <span class="name">lessThan</span>: [
              <span class="keyword">function</span>(<span class="name">left</span>, right) { <span class="keyword">return</span> <span class="name">left</span>.<span class="name">name</span> <span class="operator">&lt;</span> <span class="name">right</span>.<span class="name">name</span> },
              <span class="keyword">function</span>(<span class="name">left</span>, right) { <span class="keyword">return</span> <span class="name">left</span>.<span class="name">type</span> <span class="operator">&lt;</span> <span class="name">right</span>.<span class="name">type</span> },
              <span class="keyword">function</span>(<span class="name">left</span>, right) { <span class="keyword">return</span> <span class="name">left</span>.<span class="name">age</span> <span class="operator">&lt;</span> <span class="name">right</span>.<span class="name">age</span> },
              <span class="keyword">function</span>(<span class="name">left</span>, right) {
                  <span class="keyword">if</span> (<span class="name">left</span>.<span class="name">size</span> <span class="operator">==</span> <span class="string">&quot;Small&quot;</span>)
                      <span class="keyword">return</span> <span class="number">true</span>
                  <span class="keyword">else</span> <span class="keyword">if</span> (<span class="name">right</span>.<span class="name">size</span> <span class="operator">==</span> <span class="string">&quot;Small&quot;</span>)
                      <span class="keyword">return</span> <span class="number">false</span>
                  <span class="keyword">else</span> <span class="keyword">if</span> (<span class="name">left</span>.<span class="name">size</span> <span class="operator">==</span> <span class="string">&quot;Medium&quot;</span>)
                      <span class="keyword">return</span> <span class="number">true</span>
                  <span class="keyword">else</span>
                      <span class="keyword">return</span> <span class="number">false</span>
              }
          ]

</pre>
<p>A sort is triggered whenever new items are added to the unsorted DelegateModel which we are notified of by the DelegateModelGroup <code>onChanged</code> handler. If no sort function is currently selected we simply transfer all items from the unsorted group to the items group, otherwise we call sort with the selected sort function.</p>
<pre class="qml">

          <span class="name">groups</span>: <span class="name">VisualDataGroup</span> {
              <span class="name">id</span>: <span class="name">unsortedItems</span>
              <span class="name">name</span>: <span class="string">&quot;unsorted&quot;</span>

              <span class="name">includeByDefault</span>: <span class="number">true</span>
              <span class="name">onChanged</span>: {
                  <span class="keyword">if</span> (<span class="name">visualModel</span>.<span class="name">sortOrder</span> <span class="operator">==</span> <span class="name">visualModel</span>.<span class="name">lessThan</span>.<span class="name">length</span>)
                      <span class="name">setGroups</span>(<span class="number">0</span>, <span class="name">count</span>, <span class="string">&quot;items&quot;</span>)
                  <span class="keyword">else</span>
                      <span class="name">visualModel</span>.<span class="name">sort</span>(<span class="name">visualModel</span>.<span class="name">lessThan</span>[<span class="name">visualModel</span>.<span class="name">sortOrder</span>])
              }
          }

</pre>
<p>Finally when the selected sort order changes we can trigger a full re-sort of the list by moving all items from the items group to the unsorted group, which will trigger the DelegateModelGroup <code>onChanged</code> handler and transfer the items back to the items group in correct order. Note that the DelegateModelGroup <code>onChanged</code> handler will not be invoked recursively so there's no issue with it being invoked during a sort.</p>
<pre class="qml">

          property <span class="type">int</span> <span class="name">sortOrder</span>: <span class="name">orderSelector</span>.<span class="name">selectedIndex</span>
          <span class="name">onSortOrderChanged</span>: <span class="name">items</span>.<span class="name">setGroups</span>(<span class="number">0</span>, <span class="name">items</span>.<span class="name">count</span>, <span class="string">&quot;unsorted&quot;</span>)

</pre>
<p>Files:</p>
<ul>
<li><a href="qtquick-tutorials-dynamicview-dynamicview4-listselector-qml.html">tutorials/dynamicview/dynamicview4/ListSelector.qml</a></li>
<li><a href="qtquick-tutorials-dynamicview-dynamicview4-petsmodel-qml.html">tutorials/dynamicview/dynamicview4/PetsModel.qml</a></li>
<li><a href="qtquick-tutorials-dynamicview-dynamicview4-dynamicview-qml.html">tutorials/dynamicview/dynamicview4/dynamicview.qml</a></li>
<li><a href="qtquick-tutorials-dynamicview-dynamicview4-dynamicview4-qmlproject.html">tutorials/dynamicview/dynamicview4/dynamicview4.qmlproject</a></li>
</ul>
</div>
<!-- @@@tutorials/dynamicview/dynamicview4 -->
<p class="naviNextPrevious footerNavi">
<a class="prevPage" href="qtquick-tutorials-dynamicview-dynamicview3-example.html">QML Dynamic View Ordering Tutorial 3 - Moving Dragged Items</a>
</p>
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2017 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>