1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- qml-folderlistmodel.qdoc -->
<title>Qt 4.8: FolderListModel - a C++ model plugin</title>
<link rel="stylesheet" type="text/css" href="style/offline.css" />
</head>
<body>
<div class="header" id="qtdocheader">
<div class="content">
<a href="index.html" class="qtref"><span>Qt Reference Documentation</span></a>
</div>
<div class="breadcrumb toolblock">
<ul>
<li class="first"><a href="index.html">Home</a></li>
<!-- Breadcrumbs go here -->
<li><a href="all-examples.html">Examples</a></li>
<li>FolderListModel - a C++ model plugin</li>
</ul>
</div>
</div>
<div class="content mainContent">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#usage-from-qml">Usage from QML</a></li>
<li class="level1"><a href="#defining-the-model">Defining the Model</a></li>
<li class="level1"><a href="#connecting-the-model-to-qml">Connecting the Model to QML</a></li>
<li class="level1"><a href="#implementing-the-model">Implementing the Model</a></li>
</ul>
</div>
<h1 class="title">FolderListModel - a C++ model plugin</h1>
<span class="subtitle"></span>
<!-- $$$src/imports/folderlistmodel-description -->
<div class="descr"> <a name="details"></a>
<p>Files:</p>
<ul>
<li><a href="src-imports-folderlistmodel-plugin-cpp.html">src/imports/folderlistmodel/plugin.cpp</a></li>
<li><a href="src-imports-folderlistmodel-qdeclarativefolderlistmodel-cpp.html">src/imports/folderlistmodel/qdeclarativefolderlistmodel.cpp</a></li>
<li><a href="src-imports-folderlistmodel-qdeclarativefolderlistmodel-h.html">src/imports/folderlistmodel/qdeclarativefolderlistmodel.h</a></li>
<li><a href="src-imports-folderlistmodel-folderlistmodel-pro.html">src/imports/folderlistmodel/folderlistmodel.pro</a></li>
<li><a href="src-imports-folderlistmodel-qmldir.html">src/imports/folderlistmodel/qmldir</a></li>
</ul>
<p>The <a href="qml-folderlistmodel.html">FolderListModel</a> plugin example shows how to make a C++ model available to QML.<p>It presents a simple file list for a single folder (directory) and allows the presented folder to be changed.</p>
<p class="centerAlign"><img src="images/declarative-folderlistmodel.png" alt="The FolderListModel used to choose a QML file" /></p><p>We do not explain the model implementation in detail, but rather focus on the mechanics of making the model available to QML.</p>
<a name="usage-from-qml"></a>
<h2>Usage from QML</h2>
<p>The <a href="qml-folderlistmodel.html">FolderListModel</a> can be used from QML like this:</p>
<pre class="qml"> import QtQuick 1.0
import Qt.labs.folderlistmodel 1.0
<span class="type"><a href="qml-listview.html">ListView</a></span> {
<span class="name">width</span>: <span class="number">200</span>; <span class="name">height</span>: <span class="number">400</span>
<span class="type"><a href="qml-folderlistmodel.html">FolderListModel</a></span> {
<span class="name">id</span>: <span class="name">folderModel</span>
<span class="name">nameFilters</span>: [<span class="string">"*.qml"</span>]
}
<span class="type"><a href="qml-component.html">Component</a></span> {
<span class="name">id</span>: <span class="name">fileDelegate</span>
<span class="type"><a href="qml-text.html">Text</a></span> { <span class="name">text</span>: <span class="name">fileName</span> }
}
<span class="name">model</span>: <span class="name">folderModel</span>
<span class="name">delegate</span>: <span class="name">fileDelegate</span>
}</pre>
<p>This displays a list of all subfolders and QML files in the current folder.</p>
<p>The <a href="qml-folderlistmodel.html">FolderListModel</a> <tt>folder</tt> property can be set to change the folder that is currently displayed.</p>
<a name="defining-the-model"></a>
<h2>Defining the Model</h2>
<p>We are subclassing <a href="qabstractlistmodel.html">QAbstractListModel</a> which will allow us to give data to QML and send notifications when the data changes:</p>
<pre class="cpp"> <span class="keyword">class</span> <span class="type">QDeclarativeFolderListModel</span> : <span class="keyword">public</span> <span class="type"><a href="qabstractlistmodel.html">QAbstractListModel</a></span><span class="operator">,</span> <span class="keyword">public</span> <span class="type"><a href="qdeclarativeparserstatus.html">QDeclarativeParserStatus</a></span>
{
Q_OBJECT
Q_INTERFACES(<span class="type"><a href="qdeclarativeparserstatus.html">QDeclarativeParserStatus</a></span>)</pre>
<p>As you see, we also inherit the <a href="qdeclarativeparserstatus.html">QDeclarativeParserStatus</a> interface, so that we can delay initial processing until we have all properties set (via componentComplete() below).</p>
<p>The first thing to do when devising a new type for QML is to define the properties you want the type to have:</p>
<pre class="cpp"> Q_PROPERTY(<span class="type"><a href="qurl.html">QUrl</a></span> folder READ folder WRITE setFolder NOTIFY folderChanged)
Q_PROPERTY(<span class="type"><a href="qurl.html">QUrl</a></span> parentFolder READ parentFolder NOTIFY folderChanged)
Q_PROPERTY(<span class="type"><a href="qstringlist.html">QStringList</a></span> nameFilters READ nameFilters WRITE setNameFilters)
Q_PROPERTY(SortField sortField READ sortField WRITE setSortField)
Q_PROPERTY(<span class="type">bool</span> sortReversed READ sortReversed WRITE setSortReversed)
Q_PROPERTY(<span class="type">bool</span> showDirs READ showDirs WRITE setShowDirs)
Q_PROPERTY(<span class="type">bool</span> showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot)
Q_PROPERTY(<span class="type">bool</span> showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable)
Q_PROPERTY(<span class="type">int</span> count READ count)</pre>
<p>The purposes of each of these should be pretty obvious - in QML we will set the folder to display (a file: URL), and the kinds of files we want to show in the view of the model.</p>
<p>Next are the constructor, destructor, and standard <a href="qabstractlistmodel.html">QAbstractListModel</a> subclassing requirements:</p>
<pre class="cpp"> <span class="keyword">public</span>:
<span class="type">QDeclarativeFolderListModel</span>(<span class="type"><a href="qobject.html">QObject</a></span> <span class="operator">*</span>parent <span class="operator">=</span> <span class="number">0</span>);
<span class="operator">~</span><span class="type">QDeclarativeFolderListModel</span>();
<span class="keyword">enum</span> Roles { FileNameRole <span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>UserRole<span class="operator">+</span><span class="number">1</span><span class="operator">,</span> FilePathRole <span class="operator">=</span> <span class="type"><a href="qt.html">Qt</a></span><span class="operator">::</span>UserRole<span class="operator">+</span><span class="number">2</span> };
<span class="type">int</span> rowCount(<span class="keyword">const</span> <span class="type"><a href="qmodelindex.html">QModelIndex</a></span> <span class="operator">&</span>parent) <span class="keyword">const</span>;
<span class="type"><a href="qvariant.html">QVariant</a></span> data(<span class="keyword">const</span> <span class="type"><a href="qmodelindex.html">QModelIndex</a></span> <span class="operator">&</span>index<span class="operator">,</span> <span class="type">int</span> role) <span class="keyword">const</span>;</pre>
<p>The data() function is where we provide model values. The rowCount() function is also a standard part of the <a href="qabstractlistmodel.html">QAbstractListModel</a> interface, but we also want to provide a simpler count property:</p>
<pre class="cpp"> <span class="type">int</span> count() <span class="keyword">const</span> { <span class="keyword">return</span> rowCount(<span class="type"><a href="qmodelindex.html">QModelIndex</a></span>()); }</pre>
<p>Then we have the functions for the remaining properties which we defined above:</p>
<pre class="cpp"> <span class="type"><a href="qurl.html">QUrl</a></span> folder() <span class="keyword">const</span>;
<span class="type">void</span> setFolder(<span class="keyword">const</span> <span class="type"><a href="qurl.html">QUrl</a></span> <span class="operator">&</span>folder);
<span class="type"><a href="qurl.html">QUrl</a></span> parentFolder() <span class="keyword">const</span>;
<span class="type"><a href="qstringlist.html">QStringList</a></span> nameFilters() <span class="keyword">const</span>;
<span class="type">void</span> setNameFilters(<span class="keyword">const</span> <span class="type"><a href="qstringlist.html">QStringList</a></span> <span class="operator">&</span>filters);
<span class="keyword">enum</span> SortField { Unsorted<span class="operator">,</span> Name<span class="operator">,</span> Time<span class="operator">,</span> Size<span class="operator">,</span> Type };
SortField sortField() <span class="keyword">const</span>;
<span class="type">void</span> setSortField(SortField field);
Q_ENUMS(SortField)
<span class="type">bool</span> sortReversed() <span class="keyword">const</span>;
<span class="type">void</span> setSortReversed(<span class="type">bool</span> rev);
<span class="type">bool</span> showDirs() <span class="keyword">const</span>;
<span class="type">void</span> setShowDirs(<span class="type">bool</span>);
<span class="type">bool</span> showDotAndDotDot() <span class="keyword">const</span>;
<span class="type">void</span> setShowDotAndDotDot(<span class="type">bool</span>);
<span class="type">bool</span> showOnlyReadable() <span class="keyword">const</span>;
<span class="type">void</span> setShowOnlyReadable(<span class="type">bool</span>);</pre>
<p>Imperative actions upon the model are made available to QML via a <a href="qobject.html#Q_INVOKABLE">Q_INVOKABLE</a> tag on a normal member function. The isFolder(index) function says whether the value at <i>index</i> is a folder:</p>
<pre class="cpp"> Q_INVOKABLE <span class="type">bool</span> isFolder(<span class="type">int</span> index) <span class="keyword">const</span>;</pre>
<p>Then we have the <a href="qdeclarativeparserstatus.html">QDeclarativeParserStatus</a> interface:</p>
<pre class="cpp"> <span class="keyword">virtual</span> <span class="type">void</span> classBegin();
<span class="keyword">virtual</span> <span class="type">void</span> componentComplete();</pre>
<p>Then the NOTIFY function for the folders property. The implementation will emit this when the folder property is changed.</p>
<pre class="cpp"> Q_SIGNALS:
<span class="type">void</span> folderChanged();</pre>
<p>The class ends with some implementation details:</p>
<pre class="cpp"> <span class="keyword">private</span> Q_SLOTS:
<span class="type">void</span> refresh();
<span class="type">void</span> inserted(<span class="keyword">const</span> <span class="type"><a href="qmodelindex.html">QModelIndex</a></span> <span class="operator">&</span>index<span class="operator">,</span> <span class="type">int</span> start<span class="operator">,</span> <span class="type">int</span> end);
<span class="type">void</span> removed(<span class="keyword">const</span> <span class="type"><a href="qmodelindex.html">QModelIndex</a></span> <span class="operator">&</span>index<span class="operator">,</span> <span class="type">int</span> start<span class="operator">,</span> <span class="type">int</span> end);
<span class="type">void</span> handleDataChanged(<span class="keyword">const</span> <span class="type"><a href="qmodelindex.html">QModelIndex</a></span> <span class="operator">&</span>start<span class="operator">,</span> <span class="keyword">const</span> <span class="type"><a href="qmodelindex.html">QModelIndex</a></span> <span class="operator">&</span>end);
<span class="keyword">private</span>:
Q_DISABLE_COPY(<span class="type">QDeclarativeFolderListModel</span>)
<span class="type">QDeclarativeFolderListModelPrivate</span> <span class="operator">*</span>d;
};</pre>
<p>Lastly, the boilerplare to declare the type for QML use:</p>
<pre class="cpp"> <a href="qdeclarativeengine.html#QML_DECLARE_TYPE">QML_DECLARE_TYPE</a>(<span class="type">QDeclarativeFolderListModel</span>)</pre>
<a name="connecting-the-model-to-qml"></a>
<h2>Connecting the Model to QML</h2>
<p>To make this class available to QML, we only need to make a simple subclass of <a href="qdeclarativeextensionplugin.html">QDeclarativeExtensionPlugin</a>:</p>
<pre class="cpp"> <span class="keyword">class</span> QmlFolderListModelPlugin : <span class="keyword">public</span> <span class="type"><a href="qdeclarativeextensionplugin.html">QDeclarativeExtensionPlugin</a></span>
{
Q_OBJECT
<span class="keyword">public</span>:
<span class="keyword">virtual</span> <span class="type">void</span> registerTypes(<span class="keyword">const</span> <span class="type">char</span> <span class="operator">*</span>uri)
{
Q_ASSERT(QLatin1String(uri) <span class="operator">=</span><span class="operator">=</span> QLatin1String(<span class="string">"Qt.labs.folderlistmodel"</span>));
<span class="preprocessor">#ifndef QT_NO_DIRMODEL</span>
qmlRegisterType<span class="operator"><</span><span class="type">QDeclarativeFolderListModel</span><span class="operator">></span>(uri<span class="operator">,</span><span class="number">1</span><span class="operator">,</span><span class="number">0</span><span class="operator">,</span><span class="string">"FolderListModel"</span>);
<span class="preprocessor">#endif</span>
}
};</pre>
<p>and then use the standard Qt plugin export macro:</p>
<pre class="cpp"> <a href="qtplugin.html#Q_EXPORT_PLUGIN2">Q_EXPORT_PLUGIN2</a>(qmlfolderlistmodelplugin<span class="operator">,</span> QT_PREPEND_NAMESPACE(QmlFolderListModelPlugin));</pre>
<p>Finally, in order for QML to connect the "import" statement to our plugin, we list it in the qmldir file:</p>
<p><a href="src-imports-folderlistmodel-qmldir.html">src/imports/folderlistmodel/qmldir</a></p>
<p>This qmldir file and the compiled plugin will be installed in <tt>$QTDIR/imports/Qt/labs/folderlistmodel/</tt> where the QML engine will find it (since <tt>$QTDIR/imports</tt> is the value of QLibraryInf::libraryPath()).</p>
<a name="implementing-the-model"></a>
<h2>Implementing the Model</h2>
<p>We'll not discuss the model implementation in detail, as it is not specific to QML - any Qt C++ model can be interfaced to QML. This implementation is basically just takes the krufty old <a href="qdirmodel.html" class="obsolete">QDirModel<sup>(obsolete)</sup></a>, which is a tree with lots of detailed roles and re-presents it as a simpler list model where each item is just a fileName and a filePath (as a file: URL rather than a plain file, since QML works with URLs for all content).</p>
<p><a href="src-imports-folderlistmodel-qdeclarativefolderlistmodel-cpp.html">src/imports/folderlistmodel/qdeclarativefolderlistmodel.cpp</a></p>
</div>
<!-- @@@src/imports/folderlistmodel -->
<div class="ft">
<span></span>
</div>
</div>
<div class="footer">
<p>
<acronym title="Copyright">©</acronym> 2012 Nokia Corporation and/or its
subsidiaries. Documentation contributions included herein are the copyrights of
their respective owners.</p>
<br />
<p>
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.</p>
<p>
Documentation sources may be obtained from <a href="http://www.qt-project.org">
www.qt-project.org</a>.</p>
<br />
<p>
Nokia, Qt and their respective logos are trademarks of Nokia Corporation
in Finland and/or other countries worldwide. All other trademarks are property
of their respective owners. <a title="Privacy Policy"
href="http://en.gitorious.org/privacy_policy/">Privacy Policy</a></p>
</div>
</body>
</html>
|