/usr/share/qt5/doc/qtquick/qtquick-scenegraph-customgeometry-example.html is in qtdeclarative5-doc-html 5.5.1-2ubuntu6.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- customgeometry.qdoc -->
<title>Scene Graph - Custom Geometry | Qt Quick 5.5</title>
<link rel="stylesheet" type="text/css" href="style/offline.css" />
</head>
<body>
<div class="header" id="qtdocheader">
<div class="main">
<div class="main-rounded">
<div class="navigationbar">
<ul>
<li>Qt 5.5</li>
<li><a href="qtquick-index.html">Qt Quick</a></li>
<li>Scene Graph - Custom Geometry</li>
<li id="buildversion">Qt 5.5.1 Reference Documentation</li>
</ul>
</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="#beziercurve-declaration">BezierCurve Declaration</a></li>
<li class="level1"><a href="#beziercurve-implementation">BezierCurve Implementation</a></li>
<li class="level1"><a href="#application-entry-point">Application Entry-Point</a></li>
<li class="level1"><a href="#using-the-item">Using the Item</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Scene Graph - Custom Geometry</h1>
<span class="subtitle"></span>
<!-- $$$scenegraph/customgeometry-description -->
<div class="descr"> <a name="details"></a>
<p>The custom geometry example shows how to create a <a href="qquickitem.html">QQuickItem</a> which uses the scene graph API to build a custom geometry for the scene graph. It does this by creating a BezierCurve item which is made part of the CustomGeometry module and makes use of this in a QML file.</p>
<p class="centerAlign"><img src="images/custom-geometry-example.png" alt="" /></p><a name="beziercurve-declaration"></a>
<h2 id="beziercurve-declaration">BezierCurve Declaration</h2>
<pre class="cpp"><span class="preprocessor">#include <QtQuick/QQuickItem></span>
<span class="keyword">class</span> BezierCurve : <span class="keyword">public</span> <span class="type"><a href="qquickitem.html">QQuickItem</a></span>
{
Q_OBJECT
Q_PROPERTY(<span class="type">QPointF</span> p1 READ p1 WRITE setP1 NOTIFY p1Changed)
Q_PROPERTY(<span class="type">QPointF</span> p2 READ p2 WRITE setP2 NOTIFY p2Changed)
Q_PROPERTY(<span class="type">QPointF</span> p3 READ p3 WRITE setP3 NOTIFY p3Changed)
Q_PROPERTY(<span class="type">QPointF</span> p4 READ p4 WRITE setP4 NOTIFY p4Changed)
Q_PROPERTY(<span class="type">int</span> segmentCount READ segmentCount WRITE setSegmentCount NOTIFY segmentCountChanged)
<span class="keyword">public</span>:
BezierCurve(<span class="type"><a href="qquickitem.html">QQuickItem</a></span> <span class="operator">*</span>parent <span class="operator">=</span> <span class="number">0</span>);
<span class="operator">~</span>BezierCurve();
<span class="type"><a href="qsgnode.html">QSGNode</a></span> <span class="operator">*</span>updatePaintNode(<span class="type"><a href="qsgnode.html">QSGNode</a></span> <span class="operator">*</span><span class="operator">,</span> UpdatePaintNodeData <span class="operator">*</span>);
<span class="type">QPointF</span> p1() <span class="keyword">const</span> { <span class="keyword">return</span> m_p1; }
<span class="type">QPointF</span> p2() <span class="keyword">const</span> { <span class="keyword">return</span> m_p2; }
<span class="type">QPointF</span> p3() <span class="keyword">const</span> { <span class="keyword">return</span> m_p3; }
<span class="type">QPointF</span> p4() <span class="keyword">const</span> { <span class="keyword">return</span> m_p4; }
<span class="type">int</span> segmentCount() <span class="keyword">const</span> { <span class="keyword">return</span> m_segmentCount; }
<span class="type">void</span> setP1(<span class="keyword">const</span> <span class="type">QPointF</span> <span class="operator">&</span>p);
<span class="type">void</span> setP2(<span class="keyword">const</span> <span class="type">QPointF</span> <span class="operator">&</span>p);
<span class="type">void</span> setP3(<span class="keyword">const</span> <span class="type">QPointF</span> <span class="operator">&</span>p);
<span class="type">void</span> setP4(<span class="keyword">const</span> <span class="type">QPointF</span> <span class="operator">&</span>p);
<span class="type">void</span> setSegmentCount(<span class="type">int</span> count);
<span class="keyword">signals</span>:
<span class="type">void</span> p1Changed(<span class="keyword">const</span> <span class="type">QPointF</span> <span class="operator">&</span>p);
<span class="type">void</span> p2Changed(<span class="keyword">const</span> <span class="type">QPointF</span> <span class="operator">&</span>p);
<span class="type">void</span> p3Changed(<span class="keyword">const</span> <span class="type">QPointF</span> <span class="operator">&</span>p);
<span class="type">void</span> p4Changed(<span class="keyword">const</span> <span class="type">QPointF</span> <span class="operator">&</span>p);
<span class="type">void</span> segmentCountChanged(<span class="type">int</span> count);
<span class="keyword">private</span>:
<span class="type">QPointF</span> m_p1;
<span class="type">QPointF</span> m_p2;
<span class="type">QPointF</span> m_p3;
<span class="type">QPointF</span> m_p4;
<span class="type">int</span> m_segmentCount;
};</pre>
<p>The item declaration subclasses the <a href="qquickitem.html">QQuickItem</a> class and adds five properties. One for each of the four control points in the bezier curve and a parameter to control the number of segments the curve is subdivided into. For each of the properties we have corresponding getter and setter functions. Since these properties can be bound to in QML, it is also preferable to have notifier signals for each of them so changes will be picked up the QML engine and used accordingly.</p>
<pre class="cpp"> <span class="type"><a href="qsgnode.html">QSGNode</a></span> <span class="operator">*</span>updatePaintNode(<span class="type"><a href="qsgnode.html">QSGNode</a></span> <span class="operator">*</span><span class="operator">,</span> UpdatePaintNodeData <span class="operator">*</span>);</pre>
<p>The synchronization point between the QML scene and the rendering scene graph is the virtual function <a href="qquickitem.html#updatePaintNode">QQuickItem::updatePaintNode</a>() which all items with custom scene graph logic must implement.</p>
<p><b>Note: </b>The scene graph will on many hardware configurations be rendering on a separate thread. It is therefore crucial that interaction with the scene graph happens in a controlled manner, first and foremost through the <a href="qquickitem.html#updatePaintNode">QQuickItem::updatePaintNode</a>() function.</p><a name="beziercurve-implementation"></a>
<h2 id="beziercurve-implementation">BezierCurve Implementation</h2>
<pre class="cpp">BezierCurve<span class="operator">::</span>BezierCurve(<span class="type"><a href="qquickitem.html">QQuickItem</a></span> <span class="operator">*</span>parent)
: <span class="type"><a href="qquickitem.html">QQuickItem</a></span>(parent)
<span class="operator">,</span> m_p1(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span>)
<span class="operator">,</span> m_p2(<span class="number">1</span><span class="operator">,</span> <span class="number">0</span>)
<span class="operator">,</span> m_p3(<span class="number">0</span><span class="operator">,</span> <span class="number">1</span>)
<span class="operator">,</span> m_p4(<span class="number">1</span><span class="operator">,</span> <span class="number">1</span>)
<span class="operator">,</span> m_segmentCount(<span class="number">32</span>)
{
setFlag(ItemHasContents<span class="operator">,</span> <span class="keyword">true</span>);
}</pre>
<p>The BezierCurve constructor sets up default values for the control points and the number of segments. The bezier curve is specified in normalized coordinates relative to the item's bounding rectangle.</p>
<p>The constructor also sets the flag <a href="qquickitem.html#Flag-enum">QQuickItem::ItemHasContents</a>. This flags tells the canvas that this item provides visual content and will call <a href="qquickitem.html#updatePaintNode">QQuickItem::updatePaintNode</a>() when it is time for the QML scene to be synchronized with the rendering scene graph.</p>
<pre class="cpp">BezierCurve<span class="operator">::</span><span class="operator">~</span>BezierCurve()
{
}</pre>
<p>The BezierCurve class has no data members that need to be cleaned up so the destructor does nothing. It is worth mentioning that the rendering scene graph is managed by the scene graph it self, potentially in a different thread, so one should never retain <a href="qsgnode.html">QSGNode</a> references in the <a href="qquickitem.html">QQuickItem</a> class nor try to clean them up explicitly.</p>
<pre class="cpp"><span class="type">void</span> BezierCurve<span class="operator">::</span>setP1(<span class="keyword">const</span> <span class="type">QPointF</span> <span class="operator">&</span>p)
{
<span class="keyword">if</span> (p <span class="operator">=</span><span class="operator">=</span> m_p1)
<span class="keyword">return</span>;
m_p1 <span class="operator">=</span> p;
<span class="keyword">emit</span> p1Changed(p);
update();
}</pre>
<p>The setter function for the p1 property checks if the value is unchanged and exits early if this is the case. Then it updates the internal value and emits the changed signal. It then proceeds to call the <a href="qquickitem.html#update">QQuickItem::update</a>() function which will notify the rendering scene graph, that the state of this object has changed and needs to be synchronized with the rendering scene graph. A call to update() will result in a call to <a href="qquickitem.html#updatePaintNode">QQuickItem::updatePaintNode</a>() at a later time.</p>
<p>The other property setters are equivalent, and are omitted from this example.</p>
<pre class="cpp"><span class="type"><a href="qsgnode.html">QSGNode</a></span> <span class="operator">*</span>BezierCurve<span class="operator">::</span>updatePaintNode(<span class="type"><a href="qsgnode.html">QSGNode</a></span> <span class="operator">*</span>oldNode<span class="operator">,</span> UpdatePaintNodeData <span class="operator">*</span>)
{
<span class="type"><a href="qsggeometrynode.html">QSGGeometryNode</a></span> <span class="operator">*</span>node <span class="operator">=</span> <span class="number">0</span>;
<span class="type"><a href="qsggeometry.html">QSGGeometry</a></span> <span class="operator">*</span>geometry <span class="operator">=</span> <span class="number">0</span>;
<span class="keyword">if</span> (<span class="operator">!</span>oldNode) {
node <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qsggeometrynode.html">QSGGeometryNode</a></span>;</pre>
<p>The updatePaintNode() function is the primary integration point for synchronizing the state of the QML scene with the rendering scene graph. The function gets passed a <a href="qsgnode.html">QSGNode</a> which is the instance that was returned on the last call to the function. It will be null the first time the function gets called and we create our <a href="qsggeometrynode.html">QSGGeometryNode</a> which we will fill with geometry and a material.</p>
<pre class="cpp"> geometry <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qsggeometry.html">QSGGeometry</a></span>(<span class="type"><a href="qsggeometry.html">QSGGeometry</a></span><span class="operator">::</span>defaultAttributes_Point2D()<span class="operator">,</span> m_segmentCount);
geometry<span class="operator">-</span><span class="operator">></span>setLineWidth(<span class="number">2</span>);
geometry<span class="operator">-</span><span class="operator">></span>setDrawingMode(GL_LINE_STRIP);
node<span class="operator">-</span><span class="operator">></span>setGeometry(geometry);
node<span class="operator">-</span><span class="operator">></span>setFlag(<span class="type"><a href="qsgnode.html">QSGNode</a></span><span class="operator">::</span>OwnsGeometry);</pre>
<p>We then create the geometry and add it to the node. The first argument to the <a href="qsggeometry.html">QSGGeometry</a> constructor is a definition of the vertex type, called an "attribute set". Since the graphics often used in QML centers around a few common standard attribute sets, these are provided by default. Here we use the Point2D attribute set which has two floats, one for x coordinates and one for y coordinates. The second argument is the vertex count.</p>
<p>Custom attribute sets can also created, but that is not covered in this example.</p>
<p>Since we do not have any special needs for memory managing the geometry, we specify that the <a href="qsggeometrynode.html">QSGGeometryNode</a> should own the geometry.</p>
<p>To minimize allocations, reduce memory fragmentation and improve performance, it would also be possible to make the geometry a member of a <a href="qsggeometrynode.html">QSGGeometryNode</a> subclass, in which case, we would not have set the <a href="qsgnode.html#Flag-enum">QSGGeometryNode::OwnsGeometry</a> flag.</p>
<pre class="cpp"> <span class="type"><a href="qsgflatcolormaterial.html">QSGFlatColorMaterial</a></span> <span class="operator">*</span>material <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="qsgflatcolormaterial.html">QSGFlatColorMaterial</a></span>;
material<span class="operator">-</span><span class="operator">></span>setColor(<span class="type">QColor</span>(<span class="number">255</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span>));
node<span class="operator">-</span><span class="operator">></span>setMaterial(material);
node<span class="operator">-</span><span class="operator">></span>setFlag(<span class="type"><a href="qsgnode.html">QSGNode</a></span><span class="operator">::</span>OwnsMaterial);</pre>
<p>The scene graph API provides a few commonly used material implementations. In this example we use the <a href="qsgflatcolormaterial.html">QSGFlatColorMaterial</a> which will fill the shape defined by the geometry with a solid color. Again we pass the ownership of the material to the node, so it can be cleaned up by the scene graph.</p>
<pre class="cpp"> } <span class="keyword">else</span> {
node <span class="operator">=</span> <span class="keyword">static_cast</span><span class="operator"><</span><span class="type"><a href="qsggeometrynode.html">QSGGeometryNode</a></span> <span class="operator">*</span><span class="operator">></span>(oldNode);
geometry <span class="operator">=</span> node<span class="operator">-</span><span class="operator">></span>geometry();
geometry<span class="operator">-</span><span class="operator">></span>allocate(m_segmentCount);
}</pre>
<p>In the case where the QML item has changed and we only want to modify the existing node's geometry, we cast the <code>oldNode</code> to a <a href="qsggeometrynode.html">QSGGeometryNode</a> instance and extract it's geometry. In case the segment count has changed, we call <a href="qsggeometry.html#allocate">QSGGeometry::allocate</a>() to make sure it has the right number of vertices.</p>
<pre class="cpp"> <span class="type">QRectF</span> bounds <span class="operator">=</span> boundingRect();
<span class="type"><a href="qsggeometry.html">QSGGeometry</a></span><span class="operator">::</span>Point2D <span class="operator">*</span>vertices <span class="operator">=</span> geometry<span class="operator">-</span><span class="operator">></span>vertexDataAsPoint2D();
<span class="keyword">for</span> (<span class="type">int</span> i <span class="operator">=</span> <span class="number">0</span>; i <span class="operator"><</span> m_segmentCount; <span class="operator">+</span><span class="operator">+</span>i) {
<span class="type">qreal</span> t <span class="operator">=</span> i <span class="operator">/</span> <span class="type">qreal</span>(m_segmentCount <span class="operator">-</span> <span class="number">1</span>);
<span class="type">qreal</span> invt <span class="operator">=</span> <span class="number">1</span> <span class="operator">-</span> t;
<span class="type">QPointF</span> pos <span class="operator">=</span> invt <span class="operator">*</span> invt <span class="operator">*</span> invt <span class="operator">*</span> m_p1
<span class="operator">+</span> <span class="number">3</span> <span class="operator">*</span> invt <span class="operator">*</span> invt <span class="operator">*</span> t <span class="operator">*</span> m_p2
<span class="operator">+</span> <span class="number">3</span> <span class="operator">*</span> invt <span class="operator">*</span> t <span class="operator">*</span> t <span class="operator">*</span> m_p3
<span class="operator">+</span> t <span class="operator">*</span> t <span class="operator">*</span> t <span class="operator">*</span> m_p4;
<span class="type">float</span> x <span class="operator">=</span> bounds<span class="operator">.</span>x() <span class="operator">+</span> pos<span class="operator">.</span>x() <span class="operator">*</span> bounds<span class="operator">.</span>width();
<span class="type">float</span> y <span class="operator">=</span> bounds<span class="operator">.</span>y() <span class="operator">+</span> pos<span class="operator">.</span>y() <span class="operator">*</span> bounds<span class="operator">.</span>height();
vertices<span class="operator">[</span>i<span class="operator">]</span><span class="operator">.</span>set(x<span class="operator">,</span> y);
}
node<span class="operator">-</span><span class="operator">></span>markDirty(<span class="type"><a href="qsgnode.html">QSGNode</a></span><span class="operator">::</span>DirtyGeometry);</pre>
<p>To fill the geometry, we first extract the vertex array from it. Since we are using one of the default attribute sets, we can use the convenience function <a href="qsggeometry.html#vertexDataAsPoint2D">QSGGeometry::vertexDataAsPoint2D</a>(). Then we go through each segment and calculate its position and write that value to the vertex.</p>
<pre class="cpp"> <span class="keyword">return</span> node;
}</pre>
<p>In the end of the function, we return the node so the scene graph can render it.</p>
<a name="application-entry-point"></a>
<h2 id="application-entry-point">Application Entry-Point</h2>
<pre class="cpp"><span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span><span class="operator">*</span>argv)
{
<span class="type">QGuiApplication</span> app(argc<span class="operator">,</span> argv);
qmlRegisterType<span class="operator"><</span>BezierCurve<span class="operator">></span>(<span class="string">"CustomGeometry"</span><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">"BezierCurve"</span>);
<span class="type"><a href="qquickview.html">QQuickView</a></span> view;
<span class="type">QSurfaceFormat</span> format <span class="operator">=</span> view<span class="operator">.</span>format();
format<span class="operator">.</span>setSamples(<span class="number">16</span>);
view<span class="operator">.</span>setFormat(format);
view<span class="operator">.</span>setSource(<span class="type">QUrl</span>(<span class="string">"qrc:///scenegraph/customgeometry/main.qml"</span>));
view<span class="operator">.</span>show();
app<span class="operator">.</span>exec();
}</pre>
<p>The application is a straightforward QML application, with a QGuiApplication and a <a href="qquickview.html">QQuickView</a> that we pass a .qml file. To make use of the BezierCurve item, we need to register it in the QML engine, using the qmlRegisterType() function. We give it the name BezierCurve and make it part of the <code>CustomGeometry 1.0</code> module.</p>
<p>As the bezier curve is drawn using GL_LINE_STRIP, we specify that the view should be multisampled to get antialiasing. This is not required, but it will make the item look a bit nicer on hardware that supports it. Multisampling is not enabled by default because it often results in higher memory usage.</p>
<a name="using-the-item"></a>
<h2 id="using-the-item">Using the Item</h2>
<pre class="qml">import QtQuick 2.0
import CustomGeometry 1.0</pre>
<p>Our .qml file imports the <code>QtQuick 2.0</code> module to get the standard types and also our own <code>CustomGeometry 1.0</code> module which contains our newly created BezierCurve objects.</p>
<pre class="qml"><span class="type"><a href="qml-qtquick-item.html">Item</a></span> {
<span class="name">width</span>: <span class="number">300</span>
<span class="name">height</span>: <span class="number">200</span>
<span class="type">BezierCurve</span> {
<span class="name">id</span>: <span class="name">line</span>
<span class="name">anchors</span>.fill: <span class="name">parent</span>
<span class="name">anchors</span>.margins: <span class="number">20</span></pre>
<p>Then we create the our root item and an instance of the BezierCurve which we anchor to fill the root.</p>
<pre class="qml"> property <span class="type">real</span> <span class="name">t</span>
SequentialAnimation on <span class="name">t</span> {
<span class="type"><a href="qml-qtquick-numberanimation.html">NumberAnimation</a></span> { <span class="name">to</span>: <span class="number">1</span>; <span class="name">duration</span>: <span class="number">2000</span>; <span class="name">easing</span>.type: <span class="name">Easing</span>.<span class="name">InOutQuad</span> }
<span class="type"><a href="qml-qtquick-numberanimation.html">NumberAnimation</a></span> { <span class="name">to</span>: <span class="number">0</span>; <span class="name">duration</span>: <span class="number">2000</span>; <span class="name">easing</span>.type: <span class="name">Easing</span>.<span class="name">InOutQuad</span> }
<span class="name">loops</span>: <span class="name">Animation</span>.<span class="name">Infinite</span>
}
<span class="name">p2</span>: <span class="name">Qt</span>.<span class="name">point</span>(<span class="name">t</span>, <span class="number">1</span> <span class="operator">-</span> <span class="name">t</span>)
<span class="name">p3</span>: <span class="name">Qt</span>.<span class="name">point</span>(<span class="number">1</span> <span class="operator">-</span> <span class="name">t</span>, <span class="name">t</span>)
}</pre>
<p>To make the example a bit more interesting we add an animation to change the two control points in the curve. The end points stay unchanged.</p>
<pre class="qml"> <span class="type"><a href="qml-qtquick-text.html">Text</a></span> {
<span class="name">anchors</span>.bottom: <span class="name">line</span>.<span class="name">bottom</span>
<span class="name">x</span>: <span class="number">20</span>
<span class="name">width</span>: <span class="name">parent</span>.<span class="name">width</span> <span class="operator">-</span> <span class="number">40</span>
<span class="name">wrapMode</span>: <span class="name">Text</span>.<span class="name">WordWrap</span>
<span class="name">text</span>: <span class="string">"This curve is a custom scene graph item, implemented using GL_LINE_STRIP"</span>
}
}</pre>
<p>Finally we overlay a short text outlining what the example shows.</p>
<p>Files:</p>
<ul>
<li><a href="qtquick-scenegraph-customgeometry-beziercurve-cpp.html">scenegraph/customgeometry/beziercurve.cpp</a></li>
<li><a href="qtquick-scenegraph-customgeometry-beziercurve-h.html">scenegraph/customgeometry/beziercurve.h</a></li>
<li><a href="qtquick-scenegraph-customgeometry-main-qml.html">scenegraph/customgeometry/main.qml</a></li>
<li><a href="qtquick-scenegraph-customgeometry-main-cpp.html">scenegraph/customgeometry/main.cpp</a></li>
<li><a href="qtquick-scenegraph-customgeometry-customgeometry-pro.html">scenegraph/customgeometry/customgeometry.pro</a></li>
<li><a href="qtquick-scenegraph-customgeometry-customgeometry-qrc.html">scenegraph/customgeometry/customgeometry.qrc</a></li>
</ul>
</div>
<!-- @@@scenegraph/customgeometry -->
</div>
</div>
</div>
</div>
</div>
<div class="footer">
<p>
<acronym title="Copyright">©</acronym> 2015 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>
|