Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-updates > by-pkgid > 4ff6143ff2a088c33c83add3bab6e293 > files > 5

qtenginio5-doc-1.6.3-7.1.mga7.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" />
<!-- cloudaddressbook.qdoc -->
  <title>Enginio C++ Examples - Cloud Address Book | Enginio Manual 1.6.3</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 1.6</td><td >Enginio Manual</td><td >Enginio C++ Examples - Cloud Address Book</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right">Qt 1.6&#x2e;3 Reference Documentation</td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#preconditions">Preconditions</a></li>
<li class="level1"><a href="#backend-description">Backend Description</a></li>
<li class="level1"><a href="#application-design">Application Design</a></li>
<li class="level1"><a href="#implementation">Implementation</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Enginio C++ Examples - Cloud Address Book</h1>
<span class="subtitle"></span>
<!-- $$$cloudaddressbook-brief -->
<p>The Cloud Address Book demonstrates how to use sorting, filtering, and the full text search functionality.</p>
<!-- @@@cloudaddressbook -->
<!-- $$$cloudaddressbook-description -->
<div class="descr"> <a name="details"></a>
<p>This example explains how to use the full text search feature of Enginio, and how to sort and filter data showed from the <a href="enginiomodel.html">EnginioModel</a>. A simple addressbook-like application will be created to illustrate this. This example doesn't cover security or multi-user management. For such topics, please refer to the Social Todo example.</p>
<p class="centerAlign"><img src="images/cloudaddressbook-example.png" alt="" /></p><a name="preconditions"></a>
<h2 id="preconditions">Preconditions</h2>
<p>To start the example, a <i>backend id</i> and a <i>backend secret</i> have to be provided for an existing and configured Enginio backend. The backend can be created using the dashboard, where the Cloud Address Book preconfigured backend can be chosen.</p>
<a name="backend-description"></a>
<h2 id="backend-description">Backend Description</h2>
<p>We recommend to use preconfigured backend, because it contains already all data and structures that are needed to run these examples, but it is not difficult to create the backend from scratch too. The backend should contain one custom object type <code>objects.addressbook</code> having properties:</p>
<ul>
<li>firstName</li>
<li>lastName</li>
<li>email</li>
<li>phone</li>
<li>address</li>
</ul>
<p>All properties are of <code>string</code> type and have to be indexed, because only indexed properties will be searched by the full text search.</p>
<a name="application-design"></a>
<h2 id="application-design">Application Design</h2>
<p>The application's ui mainly consists of a table showing all addresses and a text filed where a query can be typed. A user should be able to sort addresses or highlight an address containing a specified phrase.</p>
<a name="implementation"></a>
<h2 id="implementation">Implementation</h2>
<p>From a developer point of view the application consists of a few simple components:</p>
<ul>
<li><a href="enginioclient.html">EnginioClient</a> which encapsulates all information needed to keep the connection to the backend</li>
<li><a href="enginiomodel.html">EnginioModel</a> which queries all addresses</li>
<li>QSortFilterProxyModel which sorts the data</li>
<li>QTableView which shows the data</li>
</ul>
<p>First we need to establish a connection to the Enginio service. We need to specify the <i>backend id</i> as well as <i>backend secret</i>.</p>
<pre class="cpp">

  client <span class="operator">=</span> <span class="keyword">new</span> EnginioClient(<span class="keyword">this</span>);
  client<span class="operator">-</span><span class="operator">&gt;</span>setBackendId(EnginioBackendId);

</pre>
<p>The second step is to create <a href="enginiomodel.html">EnginioModel</a> which queries all data from the backend. The query is quite simple, it specifies an object type of which all objects need to be returned.</p>
<pre class="cpp">

  model <span class="operator">=</span> <span class="keyword">new</span> AddressBookModel(<span class="keyword">this</span>);
  model<span class="operator">-</span><span class="operator">&gt;</span>setClient(client);

  <span class="type">QJsonObject</span> query;
  query<span class="operator">[</span><span class="string">&quot;objectType&quot;</span><span class="operator">]</span> <span class="operator">=</span> <span class="type">QString</span><span class="operator">::</span>fromUtf8(<span class="string">&quot;objects.addressbook&quot;</span>);
  model<span class="operator">-</span><span class="operator">&gt;</span>setQuery(query);

</pre>
<p><a href="enginiomodel.html">EnginioModel</a> can sort or filter data only initially, which means that, for example, a newly added item will not be placed correctly. To solve the problem QSortFilterProxyModel has to be used.</p>
<pre class="cpp">

  sortFilterProxyModel <span class="operator">=</span> <span class="keyword">new</span> <span class="type">QSortFilterProxyModel</span>(<span class="keyword">this</span>);
  sortFilterProxyModel<span class="operator">-</span><span class="operator">&gt;</span>setSourceModel(model);
  tableView<span class="operator">-</span><span class="operator">&gt;</span>setSortingEnabled(<span class="keyword">true</span>);
  tableView<span class="operator">-</span><span class="operator">&gt;</span>setModel(sortFilterProxyModel);

</pre>
<p>Now is a time to look deeper into EngnioModel. <a href="enginiomodel.html">EnginioModel</a> should define data roles.</p>
<pre class="cpp">

  <span class="keyword">enum</span> Roles {
      FirstNameRole <span class="operator">=</span> Enginio<span class="operator">::</span>CustomPropertyRole<span class="operator">,</span>
      LastNameRole<span class="operator">,</span>
      EmailRole<span class="operator">,</span>
      PhoneRole<span class="operator">,</span>
      AddressRole
  };
  <span class="type">QHash</span><span class="operator">&lt;</span><span class="type">int</span><span class="operator">,</span> <span class="type">QByteArray</span><span class="operator">&gt;</span> AddressBookModel<span class="operator">::</span>roleNames() <span class="keyword">const</span>
  {
      <span class="type">QHash</span><span class="operator">&lt;</span><span class="type">int</span><span class="operator">,</span> <span class="type">QByteArray</span><span class="operator">&gt;</span> roles <span class="operator">=</span> EnginioModel<span class="operator">::</span>roleNames();
      roles<span class="operator">.</span>insert(FirstNameRole<span class="operator">,</span> <span class="string">&quot;firstName&quot;</span>);
      roles<span class="operator">.</span>insert(LastNameRole<span class="operator">,</span> <span class="string">&quot;lastName&quot;</span>);
      roles<span class="operator">.</span>insert(EmailRole<span class="operator">,</span> <span class="string">&quot;email&quot;</span>);
      roles<span class="operator">.</span>insert(PhoneRole<span class="operator">,</span> <span class="string">&quot;phone&quot;</span>);
      roles<span class="operator">.</span>insert(AddressRole<span class="operator">,</span> <span class="string">&quot;address&quot;</span>);
      <span class="keyword">return</span> roles;
  }

</pre>
<p>and as always the data() and <a href="enginiomodel.html#setData">setData()</a> functions have to be overridden to provide Qt::DisplayRole in such a way as to nicely cooperate with QTableView.</p>
<pre class="cpp">

  <span class="type">QVariant</span> AddressBookModel<span class="operator">::</span>data(<span class="keyword">const</span> <span class="type">QModelIndex</span> <span class="operator">&amp;</span>index<span class="operator">,</span> <span class="type">int</span> role) <span class="keyword">const</span>
  {
      <span class="keyword">if</span> (role <span class="operator">=</span><span class="operator">=</span> <span class="type">Qt</span><span class="operator">::</span>DisplayRole) {
          <span class="comment">// we assume here that column order is constant and it is the same as in AddressBookModel::Roles</span>
          <span class="keyword">return</span> EnginioModel<span class="operator">::</span>data(index<span class="operator">,</span> FirstNameRole <span class="operator">+</span> index<span class="operator">.</span>column())<span class="operator">.</span>value<span class="operator">&lt;</span><span class="type">QJsonValue</span><span class="operator">&gt;</span>()<span class="operator">.</span>toString();
      }
      <span class="keyword">if</span> (role <span class="operator">=</span><span class="operator">=</span> <span class="type">Qt</span><span class="operator">::</span>FontRole) {
          <span class="comment">// this role is used to mark items found in the full text search.</span>
          <span class="type">QFont</span> font;
          <span class="type">QString</span> id <span class="operator">=</span> EnginioModel<span class="operator">::</span>data(index<span class="operator">,</span> Enginio<span class="operator">::</span>IdRole)<span class="operator">.</span>value<span class="operator">&lt;</span><span class="type">QString</span><span class="operator">&gt;</span>();
          font<span class="operator">.</span>setBold(_markedItems<span class="operator">.</span>contains(id));
          <span class="keyword">return</span> font;
      }

      <span class="keyword">return</span> EnginioModel<span class="operator">::</span>data(index<span class="operator">,</span> role);
  }

  bool AddressBookModel<span class="operator">::</span>setData(<span class="keyword">const</span> <span class="type">QModelIndex</span> <span class="operator">&amp;</span>index<span class="operator">,</span> <span class="keyword">const</span> <span class="type">QVariant</span> <span class="operator">&amp;</span>value<span class="operator">,</span> <span class="type">int</span> role)
  {
      bool result <span class="operator">=</span> role <span class="operator">=</span><span class="operator">=</span> <span class="type">Qt</span><span class="operator">::</span>EditRole
              <span class="operator">?</span> EnginioModel<span class="operator">::</span>setData(<span class="keyword">this</span><span class="operator">-</span><span class="operator">&gt;</span>index(index<span class="operator">.</span>row())<span class="operator">,</span> value<span class="operator">,</span> FirstNameRole <span class="operator">+</span> index<span class="operator">.</span>column())
              : EnginioModel<span class="operator">::</span>setData(<span class="keyword">this</span><span class="operator">-</span><span class="operator">&gt;</span>index(index<span class="operator">.</span>row())<span class="operator">,</span> value<span class="operator">,</span> role);

      <span class="comment">// if the data was edited, the marked items set may not be valid anymore</span>
      <span class="comment">// so we need to clear it.</span>
      <span class="keyword">if</span> (result)
          _markedItems<span class="operator">.</span>clear();
      <span class="keyword">return</span> result;
  }

</pre>
<p>QTableView requires the specification of columns headers, so that they can be shown in the user interface:</p>
<pre class="cpp">

  <span class="type">int</span> AddressBookModel<span class="operator">::</span>columnCount(<span class="keyword">const</span> <span class="type">QModelIndex</span> <span class="operator">&amp;</span>parent) <span class="keyword">const</span>
  {
      <span class="keyword">return</span> parent<span class="operator">.</span>isValid() <span class="operator">?</span> <span class="number">0</span> : <span class="number">5</span>;
  }

  <span class="type">QVariant</span> AddressBookModel<span class="operator">::</span>headerData(<span class="type">int</span> section<span class="operator">,</span> <span class="type">Qt</span><span class="operator">::</span>Orientation orientation<span class="operator">,</span> <span class="type">int</span> role) <span class="keyword">const</span>
  {
      <span class="keyword">if</span> (orientation <span class="operator">=</span><span class="operator">=</span> <span class="type">Qt</span><span class="operator">::</span>Horizontal <span class="operator">&amp;</span><span class="operator">&amp;</span> role <span class="operator">=</span><span class="operator">=</span> <span class="type">Qt</span><span class="operator">::</span>DisplayRole) {
          <span class="keyword">switch</span> (section) {
          <span class="keyword">case</span> <span class="number">0</span>: <span class="keyword">return</span> <span class="type">QStringLiteral</span>(<span class="string">&quot;First name&quot;</span>);
          <span class="keyword">case</span> <span class="number">1</span>: <span class="keyword">return</span> <span class="type">QStringLiteral</span>(<span class="string">&quot;Last name&quot;</span>);
          <span class="keyword">case</span> <span class="number">2</span>: <span class="keyword">return</span> <span class="type">QStringLiteral</span>(<span class="string">&quot;Email&quot;</span>);
          <span class="keyword">case</span> <span class="number">3</span>: <span class="keyword">return</span> <span class="type">QStringLiteral</span>(<span class="string">&quot;Phone number&quot;</span>);
          <span class="keyword">case</span> <span class="number">4</span>: <span class="keyword">return</span> <span class="type">QStringLiteral</span>(<span class="string">&quot;Address&quot;</span>);
          }
          <span class="keyword">return</span> <span class="type">QVariant</span>();
      }
      <span class="keyword">return</span> EnginioModel<span class="operator">::</span>headerData(section<span class="operator">,</span> orientation<span class="operator">,</span> role);
  }

</pre>
<p>Integration of the full text search is the last step in this tutorial. The goal is to highlight items that contain a given phrase. The highlighting is done by data(), which returns a bold font for Qt::FontRole if an item is matching the search query. For reasons of simplicity, this example assumes that the matching items count is not big and can be kept in a QSet, which would be recreated on each search.</p>
<p>To do a full text search, a JSON query needs to be constructed:</p>
<pre class="cpp">

  <span class="comment">// construct JSON object:</span>
  <span class="comment">//    {</span>
  <span class="comment">//        &quot;objectTypes&quot;: [&quot;objects.addressbook&quot;],</span>
  <span class="comment">//        &quot;search&quot;: { &quot;phrase&quot;: &quot;*PHRASE*&quot;,</span>
  <span class="comment">//            &quot;properties&quot;: [&quot;firstName&quot;, &quot;lastName&quot;, &quot;email&quot;, &quot;phone&quot;, &quot;address&quot;]</span>
  <span class="comment">//        }</span>
  <span class="comment">//    }</span>

  <span class="type">QJsonObject</span> query;
  {
      <span class="type">QJsonArray</span> objectTypes;
      objectTypes<span class="operator">.</span>append(<span class="type">QString</span><span class="operator">::</span>fromUtf8(<span class="string">&quot;objects.addressbook&quot;</span>));

      <span class="type">QJsonArray</span> properties;
      properties<span class="operator">.</span>append(<span class="type">QString</span><span class="operator">::</span>fromUtf8(<span class="string">&quot;firstName&quot;</span>));
      properties<span class="operator">.</span>append(<span class="type">QString</span><span class="operator">::</span>fromUtf8(<span class="string">&quot;lastName&quot;</span>));
      properties<span class="operator">.</span>append(<span class="type">QString</span><span class="operator">::</span>fromUtf8(<span class="string">&quot;email&quot;</span>));
      properties<span class="operator">.</span>append(<span class="type">QString</span><span class="operator">::</span>fromUtf8(<span class="string">&quot;phone&quot;</span>));
      properties<span class="operator">.</span>append(<span class="type">QString</span><span class="operator">::</span>fromUtf8(<span class="string">&quot;address&quot;</span>));

      <span class="type">QJsonObject</span> searchQuery;
      searchQuery<span class="operator">.</span>insert(<span class="string">&quot;phrase&quot;</span><span class="operator">,</span> <span class="string">&quot;*&quot;</span> <span class="operator">+</span> search <span class="operator">+</span> <span class="string">&quot;*&quot;</span>);
      searchQuery<span class="operator">.</span>insert(<span class="string">&quot;properties&quot;</span><span class="operator">,</span> properties);

      query<span class="operator">.</span>insert(<span class="string">&quot;objectTypes&quot;</span><span class="operator">,</span> objectTypes);
      query<span class="operator">.</span>insert(<span class="string">&quot;search&quot;</span><span class="operator">,</span> searchQuery);
  }

</pre>
<p>The query contains <code>objectTypes</code> property (note the 's' at the end) which is an array of all object types which have to be searched. In this case, it is only one type: <code>objects.addressbook</code>. Next the <code>search</code> property has to be specified. It is an object that is required to have a <code>phrase</code> property, containing the phrase to search for. phrase that has to be found. Please use the wildcard <code>*</code> in the search criteria, otherwise only full words will be found. To avoid substrings, for example in an <code>object id</code>, which is not visible for a user, the search is limited to a selected array of <code>properties</code>. When the search query is constructed, it is enough to call <a href="enginioclient.html#fullTextSearch">fullTextSearch()</a>:</p>
<pre class="cpp">

  _searchReply <span class="operator">=</span>  client()<span class="operator">-</span><span class="operator">&gt;</span>fullTextSearch(query);
  <span class="type">QObject</span><span class="operator">::</span>connect(_searchReply<span class="operator">,</span> <span class="operator">&amp;</span>EnginioReply<span class="operator">::</span>finished<span class="operator">,</span> <span class="keyword">this</span><span class="operator">,</span> <span class="operator">&amp;</span>AddressBookModel<span class="operator">::</span>searchResultsArrived);
  <span class="type">QObject</span><span class="operator">::</span>connect(_searchReply<span class="operator">,</span> <span class="operator">&amp;</span>EnginioReply<span class="operator">::</span>finished<span class="operator">,</span> _searchReply<span class="operator">,</span> <span class="operator">&amp;</span>EnginioReply<span class="operator">::</span>deleteLater);

</pre>
<p>The result will be delivered to the <code>searchResultsArrived</code> slot. All objects ids found will be gathered in a <code>markedItems</code> set.</p>
<pre class="cpp">

  <span class="type">void</span> AddressBookModel<span class="operator">::</span>searchResultsArrived()
  {
      <span class="comment">// clear old marks.</span>
      _markedItems<span class="operator">.</span>clear();

      <span class="comment">// update marked ids.</span>
      <span class="type">QJsonArray</span> results <span class="operator">=</span> _searchReply<span class="operator">-</span><span class="operator">&gt;</span>data()<span class="operator">[</span><span class="string">&quot;results&quot;</span><span class="operator">]</span><span class="operator">.</span>toArray();
      foreach (<span class="keyword">const</span> <span class="type">QJsonValue</span> <span class="operator">&amp;</span>value<span class="operator">,</span> results) {
          <span class="type">QJsonObject</span> person <span class="operator">=</span> value<span class="operator">.</span>toObject();
          _markedItems<span class="operator">.</span>insert(person<span class="operator">[</span><span class="string">&quot;id&quot;</span><span class="operator">]</span><span class="operator">.</span>toString());
      }

      <span class="type">QVector</span><span class="operator">&lt;</span><span class="type">int</span><span class="operator">&gt;</span> roles;
      roles<span class="operator">.</span>append(<span class="type">Qt</span><span class="operator">::</span>FontRole);
      <span class="comment">// We do not keep id -&gt; row mapping, therefore it is easier to emit</span>
      <span class="comment">// data change signal for all items, even if it is not optimal from</span>
      <span class="comment">// the performance point of view.</span>
      <span class="keyword">emit</span> dataChanged(index(<span class="number">0</span>)<span class="operator">,</span> index(rowCount() <span class="operator">-</span> <span class="number">1</span><span class="operator">,</span> columnCount() <span class="operator">-</span> <span class="number">1</span>) <span class="operator">,</span> roles);

      _searchReply <span class="operator">=</span> <span class="number">0</span>;
      <span class="keyword">emit</span> searchFinished();
  }

</pre>
<p>Files:</p>
<ul>
<li><a href="qtenginio-cloudaddressbook-addressbookmodel-cpp.html">cloudaddressbook/addressbookmodel.cpp</a></li>
<li><a href="qtenginio-cloudaddressbook-addressbookmodel-h.html">cloudaddressbook/addressbookmodel.h</a></li>
<li><a href="qtenginio-cloudaddressbook-cloudaddressbook-pro.html">cloudaddressbook/cloudaddressbook.pro</a></li>
<li><a href="qtenginio-cloudaddressbook-main-cpp.html">cloudaddressbook/main.cpp</a></li>
<li><a href="qtenginio-cloudaddressbook-mainwindow-cpp.html">cloudaddressbook/mainwindow.cpp</a></li>
<li><a href="qtenginio-cloudaddressbook-mainwindow-h.html">cloudaddressbook/mainwindow.h</a></li>
<li><a href="qtenginio-cloudaddressbook-mainwindow-ui.html">cloudaddressbook/mainwindow.ui</a></li>
</ul>
</div>
<!-- @@@cloudaddressbook -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2019 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>