Update obsolete contact address.
[profile/ivi/qtxmlpatterns.git] / doc / src / examples / filetree.qdoc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the documentation of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:FDL$
10 ** GNU Free Documentation License
11 ** Alternatively, this file may be used under the terms of the GNU Free
12 ** Documentation License version 1.3 as published by the Free Software
13 ** Foundation and appearing in the file included in the packaging of
14 ** this file.
15 **
16 ** Other Usage
17 ** Alternatively, this file may be used in accordance with the terms
18 ** and conditions contained in a signed written agreement between you
19 ** and Nokia.
20 **
21 **
22 **
23 **
24 ** $QT_END_LICENSE$
25 **
26 ****************************************************************************/
27
28 /*!
29   \example xmlpatterns/filetree
30   \title File System Example
31
32   This example shows how to use QtXmlPatterns for querying non-XML
33   data that is modeled to look like XML. 
34
35   \tableofcontents
36
37   \section1 Introduction
38
39   The example models your computer's file system to look like XML and
40   allows you to query the file system with XQuery. Suppose we want to
41   find all the \c{cpp} files in the subtree beginning at
42   \c{/filetree}:
43
44   \image filetree_1-example.png
45
46   \section2 The User Inteface
47
48   The example is shown below. First, we use \c{File->Open Directory}
49   (not shown) to select the \c{/filetree} directory. Then we use the
50   combobox on the right to select the XQuery that searches for \c{cpp}
51   files (\c{listCPPFiles.xq}).  Selecting an XQuery runs the query,
52   which in this case traverses the model looking for all the \c{cpp}
53   files. The XQuery text and the query results are shown on the right:
54
55   \image filetree_2-example.png
56
57   Don't be mislead by the XML representation of the \c{/filetree}
58   directory shown on the left. This is not the node model itself but
59   the XML obtained by traversing the node model and outputting it as
60   XML. Constructing and using the custom node model is explained in
61   the code walk-through.
62
63   \section2 Running your own XQueries
64
65   You can write your own XQuery files and run them in the example
66   program. The file \c{xmlpatterns/filetree/queries.qrc} is the \l{The
67   Qt Resource System} {resource file} for this example. It is used in
68   \c{main.cpp} (\c{Q_INIT_RESOURCE(queries);}). It lists the XQuery
69   files (\c{.xq}) that can be selected in the combobox.
70
71   \quotefromfile examples/xmlpatterns/filetree/queries.qrc
72   \printuntil
73
74   To add your own queries to the example's combobox, store your
75   \c{.xq} files in the \c{examples/xmlpatterns/filetree/queries}
76   directory and add them to \c{queries.qrc} as shown above.
77
78   \section1 Code Walk-Through
79
80   The strategy is to create a custom node model that represents the
81   directory tree of the computer's file system. That tree structure is
82   non-XML data. The custom node model must have the same callback
83   interface as the XML node models that the QtXmlPatterns query engine
84   uses to execute queries. The query engine can then traverse the
85   custom node model as if it were traversing the node model built from
86   an XML document.
87
88   The required callback interface is in QAbstractXmlNodeModel, so we
89   create a custom node model by subclassing QAbstractXmlNodeModel and
90   providing implementations for its pure virtual functions. For many
91   cases, the implementations of several of the virtual functions are
92   always the same, so QtXmlPatterns also provides QSimpleXmlNodeModel,
93   which subclasses QAbstractXmlNodeModel and provides implementations
94   for the callback functions that you can ignore. By subclassing
95   QSimpleXmlNodeModel instead of QAbstractXmlNodeModel, you can reduce
96   development time.
97
98   \section2 The Custom Node Model Class: FileTree
99
100   The custom node model for this example is class \c{FileTree}, which
101   is derived from QSimpleXmlNodeModel. \c{FileTree} implements all the
102   callback functions that don't have standard implementations in
103   QSimpleXmlNodeModel. When you implement your own custom node model,
104   you must provide implementations for these callback functions:
105
106   \snippet examples/xmlpatterns/filetree/filetree.h 0
107   \snippet examples/xmlpatterns/filetree/filetree.h 1
108
109   The \c{FileTree} class declares four data members:
110   
111   \snippet examples/xmlpatterns/filetree/filetree.h 2
112
113   The QVector \c{m_fileInfos} will contain the node model. Each
114   QFileInfo in the vector will represent a file or a directory in the
115   file system. At this point it is instructive to note that although
116   the node model class for this example (\c{FileTree}) actually builds
117   and contains the custom node model, building the custom node model
118   isn't always required. The node model class for the \l{QObject XML
119   Model Example} {QObject node model example} does not build its node
120   model but instead uses an already existing QObject tree as its node
121   model and just implements the callback interface for that already
122   existing data structure. In this file system example, however,
123   although we have an already existing data structure, i.e. the file
124   system, that data structure is not in memory and is not in a form we
125   can use. So we must build an analog of the file system in memory
126   from instances of QFileInfo, and we use that analog as the custom
127   node model.
128   
129   The two sets of flags, \c{m_filterAllowAll} and \c{m_sortFlags},
130   contain OR'ed flags from QDir::Filters and QDir::SortFlags
131   respectively. They are set by the \c{FileTree} constructor and used
132   in calls to QDir::entryInfoList() for getting the child list for a
133   directory node, i.e. a QFileInfoList containing the file and
134   directory nodes for all the immediate children of a directory.
135
136   The QVector \c{m_names} is an auxiliary component of the node
137   model. It holds the XML element and attribute names (QXmlName) for
138   all the node types that will be found in the node model. \c{m_names}
139   is indexed by the enum \c{FileTree::Type}, which specifies the node
140   types:
141
142   \target Node_Type
143   \snippet examples/xmlpatterns/filetree/filetree.h 4
144
145   \c{Directory} and \c{File} will represent the XML element nodes for
146   directories and files respectively, and the other enum values will
147   represent the XML attribute nodes for a file's path, name, suffix,
148   its size in bytes, and its mime type. The \c{FileTree} constructor
149   initializes \c{m_names} with an appropriate QXmlName for each
150   element and attribute type:
151
152   \snippet examples/xmlpatterns/filetree/filetree.cpp 2
153
154   Note that the constructor does \e{not} pre-build the entire node
155   model. Instead, the node model is built \e{incrementally} as the
156   query engine evaluates a query. To see how the query engine causes
157   the node model to be built incrementally, see \l{Building And
158   Traversing The Node Model}. To see how the query engine accesses the
159   node model, see \l{Accessing the node model}. See also: \l{Node
160   Model Building Strategy}.
161
162   \section3 Accessing The Node Model
163
164   Since the node model is stored outside the query engine in the
165   \c{FileTree} class, the query engine knows nothing about it and can
166   only access it by calling functions in the callback interface. When
167   the query engine calls any callback function to access data in the
168   node model, it passes a QXmlNodeModelIndex to identify the node in
169   the node model that it wants to access.  Hence all the virtual
170   functions in the callback interface use a QXmlNodeModelIndex to
171   uniquely identify a node in the model.
172
173   We use the index of a QFileInfo in \c{m_fileInfos} to uniquely
174   identify a node in the node model. To get the QXmlNodeModelIndex for
175   a QFileInfo, the class uses the private function \c{toNodeIndex()}:
176
177   \target main toNodeIndex
178   \snippet examples/xmlpatterns/filetree/filetree.cpp 1
179
180   It searches the \c{m_fileInfos} vector for a QFileInfo that matches
181   \c{fileInfo}. If a match is found, its array index is passed to
182   QAbstractXmlNodeModel::createIndex() as the \c data value for the
183   QXmlNodeIndex. If no match is found, the unmatched QFileInfo is
184   appended to the vector, so this function is also doing the actual
185   incremental model building (see \l{Building And Traversing The Node
186   Model}).
187
188   Note that \c{toNodeIndex()} gets a \l{Node_Type} {node type} as the
189   second parameter, which it just passes on to
190   \l{QAbstractXmlNodeModel::createIndex()} {createIndex()} as the
191   \c{additionalData} value. Logically, this second parameter
192   represents a second dimension in the node model, where the first
193   dimension represents the \e element nodes, and the second dimension
194   represents each element's attribute nodes. The meaning is that each
195   QFileInfo in the \c{m_fileInfos} vector can represent an \e{element}
196   node \e{and} one or more \e{attribute} nodes. In particular, the
197   QFileInfo for a file will contain the values for the attribute nodes
198   path, name, suffix, size, and mime type (see
199   \c{FileTree::attributes()}). Since the attributes are contained in
200   the QFileInfo of the file element, there aren't actually any
201   attribute nodes in the node model. Hence, we can use a QVector for
202   \c{m_fileInfos}.
203
204   A convenience overloading of \l{toNodeIndex of convenience}
205   {toNodeIndex()} is also called in several places, wherever it is
206   known that the QXmlNodeModelIndex being requested is for a directory
207   or a file and not for an attribute. The convenience function takes
208   only the QFileInfo parameter and calls the other \l{main toNodeIndex}
209   {toNodeIndex()}, after obtaining either the Directory or File node
210   type directly from the QFileInfo:
211
212   \target toNodeIndex of convenience
213   \snippet examples/xmlpatterns/filetree/filetree.cpp 0
214
215   Note that the auxiliary vector \c{m_names} is accessed using the
216   \l{Node_Type} {node type}, for example:
217
218   \snippet examples/xmlpatterns/filetree/filetree.cpp 3
219
220   Most of the virtual functions in the callback interface are as
221   simple as the ones described so far, but the callback function used
222   for traversing (and building) the node model is more complex.
223
224   \section3 Building And Traversing The Node Model 
225
226   The node model in \c{FileTree} is not fully built before the query
227   engine begins evaluating the query. In fact, when the query engine
228   begins evaluating its first query, the only node in the node model
229   is the one representing the root directory for the selected part of
230   the file system. See \l{The UI Class: MainWindow} below for details
231   about how the UI triggers creation of the model.
232
233   The query engine builds the node model incrementally each time it
234   calls the \l{next node on axis} {nextFromSimpleAxis()} callback
235   function, as it traverses the node model to evaluate a query. Thus
236   the query engine only builds the region of the node model that it
237   needs for evaluating the query.
238
239   \l{next node on axis} {nextFromSimpleAxis()} takes an
240   \l{QAbstractXmlNodeModel::SimpleAxis} {axis identifier} and a
241   \l{QXmlNodeModelIndex} {node identifier} as parameters. The
242   \l{QXmlNodeModelIndex} {node identifier} represents the \e{context
243   node} (i.e. the query engine's current location in the model), and
244   the \l{QAbstractXmlNodeModel::SimpleAxis} {axis identifier}
245   represents the direction we want to move from the context node. The
246   function finds the appropriate next node and returns its
247   QXmlNodeModelIndex.
248
249   \l{next node on axis} {nextFromSimpleAxis()} is where most of the
250   work of implementing a custom node model will be required. The
251   obvious way to do it is to use a switch statement with a case for
252   each \l{QAbstractXmlNodeModel::SimpleAxis} {axis}.
253
254   \target next node on axis
255   \snippet examples/xmlpatterns/filetree/filetree.cpp 4
256
257   The first thing this function does is call \l{to file info}
258   {toFileInfo()} to get the QFileInfo of the context node. The use of
259   QVector::at() here is guaranteed to succeed because the context node
260   must already be in the node model, and hence must have a QFileInfo
261   in \c{m_fileInfos}.
262
263   \target to file info
264   \snippet examples/xmlpatterns/filetree/filetree.cpp 6
265
266   The \l{QAbstractXmlNodeModel::Parent} {Parent} case looks up the
267   context node's parent by constructing a QFileInfo from the context
268   node's \l{QFileInfo::absoluteFilePath()} {path} and passing it to
269   \l{main toNodeIndex} {toNodeIndex()} to find the QFileInfo in
270   \c{m_fileInfos}.
271
272   The \l{QAbstractXmlNodeModel::FirstChild} {FirstChild} case requires
273   that the context node must be a directory, because a file doesn't
274   have children. If the context node is not a directory, a default
275   constructed QXmlNodeModelIndex is returned. Otherwise,
276   QDir::entryInfoList() constructs a QFileInfoList of the context
277   node's children. The first QFileInfo in the list is passed to
278   \l{toNodeIndex of convenience} {toNodeIndex()} to get its
279   QXmlNodeModelIndex. Note that this will add the child to the node
280   model, if it isn't in the model yet.
281
282   The \l{QAbstractXmlNodeModel::PreviousSibling} {PreviousSibling} and
283   \l{QAbstractXmlNodeModel::NextSibling} {NextSibling} cases call the
284   \l{nextSibling helper} {nextSibling() helper function}. It takes the
285   QXmlNodeModelIndex of the context node, the QFileInfo of the context
286   node, and an offest of +1 or -1. The context node is a child of some
287   parent, so the function gets the parent and then gets the child list
288   for the parent. The child list is searched to find the QFileInfo of
289   the context node. It must be there. Then the offset is applied, -1
290   for the previous sibling and +1 for the next sibling. The resulting
291   index is passed to \l{toNodeIndex of convenience} {toNodeIndex()} to
292   get its QXmlNodeModelIndex. Note again that this will add the
293   sibling to the node model, if it isn't in the model yet.
294
295   \target nextSibling helper
296   \snippet examples/xmlpatterns/filetree/filetree.cpp 5
297
298   \section2 The UI Class: MainWindow
299
300   The example's UI is a conventional Qt GUI application inheriting
301   QMainWindow and the Ui_MainWindow base class generated by 
302   \l{Qt Designer Manual} {Qt Designer}.
303
304   \snippet examples/xmlpatterns/filetree/mainwindow.h 0
305
306   It contains the custom node model (\c{m_fileTree}) and an instance
307   of QXmlNodeModelIndex (\c{m_fileNode}) used for holding the node
308   index for the root of the file system subtree. \c{m_fileNode} will
309   be bound to a $variable in the XQuery to be evaluated.
310
311   Two actions of interest are handled by slot functions: \l{Selecting
312   A Directory To Model} and \l{Selecting And Running An XQuery}.
313
314   \section3 Selecting A Directory To Model
315
316   The user selects \c{File->Open Directory} to choose a directory to
317   be loaded into the custom node model. Choosing a directory signals
318   the \c{on_actionOpenDirectory_triggered()} slot:
319
320   \snippet examples/xmlpatterns/filetree/mainwindow.cpp 1
321
322   The slot function simply calls the private function
323   \c{loadDirectory()} with the path of the chosen directory:
324
325   \target the standard code pattern
326   \snippet examples/xmlpatterns/filetree/mainwindow.cpp 4
327
328   \c{loadDirectory()} demonstrates a standard code pattern for using
329   QtXmlPatterns programatically. First it gets the node model index
330   for the root of the selected directory. Then it creates an instance
331   of QXmlQuery and calls QXmlQuery::bindVariable() to bind the node
332   index to the XQuery variable \c{$fileTree}. It then calls
333   QXmlQuery::setQuery() to load the XQuery text.
334
335   \note QXmlQuery::bindVariable() must be called \e before calling
336   QXmlQuery::setQuery(), which loads and parses the XQuery text and
337   must have access to the variable binding as the text is parsed.
338
339   The next lines create an output device for outputting the query
340   result, which is then used to create a QXmlFormatter to format the
341   query result as XML. QXmlQuery::evaluateTo() is called to run the
342   query, and the formatted XML output is displayed in the left panel
343   of the UI window.
344
345   Finally, the private function \l{Selecting And Running An XQuery}
346   {evaluateResult()} is called to run the currently selected XQuery
347   over the custom node model.
348
349   \note As described in \l{Building And Traversing The Node Model},
350   the \c FileTree class wants to build the custom node model
351   incrementally as it evaluates the XQuery. But, because the
352   \c{loadDirectory()} function runs the \c{wholeTree.xq} XQuery, it
353   actually builds the entire node model anyway. See \l{Node Model
354   Building Strategy} for a discussion about building your custom node
355   model.
356
357   \section3 Selecting And Running An XQuery
358
359   The user chooses an XQuery from the menu in the combobox on the
360   right. Choosing an XQuery signals the
361   \c{on_queryBox_currentIndexChanged()} slot:
362   
363   \snippet examples/xmlpatterns/filetree/mainwindow.cpp 2
364
365   The slot function opens and loads the query file and then calls the
366   private function \c{evaluateResult()} to run the query:
367   
368   \snippet examples/xmlpatterns/filetree/mainwindow.cpp 3
369
370   \c{evaluateResult()} is a second example of the same code pattern
371   shown in \l{the standard code pattern} {loadDirectory()}. In this
372   case, it runs the XQuery currently selected in the combobox instead
373   of \c{qrc:/queries/wholeTree.xq}, and it outputs the query result to
374   the panel on the lower right of the UI window.
375
376   \section2 Node Model Building Strategy
377
378   We saw that the \l{The Custom Node Model Class: FileTree} {FileTree}
379   tries to build its custom node model incrementally, but we also saw
380   that the \l{the standard code pattern} {MainWindow::loadDirectory()}
381   function in the UI class immediately subverts the incremental build
382   by running the \c{wholeTree.xq} XQuery, which traverses the entire
383   selected directory, thereby causing the entire node model to be
384   built.
385
386   If we want to preserve the incremental build capability of the
387   \c{FileTree} class, we can strip the running of \c{wholeTree.xq} out
388   of \l{the standard code pattern} {MainWindow::loadDirectory()}:
389
390   \snippet examples/xmlpatterns/filetree/mainwindow.cpp 5
391   \snippet examples/xmlpatterns/filetree/mainwindow.cpp 6
392
393   Note, however, that \c{FileTree} doesn't have the capability of
394   deleting all or part of the node model. The node model, once built,
395   is only deleted when the \c{FileTree} instance goes out of scope.
396
397   In this example, each element node in the node model represents a
398   directory or a file in the computer's file system, and each node is
399   represented by an instance of QFileInfo. An instance of QFileInfo is
400   not costly to produce, but you might imagine a node model where
401   building new nodes is very costly. In such cases, the capability to
402   build the node model incrementally is important, because it allows
403   us to only build the region of the model we need for evaluating the
404   query. In other cases, it will be simpler to just build the entire
405   node model. 
406
407 */