|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include <QVector> |
|
43 |
|
44 #include "qabstractxmlnodemodel_p.h" |
|
45 #include "qabstractxmlreceiver.h" |
|
46 #include "qcommonvalues_p.h" |
|
47 #include "qemptyiterator_p.h" |
|
48 #include "qitemmappingiterator_p.h" |
|
49 #include "qitem_p.h" |
|
50 #include "qnamespaceresolver_p.h" |
|
51 #include "qsequencemappingiterator_p.h" |
|
52 #include "qsingletoniterator_p.h" |
|
53 |
|
54 #include "qabstractxmlnodemodel.h" |
|
55 |
|
56 QT_BEGIN_NAMESPACE |
|
57 |
|
58 using namespace QPatternist; |
|
59 |
|
60 typedef QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > QXmlNodeModelIndexIteratorPointer; |
|
61 |
|
62 /** |
|
63 * @file |
|
64 * @short Contains the implementation of QAbstractXmlNodeModel. |
|
65 */ |
|
66 |
|
67 bool QAbstractXmlNodeModel::isIgnorableInDeepEqual(const QXmlNodeModelIndex &n) |
|
68 { |
|
69 Q_ASSERT(!n.isNull()); |
|
70 const QXmlNodeModelIndex::NodeKind nk = n.kind(); |
|
71 return nk == QXmlNodeModelIndex::ProcessingInstruction || |
|
72 nk == QXmlNodeModelIndex::Comment; |
|
73 } |
|
74 |
|
75 |
|
76 /*! |
|
77 \class QAbstractXmlNodeModel |
|
78 \brief The QAbstractXmlNodeModel class is an abstract base class for modeling non-XML data to look like XML for QXmlQuery. |
|
79 \threadsafe |
|
80 \since 4.4 |
|
81 \ingroup xml-tools |
|
82 |
|
83 The QAbstractXmlNodeModel specifies the interface that a node model |
|
84 must implement for that node model be accessible to the query engine |
|
85 for processing XQuery queries. A node model represents data as a |
|
86 structure that can be queried as if the data were XML. |
|
87 |
|
88 The node model represented by a subclass of QAbstractXmlNodeModel is |
|
89 meant to be accessed by the QtXmlPatterns query engine. If the API |
|
90 seems a little strange in a few places, it is because the member |
|
91 functions are called by the query engine as it evaluates an |
|
92 XQuery. They aren't meant to be used programatically. |
|
93 |
|
94 \section1 Usage |
|
95 |
|
96 QAbstractXmlNodeModel bridges the gap between the arbitrary structure |
|
97 of the non-XML data to be queried and the well-defined structure of |
|
98 XML data understood by QXmlQuery. |
|
99 |
|
100 Consider a chemistry application that reads the file \c |
|
101 chemistryData, which contains non-XML data that represents a |
|
102 chemical structure composed of molecules and atoms. The application |
|
103 will query this chemistry data with an XQuery it reads from file \c |
|
104 queryFile. We write a custom subclass of QAbstractXmlNodeModel (\c |
|
105 ChemistryNodeModel) that reads \c chemistryData and builds a data |
|
106 structure, perhaps composed of objects of our own classes \c |
|
107 molecule and \c atom. Clearly, this data structure is not XML. Our |
|
108 custom subclass will know how to traverse this non-XML structure and |
|
109 present it through the \l |
|
110 {http://www.w3.org/TR/xpath-datamodel/}{XPath Data Model interface}. |
|
111 |
|
112 \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlnodemodel.cpp 1 |
|
113 |
|
114 The application first creates an instance of QXmlQuery and calls \l |
|
115 {QXmlQuery::setQuery()}{setQuery()} to read \c queryFile containing |
|
116 the XQuery we want to run. Then it creates an instance of our custom |
|
117 node model class, \c ChemistryNodeModel, which is a subclass of |
|
118 QAbstractXmlNodeModel. Its constructor is called with the \l |
|
119 {QXmlNamePool} {name pool} obtained from our QXmlQuery, and with the |
|
120 \c chemistryFile containing the structure of molecules and atoms to |
|
121 be queried. The \l {QXmlNamePool} {name pool} is required because |
|
122 our custom node model has the member function \l |
|
123 {QAbstractXmlNodeModel::name()} {name()}, which returns the \l |
|
124 {QXmlName} {name} of any node in the model. The \l {QXmlQuery} |
|
125 {query} and the custom node model must use the same name pool for |
|
126 constructing these \l {QXmlName} {names}. The constructor would then |
|
127 read \c chemistryFile and build the custom node model structure. |
|
128 |
|
129 To connect the \c query to the custom node model, we must bind a |
|
130 variable name used in the query to a node in the model. The variable |
|
131 can then be used in the query as a starting node. First, an \l |
|
132 {QXmlNodeModelIndex} {index} for the desired starting node is |
|
133 retrieved by calling QAbstractXmlNodeModel::createIndex(). Then the |
|
134 index is bound to a variable name, in this case \c queryRoot, by |
|
135 passing the name and the index to QXmlQuery::bindVariable(). The |
|
136 query can then use a variable reference \c $queryRoot to refer to |
|
137 the starting node. Note that if the \l {QXmlQuery} {query} uses |
|
138 multiple variable references, a call to QXmlQuery::bindVariable() |
|
139 is required to bind each different variable name to a node in the |
|
140 model. |
|
141 |
|
142 The query is executed when the application calls one of the |
|
143 QXmlQuery evaluation functions. The application uses |
|
144 QXmlQuery::evaluateTo(QAbstractXmlReceiver *), because it then uses |
|
145 a \l {QXmlSerializer} {serializer} to out the query result as XML to |
|
146 \c stdout. We could have used QXmlQuery::evaluateTo(QXmlResultItems |
|
147 *) to get a list of result items, or |
|
148 QXmlQuery::evaluateTo(QStringList *) if the query evaluated to a |
|
149 sequence of \c {xs:string} values. |
|
150 |
|
151 During query execution, the engine iterates over the node model |
|
152 using nextFromSimpleAxis() to get the \l {QXmlNodeModelIndex} |
|
153 {index} of the next node to be visited. The engine can get the name |
|
154 of a node by calling name() with the node's \l {QXmlNodeModelIndex} |
|
155 {index}. stringValue(), baseUri(), documentUri() and kind() are also |
|
156 called as needed with a node \l {QXmlNodeModelIndex} {index}. |
|
157 |
|
158 The example demonstrates the standard pattern for using a subclass |
|
159 of QAbstractXmlNodeModel in combination with QXmlQuery to perform |
|
160 an XQuery. |
|
161 |
|
162 \list 1 |
|
163 |
|
164 \o Instantiate QXmlQuery and give it the XQuery to be run; |
|
165 |
|
166 \o Instantiate a subclass of QAbstractXmlNodeModel or |
|
167 QSimpleXmlNodeModel; |
|
168 |
|
169 \o Retrieve a QXmlNodeModelIndex for the node in the model where |
|
170 the QXmlQuery should start the query; |
|
171 |
|
172 \o Use QXmlQuery::bindVariable() to bind the QXmlNodeModelIndex |
|
173 to \c {$variable name}; |
|
174 |
|
175 \o Call one of the QXmlQuery evaluation functions to run the |
|
176 query. |
|
177 |
|
178 \endlist |
|
179 |
|
180 \section1 Subclassing |
|
181 |
|
182 Because the \l {http://www.w3.org/TR/xpath-datamodel/}{XPath Data Model |
|
183 interface} presented by QAbstractXmlNodeModel allows QXmlQuery to |
|
184 operate on non-XML data as if it were XML, implementing subclasses |
|
185 of QAbstractXmlNodeModel can involve a significant amount of |
|
186 work. The QSimpleXmlNodeModel class is provided to simplify the |
|
187 implementation for many common use cases. |
|
188 |
|
189 \section1 Thread Safety |
|
190 |
|
191 Because the node model can be accessed concurrently by threads in |
|
192 the QtXmlPatterns module, subclasses of QAbstractXmlNodeModel must |
|
193 be written to be \l{Reentrancy and Thread-Safety}{thread-safe}. |
|
194 Classes that simplify implementing thread-safety include QReadLocker |
|
195 and QWriteLocker. |
|
196 |
|
197 See the example \l{File System Example} for a demonstration. |
|
198 */ |
|
199 |
|
200 /*! |
|
201 \enum QXmlNodeModelIndex::Constants |
|
202 |
|
203 \value ForwardAxis All forward axes include this flag. |
|
204 \value ReverseAxis All reverse axes include this flag. |
|
205 */ |
|
206 |
|
207 /*! |
|
208 \enum QXmlNodeModelIndex::DocumentOrder |
|
209 |
|
210 Identifies the specific node comparison operator that should be |
|
211 used. |
|
212 |
|
213 \value Precedes Signifies the \c \<\< operator. Test whether the |
|
214 first operand precedes the second in the document. |
|
215 |
|
216 \value Follows Signifies the \c \>\> operator. Test whether the |
|
217 first operand follows the second in the document. |
|
218 |
|
219 \value Is Signifies the \c is operator. Test whether two nodes have |
|
220 the same node identity. |
|
221 */ |
|
222 |
|
223 /*! |
|
224 \enum QAbstractXmlNodeModel::SimpleAxis |
|
225 |
|
226 Four axes that each contain one node only. |
|
227 |
|
228 \value Parent The parent of the context node |
|
229 \value FirstChild The first child of the context node |
|
230 \value PreviousSibling The previous child of the context node |
|
231 \value NextSibling The next child of the context node |
|
232 */ |
|
233 |
|
234 /*! |
|
235 \enum QXmlNodeModelIndex::Axis |
|
236 \internal |
|
237 |
|
238 Identify the axes emanating from a node. |
|
239 |
|
240 The axes AxisChild, AxisDescendant, AxisAttribute, AxisSelf, |
|
241 AxisDescendantOrSelf, AxisFollowingSibling, and AxisFollowing are |
|
242 forward axes. |
|
243 |
|
244 The axes AxisParent, AxisAncestor, AxisPrecedingSibling, |
|
245 AxisPreceding and AxisAncestorOrSelf are reverse axes. |
|
246 |
|
247 \sa {http://www.w3.org/TR/xquery/#axes}{XQuery 1.0: An XML Query Language, 3.2.1.1 Axes} |
|
248 |
|
249 \value AxisChild The \c child axis. |
|
250 |
|
251 \value AxisDescendant The \c descendant axis. |
|
252 |
|
253 \value AxisAttribute The \c attribute axis. Note: There |
|
254 is a node kind named \c{Attribute}. |
|
255 |
|
256 \value AxisSelf The \c self axis. |
|
257 |
|
258 \value AxisDescendantOrSelf The \c descendant-or-self axis. |
|
259 |
|
260 \value AxisFollowingSibling The \c following-sibling axis. |
|
261 |
|
262 \value AxisNamespace The \c namespace axis. Note: Does |
|
263 not exist in XQuery; deprecated in |
|
264 XPath 2.0 (optionally supported); |
|
265 mandatory in XPath 1.0. |
|
266 |
|
267 \value AxisFollowing The \c following axis. |
|
268 |
|
269 \value AxisParent The \c parent axis. |
|
270 |
|
271 \value AxisAncestor The \c ancestor axis. |
|
272 |
|
273 \value AxisPrecedingSibling The \c preceding-sibling axis. |
|
274 |
|
275 \value AxisPreceding The \c preceding axis. |
|
276 |
|
277 \value AxisAncestorOrSelf The \c ancestor-or-self axis. |
|
278 */ |
|
279 |
|
280 using namespace QPatternist; |
|
281 |
|
282 /*! |
|
283 Default constructor. |
|
284 */ |
|
285 QAbstractXmlNodeModel::QAbstractXmlNodeModel() : d_ptr(0) |
|
286 { |
|
287 } |
|
288 |
|
289 /*! |
|
290 \internal |
|
291 |
|
292 Takes the d-pointer. |
|
293 |
|
294 */ |
|
295 QAbstractXmlNodeModel::QAbstractXmlNodeModel(QAbstractXmlNodeModelPrivate *d) : d_ptr(d) |
|
296 { |
|
297 } |
|
298 |
|
299 /*! |
|
300 Destructor. |
|
301 */ |
|
302 QAbstractXmlNodeModel::~QAbstractXmlNodeModel() |
|
303 { |
|
304 } |
|
305 |
|
306 /*! |
|
307 \typedef QAbstractXmlNodeModel::List |
|
308 |
|
309 A \l{QList}{list} of \l{QExplicitlySharedDataPointer} {smart |
|
310 pointers} to instances of QAbstractXmlNodeModel. |
|
311 |
|
312 \sa QExplicitlySharedDataPointer |
|
313 */ |
|
314 |
|
315 /*! |
|
316 \typedef QAbstractXmlNodeModel::Ptr |
|
317 |
|
318 A \l {QExplicitlySharedDataPointer} {smart pointer} to an |
|
319 instance of QAbstractXmlNodeModel. |
|
320 |
|
321 \sa QExplicitlySharedDataPointer |
|
322 */ |
|
323 |
|
324 /*! |
|
325 \fn QUrl QAbstractXmlNodeModel::baseUri(const QXmlNodeModelIndex &n) const |
|
326 |
|
327 Returns the base URI for the node whose index is \a n. The caller |
|
328 guarantees that \a n is not \c null and that it belongs to a node |
|
329 in this node model. |
|
330 |
|
331 The base URI of a node can be extracted using the \c fn:base-uri() |
|
332 function. The base URI is typically used for resolving relative URIs |
|
333 that appear in the node or its children. It is conformant to just |
|
334 return the document URI, although that might not properly reflect |
|
335 the underlying data. |
|
336 |
|
337 This function maps to the \c dm:base-uri accessor, which returns |
|
338 a base URI according to the following: |
|
339 |
|
340 \list |
|
341 |
|
342 \o For document nodes, the base URI and the document URI are the same. |
|
343 |
|
344 \o For elements, the base URI is the URI appearing in the element's |
|
345 \c xml:base attribute, if present, or it is resolved to the |
|
346 parent element's base URI. |
|
347 |
|
348 \o Namespace nodes have no base URI. |
|
349 |
|
350 \o The base URI for a processing instruction, comment, attribute, |
|
351 or text node is the base URI of the node's parent element. |
|
352 |
|
353 \endlist |
|
354 |
|
355 The implementation guarantees to return a valid QUrl, or a default |
|
356 constructed QUrl. If a node has no base URI, as in the case where a |
|
357 comment has no parent, a default constructed QUrl is returned. |
|
358 |
|
359 \sa {http://www.w3.org/TR/xpath-datamodel/#dm-base-uri}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.2 base-uri Accessor} |
|
360 */ |
|
361 |
|
362 /*! |
|
363 \fn QUrl QAbstractXmlNodeModel::documentUri(const QXmlNodeModelIndex &n) const |
|
364 |
|
365 Returns the document URI of \a n. The document URI identifies the |
|
366 resource which is the document. For example, the document could be a |
|
367 regular file, e.g., \c{file:/}, or it could be the \c{http://} URL of |
|
368 the location of a file. The document URI is used for resolving URIs |
|
369 and to simply know where the document is. |
|
370 |
|
371 If the node model maps to a URI in a natural way, return that URI. |
|
372 Otherwise, return the company or product URI. The document URI can |
|
373 be any URI as long as its valid and absolute. |
|
374 |
|
375 The caller guarantees that \a n is not \c null and that it belongs |
|
376 to this QAbstractXmlNodeModel. |
|
377 |
|
378 This function maps to the \c dm:document-uri accessor, which |
|
379 returns a document URI according to the following: |
|
380 |
|
381 \list |
|
382 |
|
383 \o If \a n is a document node, return an absolute QUrl containing |
|
384 the document URI, or a default constructed QUrl. The latter |
|
385 signals that no document URI is available for the document node. |
|
386 |
|
387 \o For all other nodes, return a default constructed QUrl. |
|
388 |
|
389 \endlist |
|
390 |
|
391 \sa {http://www.w3.org/TR/xpath-datamodel/#dm-document-uri}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.4 document-uri Accessor} |
|
392 \sa QUrl::isValid(), QUrl::isRelative() |
|
393 */ |
|
394 |
|
395 /* |
|
396 ### Qt 5: |
|
397 |
|
398 Add the function: |
|
399 |
|
400 virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &nodeIndex) const = 0; |
|
401 |
|
402 Such that the data model can communicate back source locations. |
|
403 */ |
|
404 |
|
405 /*! |
|
406 \fn QXmlNodeModelIndex::NodeKind QAbstractXmlNodeModel::kind(const QXmlNodeModelIndex &ni) const |
|
407 |
|
408 Returns a value indicating the kind of node identified by \a ni. |
|
409 The caller guarantees that \a ni is not null and that it identifies |
|
410 a node in this node model. This function maps to the \c |
|
411 dm:node-kind() accessor. |
|
412 |
|
413 \sa {http://www.w3.org/TR/xpath-datamodel/#dm-node-kind}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.10 node-kind Accessor} |
|
414 */ |
|
415 |
|
416 /*! |
|
417 \fn QXmlNodeModelIndex::DocumentOrder QAbstractXmlNodeModel::compareOrder(const QXmlNodeModelIndex &ni1, const QXmlNodeModelIndex &ni2) const |
|
418 |
|
419 This function returns the relative document order for the |
|
420 nodes indexed by \a ni1 and \a ni2. It is used for the \c Is |
|
421 operator and for sorting nodes in document order. |
|
422 |
|
423 The caller guarantees that \a ni1 and \a ni2 are not \c null and |
|
424 that both identify nodes in this node model. |
|
425 |
|
426 If \a ni1 is identical to \a ni2, QXmlNodeModelIndex::Is is returned. |
|
427 If \a ni1 precedes \a ni2 in document order, QXmlNodeModelIndex::Precedes |
|
428 is returned. If \a ni1 follows \a ni2 in document order, |
|
429 QXmlNodeModelIndex::Follows is returned. |
|
430 |
|
431 \sa {http://www.w3.org/TR/xpath-datamodel/#document-order}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 2.4 Document Order} |
|
432 */ |
|
433 |
|
434 /*! |
|
435 \fn QXmlNodeModelIndex QAbstractXmlNodeModel::root(const QXmlNodeModelIndex &n) const |
|
436 |
|
437 Returns the root node of the tree that contains the node whose index |
|
438 is \a n. The caller guarantees that \a n is not \c null and that it |
|
439 identifies a node in this node model. |
|
440 |
|
441 If \a n identifies a node that is a direct child of the root, |
|
442 parent() would return the same QXmlNodeModelIndex returned by |
|
443 this function. |
|
444 */ |
|
445 |
|
446 namespace QPatternist |
|
447 { |
|
448 class MergeIterator |
|
449 { |
|
450 public: |
|
451 inline MergeIterator() |
|
452 { |
|
453 } |
|
454 |
|
455 inline |
|
456 QXmlNodeModelIndexIteratorPointer |
|
457 mapToSequence(const QXmlNodeModelIndexIteratorPointer &it, |
|
458 const DynamicContext::Ptr &) const |
|
459 { |
|
460 return it; |
|
461 } |
|
462 |
|
463 private: |
|
464 Q_DISABLE_COPY(MergeIterator) |
|
465 }; |
|
466 |
|
467 static const MergeIterator mergeIterator; |
|
468 |
|
469 /** |
|
470 * One might wonder, why not use makeVectorIterator() directly on a QVector |
|
471 * with iterators? |
|
472 * |
|
473 * A problem emerges QAbstractXmlForwardIterator::copy(). All "meta |
|
474 * iterators" that contain other iterators and so forth, propagate the |
|
475 * copy() call such that all involved iterators are copied. However, if we |
|
476 * have a ListIterator of iterators it isn't aware of that it contains |
|
477 * iterators. Hence, we have this class which is specialized(not in the |
|
478 * template sense) on iterators, and hence copies them appropriately. |
|
479 */ |
|
480 class IteratorVector : public ListIterator<QXmlNodeModelIndexIteratorPointer, QVector<QXmlNodeModelIndexIteratorPointer> > |
|
481 { |
|
482 typedef QVector<QXmlNodeModelIndexIteratorPointer> ItVector; |
|
483 public: |
|
484 typedef QAbstractXmlForwardIterator<QXmlNodeModelIndexIteratorPointer>::Ptr Ptr; |
|
485 |
|
486 IteratorVector(const ItVector &in) : ListIterator<QXmlNodeModelIndexIteratorPointer, QVector<QXmlNodeModelIndexIteratorPointer> >(in) |
|
487 { |
|
488 } |
|
489 |
|
490 virtual QAbstractXmlForwardIterator<QXmlNodeModelIndexIteratorPointer>::Ptr copy() const |
|
491 { |
|
492 ItVector result; |
|
493 |
|
494 for(int i = 0; i < m_list.count(); ++i) |
|
495 result.append(m_list.at(i)->copy()); |
|
496 |
|
497 return Ptr(new IteratorVector(result)); |
|
498 } |
|
499 }; |
|
500 } |
|
501 |
|
502 /*! |
|
503 \internal |
|
504 This function is not a private member of QAbstractXmlNodeModel |
|
505 because it would be messy to forward declare the required types. |
|
506 */ |
|
507 static inline QXmlNodeModelIndexIteratorPointer mergeIterators(const QXmlNodeModelIndex &node, |
|
508 const QXmlNodeModelIndexIteratorPointer &it2) |
|
509 { |
|
510 QVector<QXmlNodeModelIndexIteratorPointer> iterators; |
|
511 iterators.append(makeSingletonIterator(node)); |
|
512 iterators.append(it2); |
|
513 |
|
514 return makeSequenceMappingIterator<QXmlNodeModelIndex>(&mergeIterator, |
|
515 IteratorVector::Ptr(new IteratorVector(iterators)), |
|
516 DynamicContext::Ptr()); |
|
517 } |
|
518 |
|
519 inline QAbstractXmlForwardIterator<QXmlNodeModelIndex>::Ptr |
|
520 QAbstractXmlNodeModel::mapToSequence(const QXmlNodeModelIndex &ni, |
|
521 const DynamicContext::Ptr &) const |
|
522 { |
|
523 Q_ASSERT(!ni.isNull()); |
|
524 /* Since we pass in this here, mapToSequence is used recursively. */ |
|
525 return mergeIterators(ni, makeSequenceMappingIterator<QXmlNodeModelIndex>(this, |
|
526 ni.iterate(QXmlNodeModelIndex::AxisChild), |
|
527 DynamicContext::Ptr())); |
|
528 } |
|
529 |
|
530 /*! |
|
531 \fn QVector<QXmlNodeModelIndex> QAbstractXmlNodeModel::attributes(const QXmlNodeModelIndex &element) const |
|
532 |
|
533 Returns the attributes of \a element. The caller guarantees |
|
534 that \a element is an element in this node model. |
|
535 */ |
|
536 |
|
537 /*! |
|
538 \internal |
|
539 |
|
540 Performs navigation, starting from \a ni, by returning an |
|
541 QAbstractXmlForwardIterator that returns nodes the \a axis emanating |
|
542 from \a ni. |
|
543 |
|
544 The implementation returns the nodes on the \a axis, without |
|
545 duplicates and in \a axis order. This means that if \a axis is a |
|
546 reverse axis, which is the case for the \c parent, \c ancestor, \c |
|
547 ancestor-or-self, \c preceding, and \c preceding-sibling, the nodes |
|
548 are delivered in reverse document order. Otherwise the nodes are |
|
549 delivered in document order. |
|
550 |
|
551 The implementor guarantees that the nodes delivered for the axes are |
|
552 consistent with the XPath Data Model. This just implies common |
|
553 sense, e.g., The child axis for a comment node can't contain any |
|
554 children; a document node can't be a child of an element, etc. |
|
555 Attributes aren't considered children of an element, but are only |
|
556 available on AxisAttribute. |
|
557 |
|
558 The value past in \a axis is not guaranteed based on what is used in |
|
559 a query. QtXmlPatterns may call this function arbitrarily with any |
|
560 value for \a axis. This is because QtXmlPatterns may rewrite queries |
|
561 to be more efficient, using axes in different ways from the original |
|
562 query. |
|
563 |
|
564 QAbstractXmlNodeModel::Axis has a good overview of the axes and what |
|
565 they select. |
|
566 |
|
567 The caller guarantees that \a ni is not \c null and that it belongs |
|
568 to this QAbstractXmlNodeModel instance. |
|
569 |
|
570 Implementing iterate() can involve significant work, since it |
|
571 requires different iterators for all the axes used. In the worst |
|
572 case, it could require writing as many QAbstractXmlForwardIterator |
|
573 subclasses as there are axes, but the number can often be reduced |
|
574 with clever use of lists and template classes. It is better to use |
|
575 or subclass QSimpleXmlNodeModel, which makes it easier to write the |
|
576 node navigation code without loss of efficiency or flexibility. |
|
577 |
|
578 \sa QSimpleXmlNodeModel |
|
579 \sa QXmlNodeModelIndex::Axis |
|
580 \sa {http://www.w3.org/TR/xquery/#axes}{XQuery 1.0: An XML Query Language, 3.2.1.1 Axes} |
|
581 \sa {http://www.w3.org/TR/xpath-datamodel/}{W3CXQuery 1.0 and XPath 2.0 Data Model (XDM)} |
|
582 */ |
|
583 QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > |
|
584 QAbstractXmlNodeModel::iterate(const QXmlNodeModelIndex &ni, |
|
585 QXmlNodeModelIndex::Axis axis) const |
|
586 { |
|
587 /* Returns iterators that track state and calls nextFromSimpleAxis() |
|
588 * iteratively. Typically, when sub-classing QSimpleXmlNodeModel, |
|
589 * you don't reimplement this function, but instead implement |
|
590 * nextFromSimpleAxis(). */ |
|
591 |
|
592 switch(axis) |
|
593 { |
|
594 case QXmlNodeModelIndex::AxisSelf: |
|
595 return makeSingletonIterator(ni); |
|
596 case QXmlNodeModelIndex::AxisParent: |
|
597 { |
|
598 if(kind(ni) == QXmlNodeModelIndex::Document) |
|
599 return makeEmptyIterator<QXmlNodeModelIndex>(); |
|
600 else |
|
601 return makeSingletonIterator(nextFromSimpleAxis(Parent, ni)); |
|
602 } |
|
603 case QXmlNodeModelIndex::AxisNamespace: |
|
604 return makeEmptyIterator<QXmlNodeModelIndex>(); |
|
605 case QXmlNodeModelIndex::AxisAncestor: |
|
606 { |
|
607 QList<QXmlNodeModelIndex> ancestors; |
|
608 QXmlNodeModelIndex ancestor = nextFromSimpleAxis(Parent, ni); |
|
609 |
|
610 while(!ancestor.isNull()) |
|
611 { |
|
612 ancestors.append(ancestor); |
|
613 ancestor = nextFromSimpleAxis(Parent, ancestor); |
|
614 } |
|
615 |
|
616 return makeListIterator(ancestors); |
|
617 } |
|
618 case QXmlNodeModelIndex::AxisAncestorOrSelf: |
|
619 { |
|
620 QList<QXmlNodeModelIndex> ancestors; |
|
621 ancestors.append(ni); |
|
622 QXmlNodeModelIndex ancestor = nextFromSimpleAxis(Parent, ni); |
|
623 |
|
624 while(!ancestor.isNull()) |
|
625 { |
|
626 ancestors.append(ancestor); |
|
627 ancestor = nextFromSimpleAxis(Parent, ancestor); |
|
628 } |
|
629 |
|
630 return makeListIterator(ancestors); |
|
631 } |
|
632 case QXmlNodeModelIndex::AxisPrecedingSibling: |
|
633 { |
|
634 QList<QXmlNodeModelIndex> preceding; |
|
635 QXmlNodeModelIndex sibling = nextFromSimpleAxis(PreviousSibling, ni); |
|
636 |
|
637 while(!sibling.isNull()) |
|
638 { |
|
639 preceding.append(sibling); |
|
640 sibling = nextFromSimpleAxis(PreviousSibling, sibling); |
|
641 } |
|
642 |
|
643 return makeListIterator(preceding); |
|
644 } |
|
645 case QXmlNodeModelIndex::AxisFollowingSibling: |
|
646 { |
|
647 QList<QXmlNodeModelIndex> preceding; |
|
648 QXmlNodeModelIndex sibling = nextFromSimpleAxis(NextSibling, ni); |
|
649 |
|
650 while(!sibling.isNull()) |
|
651 { |
|
652 preceding.append(sibling); |
|
653 sibling = nextFromSimpleAxis(NextSibling, sibling); |
|
654 } |
|
655 |
|
656 return makeListIterator(preceding); |
|
657 } |
|
658 case QXmlNodeModelIndex::AxisChildOrTop: |
|
659 { |
|
660 if(nextFromSimpleAxis(Parent, ni).isNull()) |
|
661 { |
|
662 switch(kind(ni)) |
|
663 { |
|
664 case QXmlNodeModelIndex::Comment: |
|
665 /* Fallthrough. */ |
|
666 case QXmlNodeModelIndex::ProcessingInstruction: |
|
667 /* Fallthrough. */ |
|
668 case QXmlNodeModelIndex::Element: |
|
669 /* Fallthrough. */ |
|
670 case QXmlNodeModelIndex::Text: |
|
671 return makeSingletonIterator(ni); |
|
672 case QXmlNodeModelIndex::Attribute: |
|
673 /* Fallthrough. */ |
|
674 case QXmlNodeModelIndex::Document: |
|
675 /* Fallthrough. */ |
|
676 case QXmlNodeModelIndex::Namespace: |
|
677 /* Do nothing. */; |
|
678 } |
|
679 } |
|
680 |
|
681 /* Else, fallthrough to AxisChild. */ |
|
682 } |
|
683 case QXmlNodeModelIndex::AxisChild: |
|
684 { |
|
685 QList<QXmlNodeModelIndex> children; |
|
686 QXmlNodeModelIndex child = nextFromSimpleAxis(FirstChild, ni); |
|
687 |
|
688 while(!child.isNull()) |
|
689 { |
|
690 children.append(child); |
|
691 child = nextFromSimpleAxis(NextSibling, child); |
|
692 } |
|
693 |
|
694 return makeListIterator(children); |
|
695 } |
|
696 case QXmlNodeModelIndex::AxisDescendant: |
|
697 { |
|
698 return makeSequenceMappingIterator<QXmlNodeModelIndex>(this, |
|
699 ni.iterate(QXmlNodeModelIndex::AxisChild), |
|
700 DynamicContext::Ptr()); |
|
701 } |
|
702 case QXmlNodeModelIndex::AxisAttributeOrTop: |
|
703 { |
|
704 if(kind(ni) == QXmlNodeModelIndex::Attribute && nextFromSimpleAxis(Parent, ni).isNull()) |
|
705 return makeSingletonIterator(ni); |
|
706 |
|
707 /* Else, fallthrough to AxisAttribute. */ |
|
708 } |
|
709 case QXmlNodeModelIndex::AxisAttribute: |
|
710 return makeVectorIterator(attributes(ni)); |
|
711 case QXmlNodeModelIndex::AxisDescendantOrSelf: |
|
712 return mergeIterators(ni, iterate(ni, QXmlNodeModelIndex::AxisDescendant)); |
|
713 case QXmlNodeModelIndex::AxisFollowing: |
|
714 /* Fallthrough. */ |
|
715 case QXmlNodeModelIndex::AxisPreceding: |
|
716 { |
|
717 /* We walk up along the ancestors, and for each parent, we grab its preceding/following |
|
718 * siblings, and evaluate the descendant axis. The descendant axes gets added |
|
719 * to a list and we then merge those iterators. */ |
|
720 QVector<QXmlNodeModelIndexIteratorPointer> descendantIterators; |
|
721 |
|
722 QXmlNodeModelIndex current(ni); |
|
723 while(!current.isNull()) |
|
724 { |
|
725 QXmlNodeModelIndex candidate(nextFromSimpleAxis(axis == QXmlNodeModelIndex::AxisPreceding ? PreviousSibling : NextSibling, current)); |
|
726 if(candidate.isNull()) |
|
727 { |
|
728 /* current is an ancestor. We don't want it, so next iteration we |
|
729 * will grab its preceding sibling. */ |
|
730 current = nextFromSimpleAxis(Parent, current); |
|
731 } |
|
732 else |
|
733 { |
|
734 current = candidate; |
|
735 descendantIterators.append(iterate(current, QXmlNodeModelIndex::AxisDescendantOrSelf)->toReversed()); |
|
736 } |
|
737 } |
|
738 |
|
739 return makeSequenceMappingIterator<QXmlNodeModelIndex>(&mergeIterator, |
|
740 IteratorVector::Ptr(new IteratorVector(descendantIterators)), |
|
741 DynamicContext::Ptr()); |
|
742 } |
|
743 } |
|
744 |
|
745 Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown axis, internal error."); |
|
746 return makeEmptyIterator<QXmlNodeModelIndex>(); |
|
747 } |
|
748 |
|
749 /*! |
|
750 \fn QXmlNodeModelIndex QAbstractXmlNodeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const |
|
751 |
|
752 When QtXmlPatterns evaluate path expressions, it emulate them through a |
|
753 combination of calls with QSimpleXmlNodeModel::SimpleAxis values. Therefore, |
|
754 the implementation of this function must return the node, if any, that |
|
755 appears on the \a axis emanating from the \a origin. |
|
756 |
|
757 If no such node is available, a default constructed |
|
758 QXmlNodeModelIndex is returned. |
|
759 |
|
760 QSimpleXmlNodeModel eliminates the need to handle redundant corner |
|
761 cases by guaranteeing that it will never ask for: |
|
762 |
|
763 \list |
|
764 \o Children or siblings for attributes. |
|
765 \o Children for comments, processing instructions, and text nodes. |
|
766 \o Siblings or parents for document nodes. |
|
767 \endlist |
|
768 |
|
769 A typical implementation performs a \c switch on the value of \a |
|
770 axis: |
|
771 |
|
772 \code |
|
773 QXmlNodeModelIndex MyTreeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const |
|
774 { |
|
775 // Convert the QXmlNodeModelIndex to a value that is specific to what we represent. |
|
776 const MyValue value = toMyValue(ni); |
|
777 |
|
778 switch(axis) |
|
779 { |
|
780 case Parent: |
|
781 return toNodeIndex(value.parent()); |
|
782 case FirstChild: |
|
783 case PreviousSibling: |
|
784 case NextSibling: |
|
785 // and so on |
|
786 } |
|
787 } |
|
788 \endcode |
|
789 |
|
790 */ |
|
791 |
|
792 /*! |
|
793 \fn QXmlNodeModelIndex QAbstractXmlNodeModel::createIndex(qint64 data) const |
|
794 |
|
795 Creates a node index with \a data as its internal data. \a data is |
|
796 not constrained. |
|
797 */ |
|
798 |
|
799 /*! |
|
800 \fn QXmlNodeModelIndex QAbstractXmlNodeModel::createIndex(void *pointer, qint64 additionalData) const |
|
801 |
|
802 Creates a node index with \a pointer and \a additionalData as |
|
803 its internal data. |
|
804 |
|
805 What \a pointer and \a additionalData is, is not constrained. |
|
806 */ |
|
807 |
|
808 /*! |
|
809 \fn QXmlNodeModelIndex QAbstractXmlNodeModel::createIndex(qint64 data, qint64 additionalData) const; |
|
810 \overload |
|
811 |
|
812 Creates a QXmlNodeModelIndex containing \a data and \a |
|
813 additionalData. |
|
814 */ |
|
815 |
|
816 /*! |
|
817 \fn QXmlName QAbstractXmlNodeModel::name(const QXmlNodeModelIndex &ni) const |
|
818 |
|
819 Returns the name of \a ni. The caller guarantees that \a ni is not |
|
820 \c null and that it belongs to this QAbstractXmlNodeModel. |
|
821 |
|
822 If a node does not have a name, e.g., comment nodes, a null QXmlName |
|
823 is returned. QXmlNames must be created with the instance of |
|
824 QXmlQuery that is being used for evaluating queries using this |
|
825 QAbstractXmlNodeModel. |
|
826 |
|
827 This function maps to the \c dm:node-name() accessor. |
|
828 |
|
829 If \a ni is a processing instruction, a QXmlName is returned with |
|
830 the local name as the target name and the namespace URI and prefix |
|
831 both empty. |
|
832 |
|
833 \sa {http://www.w3.org/TR/xpath-datamodel/#dm-node-name}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.11 node-name Accessor} |
|
834 \sa QXmlName |
|
835 */ |
|
836 |
|
837 /*! |
|
838 \fn QVector<QXmlName> QAbstractXmlNodeModel::namespaceBindings(const QXmlNodeModelIndex &n) const |
|
839 |
|
840 Returns the in-scope namespaces of \a n. The caller guarantees that |
|
841 \a n is not \c null and that it belongs to this QAbstractXmlNodeModel. |
|
842 |
|
843 This function corresponds to the \c dm:namespace-nodes accessor. |
|
844 |
|
845 The returned vector of namespace declarations includes namespaces |
|
846 of the ancestors of \a n. |
|
847 |
|
848 The caller guarantees that \a n is an Element that belongs to this |
|
849 QAbstractXmlNodeModel. |
|
850 */ |
|
851 |
|
852 /*! |
|
853 \internal |
|
854 Sends the namespaces declared on \a n to \a receiver. |
|
855 |
|
856 As a consequence, no namespaces are sent unless this node is an |
|
857 element and has namespaces declared. |
|
858 |
|
859 The caller guarantees that \a n is not \c null and that it belongs |
|
860 to this QAbstractXmlNodeModel instance. |
|
861 |
|
862 Note that it is not the namespaces that are in scope on \a n, but |
|
863 only the namespaces that are specifically declared on \a n. |
|
864 |
|
865 \a receiver is the receiver that this node is supposed to send its |
|
866 namespaces to. This is guaranteed by the caller to be a valid |
|
867 pointer. \a n is the index of the node whose namespaces are to |
|
868 be sent. |
|
869 */ |
|
870 void QAbstractXmlNodeModel::sendNamespaces(const QXmlNodeModelIndex &n, |
|
871 QAbstractXmlReceiver *const receiver) const |
|
872 { |
|
873 Q_ASSERT(receiver); |
|
874 const QVector<QXmlName> nss(namespaceBindings(n)); |
|
875 |
|
876 /* This is by far the most common case. */ |
|
877 if(nss.isEmpty()) |
|
878 return; |
|
879 |
|
880 const int len = nss.size(); |
|
881 for(int i = 0; i < len; ++i) |
|
882 receiver->namespaceBinding(nss.at(i)); |
|
883 } |
|
884 |
|
885 /*! |
|
886 \fn QString QAbstractXmlNodeModel::stringValue(const QXmlNodeModelIndex &n) const |
|
887 |
|
888 Returns the string value for node \a n. |
|
889 |
|
890 The caller guarantees that \a n is not \c null and that it belong to |
|
891 this QAbstractXmlNodeModel instance. |
|
892 |
|
893 This function maps to the \c dm:string-value() accessor, which the |
|
894 specification completely specifies. Here's a summary: |
|
895 |
|
896 \list |
|
897 |
|
898 \o For processing instructions, the string value is the data |
|
899 section(excluding any whitespace appearing between the name and the |
|
900 data). |
|
901 |
|
902 \o For text nodes, the string value equals the text node. |
|
903 |
|
904 \o For comments, the content of the comment |
|
905 |
|
906 \o For elements, the concatenation of all text nodes that are |
|
907 descendants. Note, this is not only the children, but the |
|
908 childrens' childrens' text nodes, and so forth. |
|
909 |
|
910 \o For document nodes, the concatenation of all text nodes in the |
|
911 document. |
|
912 |
|
913 \endlist |
|
914 |
|
915 \sa {http://www.w3.org/TR/xpath-datamodel/#dm-string-value}{XQuery 1.0 and XPath 2.0 Data Model (XDM), 5.13 string-value Accessor} |
|
916 */ |
|
917 |
|
918 /*! |
|
919 \fn QVariant QAbstractXmlNodeModel::typedValue(const QXmlNodeModelIndex &node) const |
|
920 |
|
921 Returns the typed value for node \a node. |
|
922 |
|
923 The typed value is an atomic value, which an element or attribute |
|
924 contains. |
|
925 |
|
926 The caller guarantees that \a node is either an element or an |
|
927 attribute. The implementor guarantees that the returned QVariant has |
|
928 a value which is supported in XQuery. It cannot be an arbitrary |
|
929 QVariant value. The implementor also guarantees that stringValue() |
|
930 returns a lexical representation of typedValue()(this is guaranteed |
|
931 by QSimpleXmlNodeModel::stringValue()). |
|
932 |
|
933 If the return QVariant is a default constructed variant, it signals |
|
934 that \a node has no typed value. |
|
935 */ |
|
936 |
|
937 /*! |
|
938 \internal |
|
939 */ |
|
940 QPatternist::ItemIteratorPtr QAbstractXmlNodeModel::sequencedTypedValue(const QXmlNodeModelIndex &ni) const |
|
941 { |
|
942 const QVariant &candidate = typedValue(ni); |
|
943 if(candidate.isNull()) |
|
944 return QPatternist::CommonValues::emptyIterator; |
|
945 else |
|
946 return makeSingletonIterator(AtomicValue::toXDM(candidate)); |
|
947 } |
|
948 |
|
949 /*! |
|
950 \internal |
|
951 */ |
|
952 QPatternist::ItemTypePtr QAbstractXmlNodeModel::type(const QXmlNodeModelIndex &) const |
|
953 { |
|
954 Q_ASSERT_X(false, Q_FUNC_INFO, |
|
955 "This function is internal and must not be called."); |
|
956 return QPatternist::ItemTypePtr(); |
|
957 } |
|
958 |
|
959 /*! |
|
960 \internal |
|
961 |
|
962 Returns the namespace URI on \a ni that corresponds to \a prefix. |
|
963 |
|
964 If \a prefix is StandardPrefixes::empty, the namespace URI for the |
|
965 default namespace is returned. |
|
966 |
|
967 The default implementation use namespaceBindings(), in a straight |
|
968 forward manner. |
|
969 |
|
970 If no namespace exists for \a prefix, NamespaceResolver::NoBinding |
|
971 is returned. |
|
972 |
|
973 The caller guarantees to only call this function for element nodes. |
|
974 */ |
|
975 QXmlName::NamespaceCode QAbstractXmlNodeModel::namespaceForPrefix(const QXmlNodeModelIndex &ni, |
|
976 const QXmlName::PrefixCode prefix) const |
|
977 { |
|
978 Q_ASSERT(kind(ni) == QXmlNodeModelIndex::Element); |
|
979 |
|
980 const QVector<QXmlName> nbs(namespaceBindings(ni)); |
|
981 const int len = nbs.size(); |
|
982 |
|
983 for(int i = 0; i < len; ++i) |
|
984 { |
|
985 if(nbs.at(i).prefix() == prefix) |
|
986 return nbs.at(i).namespaceURI(); |
|
987 } |
|
988 |
|
989 return NamespaceResolver::NoBinding; |
|
990 } |
|
991 |
|
992 |
|
993 /*! |
|
994 \internal |
|
995 |
|
996 Determines whether \a ni1 is deep equal to \a ni2. |
|
997 |
|
998 isDeepEqual() is defined as evaluating the expression \c |
|
999 fn:deep-equal($n1, $n2) where \c $n1 is \a ni1 and \c $n1 is \a |
|
1000 ni2. This function is associative, meaning the same value is |
|
1001 returned regardless of if isDeepEqual() is invoked with \a ni1 as |
|
1002 first argument or second. It is guaranteed that \a ni1 and \a ni2 |
|
1003 are nodes, as opposed to the definition of \c fn:deep-equal(). |
|
1004 |
|
1005 Returns true if \a ni1 is deep-equal to \a ni2, otherwise false |
|
1006 |
|
1007 \sa {"http://www.w3.org/TR/xpath-functions/#func-deep-equal"}{XQuery 1.0 and XPath 2.0 Functions and Operators, 15.3.1 fn:deep-equal} |
|
1008 */ |
|
1009 bool QAbstractXmlNodeModel::isDeepEqual(const QXmlNodeModelIndex &n1, |
|
1010 const QXmlNodeModelIndex &n2) const |
|
1011 { |
|
1012 Q_ASSERT(!n1.isNull()); |
|
1013 Q_ASSERT(!n2.isNull()); |
|
1014 |
|
1015 const QXmlNodeModelIndex::NodeKind nk = n1.kind(); |
|
1016 |
|
1017 if(nk != n2.kind()) |
|
1018 return false; |
|
1019 |
|
1020 if(n1.name() != n2.name()) |
|
1021 return false; |
|
1022 |
|
1023 switch(nk) |
|
1024 { |
|
1025 case QXmlNodeModelIndex::Element: |
|
1026 { |
|
1027 QXmlNodeModelIndexIteratorPointer atts1(n1.iterate(QXmlNodeModelIndex::AxisAttribute)); |
|
1028 QXmlNodeModelIndex node(atts1->next()); |
|
1029 |
|
1030 const QXmlNodeModelIndex::List atts2(n2.iterate(QXmlNodeModelIndex::AxisAttribute)->toList()); |
|
1031 const QXmlNodeModelIndex::List::const_iterator end(atts2.constEnd()); |
|
1032 |
|
1033 while(!node.isNull()) |
|
1034 { |
|
1035 bool equal = false; |
|
1036 for(QXmlNodeModelIndex::List::const_iterator it = atts2.constBegin(); it != end; ++it) |
|
1037 { |
|
1038 if(isDeepEqual(node, (*it))) |
|
1039 equal = true; |
|
1040 } |
|
1041 |
|
1042 if(!equal) |
|
1043 return false; |
|
1044 |
|
1045 node = atts1->next(); |
|
1046 } |
|
1047 |
|
1048 /* Fallthrough, so we check the children. */ |
|
1049 } |
|
1050 case QXmlNodeModelIndex::Document: |
|
1051 { |
|
1052 QXmlNodeModelIndexIteratorPointer itn1(n1.iterate(QXmlNodeModelIndex::AxisChild)); |
|
1053 QXmlNodeModelIndexIteratorPointer itn2(n2.iterate(QXmlNodeModelIndex::AxisChild)); |
|
1054 |
|
1055 while(true) |
|
1056 { |
|
1057 QXmlNodeModelIndex no1(itn1->next()); |
|
1058 QXmlNodeModelIndex no2(itn2->next()); |
|
1059 |
|
1060 while(!no1.isNull() && isIgnorableInDeepEqual(no1)) |
|
1061 no1 = itn1->next(); |
|
1062 |
|
1063 while(!no2.isNull() && isIgnorableInDeepEqual(no2)) |
|
1064 no2 = itn2->next(); |
|
1065 |
|
1066 if(!no1.isNull() && !no2.isNull()) |
|
1067 { |
|
1068 if(!isDeepEqual(no1, no2)) |
|
1069 return false; |
|
1070 } |
|
1071 else |
|
1072 return no1.isNull() && no2.isNull(); |
|
1073 } |
|
1074 |
|
1075 return true; |
|
1076 } |
|
1077 case QXmlNodeModelIndex::Attribute: |
|
1078 /* Fallthrough */ |
|
1079 case QXmlNodeModelIndex::ProcessingInstruction: |
|
1080 /* Fallthrough. */ |
|
1081 case QXmlNodeModelIndex::Text: |
|
1082 /* Fallthrough. */ |
|
1083 case QXmlNodeModelIndex::Comment: |
|
1084 return n1.stringValue() == n2.stringValue(); |
|
1085 case QXmlNodeModelIndex::Namespace: |
|
1086 { |
|
1087 Q_ASSERT_X(false, Q_FUNC_INFO, "Not implemented"); |
|
1088 return false; |
|
1089 } |
|
1090 } |
|
1091 |
|
1092 return false; |
|
1093 } |
|
1094 |
|
1095 /*! |
|
1096 \class QXmlItem |
|
1097 \reentrant |
|
1098 \since 4.4 |
|
1099 \brief The QXmlItem class contains either an XML node or an atomic value. |
|
1100 \ingroup xml-tools |
|
1101 |
|
1102 In XQuery, all expressions evaluate to a sequence of items, where |
|
1103 each item is either an XML node or an atomic value. The query in the |
|
1104 following snippet evaluates to sequence of five items. |
|
1105 |
|
1106 \quotefile doc/src/snippets/patternist/items.xq |
|
1107 |
|
1108 The five items are: An element, an atomic value (binary data encoded |
|
1109 in base64), a date, a float, and an attribute. |
|
1110 |
|
1111 QXmlItem is the class that represents these XQuery items in the |
|
1112 QtXmlPatterns API. A non-null instance of QXmlItem is either a node |
|
1113 or an atomic value. Calling isNode() or isAtomicValue() tells you |
|
1114 which it is. Atomic values are represented elsewhere in the Qt API |
|
1115 as instances of QVariant, and an instance of QXmlItem that |
|
1116 represents an atomic value can be converted to a QVariant by calling |
|
1117 toAtomicValue(). A QXmlItem that wraps a node is represented |
|
1118 elsewhere as an instance of QXmlNodeModelIndex. A node QXmlItem can |
|
1119 be converted to a QXmlNodeModelIndex by calling toNodeModelIndex(). |
|
1120 |
|
1121 A default constructed QXmlItem instance is neither a node nor an |
|
1122 atomic value. It is considered null, in which case isNull() returns |
|
1123 true. |
|
1124 |
|
1125 An instance of QXmlItem will be left dangling if the |
|
1126 \l{QAbstractXmlNodeModel} {XML node model} it |
|
1127 refers to is deleted, if it is a QXmlNodeModelIndex. |
|
1128 */ |
|
1129 |
|
1130 /*! |
|
1131 \typedef QXmlItem::Iterator |
|
1132 A QAbstractXmlForwardIterator over QXmlItem. |
|
1133 */ |
|
1134 |
|
1135 /*! |
|
1136 Constructs a null QXmlItem that is neither a node nor an atomic |
|
1137 value. isNull() returns true for a default constructed instance. |
|
1138 */ |
|
1139 QXmlItem::QXmlItem() |
|
1140 { |
|
1141 m_node.model = 0; |
|
1142 m_node.data = 0; |
|
1143 m_node.additionalData = 0; |
|
1144 } |
|
1145 |
|
1146 bool QXmlItem::internalIsAtomicValue() const |
|
1147 { |
|
1148 return m_node.model == reinterpret_cast<QAbstractXmlNodeModel *>(~0); |
|
1149 } |
|
1150 |
|
1151 /*! |
|
1152 The copy constructor constructs a copy of \a other. |
|
1153 */ |
|
1154 QXmlItem::QXmlItem(const QXmlItem &other) : m_node(other.m_node) |
|
1155 { |
|
1156 if(internalIsAtomicValue()) |
|
1157 m_atomicValue->ref.ref(); |
|
1158 } |
|
1159 |
|
1160 /*! |
|
1161 Constructs an atomic value QXmlItem with \a atomicValue. |
|
1162 |
|
1163 \sa isAtomicValue() |
|
1164 */ |
|
1165 QXmlItem::QXmlItem(const QVariant &atomicValue) |
|
1166 { |
|
1167 if(atomicValue.isNull()) |
|
1168 { |
|
1169 /* Then we behave just like the default constructor. */ |
|
1170 m_node.model = 0; |
|
1171 m_node.data = 0; |
|
1172 m_node.additionalData = 0; |
|
1173 return; |
|
1174 } |
|
1175 |
|
1176 /* |
|
1177 We can't assign directly to m_atomicValue, because the |
|
1178 temporary will self-destruct before we've ref'd it. |
|
1179 */ |
|
1180 const QPatternist::Item temp(QPatternist::AtomicValue::toXDM(atomicValue)); |
|
1181 |
|
1182 if(temp) |
|
1183 { |
|
1184 temp.asAtomicValue()->ref.ref(); |
|
1185 m_node.model = reinterpret_cast<const QAbstractXmlNodeModel *>(~0); |
|
1186 m_atomicValue = temp.asAtomicValue(); |
|
1187 } |
|
1188 else |
|
1189 { |
|
1190 m_atomicValue = 0; |
|
1191 m_node.model = 0; |
|
1192 } |
|
1193 |
|
1194 m_node.additionalData = 0; |
|
1195 } |
|
1196 |
|
1197 /*! |
|
1198 Constructs a node QXmlItem that is a copy of \a node. |
|
1199 |
|
1200 \sa isNode() |
|
1201 */ |
|
1202 QXmlItem::QXmlItem(const QXmlNodeModelIndex &node) : m_node(node.m_storage) |
|
1203 { |
|
1204 } |
|
1205 |
|
1206 |
|
1207 /*! |
|
1208 Destructor. |
|
1209 */ |
|
1210 QXmlItem::~QXmlItem() |
|
1211 { |
|
1212 if(internalIsAtomicValue() && !m_atomicValue->ref.deref()) |
|
1213 delete m_atomicValue; |
|
1214 } |
|
1215 |
|
1216 bool QPatternist::NodeIndexStorage::operator!=(const NodeIndexStorage &other) const |
|
1217 { |
|
1218 return data != other.data |
|
1219 || additionalData != other.additionalData |
|
1220 || model != other.model; |
|
1221 } |
|
1222 |
|
1223 /*! |
|
1224 Assigns \a other to \c this. |
|
1225 */ |
|
1226 QXmlItem &QXmlItem::operator=(const QXmlItem &other) |
|
1227 { |
|
1228 if(m_node != other.m_node) |
|
1229 { |
|
1230 if(internalIsAtomicValue() && !m_atomicValue->ref.deref()) |
|
1231 delete m_atomicValue; |
|
1232 |
|
1233 m_node = other.m_node; |
|
1234 |
|
1235 if(internalIsAtomicValue()) |
|
1236 m_atomicValue->ref.ref(); |
|
1237 } |
|
1238 |
|
1239 return *this; |
|
1240 } |
|
1241 |
|
1242 /*! |
|
1243 Returns true if this item is a Node. Returns false if it |
|
1244 is an atomic value or null. |
|
1245 |
|
1246 \sa isNull(), isAtomicValue() |
|
1247 */ |
|
1248 bool QXmlItem::isNode() const |
|
1249 { |
|
1250 return QPatternist::Item::fromPublic(*this).isNode(); |
|
1251 } |
|
1252 |
|
1253 /*! |
|
1254 Returns true if this item is an atomic value. Returns false |
|
1255 if it is a node or null. |
|
1256 |
|
1257 \sa isNull(), isNode() |
|
1258 */ |
|
1259 bool QXmlItem::isAtomicValue() const |
|
1260 { |
|
1261 return internalIsAtomicValue(); |
|
1262 } |
|
1263 |
|
1264 /*! |
|
1265 If this QXmlItem represents an atomic value, it is converted |
|
1266 to an appropriate QVariant and returned. If this QXmlItem is |
|
1267 not an atomic value, the return value is a default constructed |
|
1268 QVariant. You can call isAtomicValue() to test whether the |
|
1269 item is an atomic value. |
|
1270 |
|
1271 \sa isAtomicValue() |
|
1272 */ |
|
1273 QVariant QXmlItem::toAtomicValue() const |
|
1274 { |
|
1275 if(isAtomicValue()) |
|
1276 return QPatternist::AtomicValue::toQt(m_atomicValue); |
|
1277 else |
|
1278 return QVariant(); |
|
1279 } |
|
1280 |
|
1281 /*! |
|
1282 If this QXmlItem represents a node, it returns the item as a |
|
1283 QXmlNodeModelIndex. If this QXmlItem is not a node, the return |
|
1284 value is undefined. You can call isNode() to test whether the |
|
1285 item is a node. |
|
1286 |
|
1287 \sa isNode() |
|
1288 */ |
|
1289 QXmlNodeModelIndex QXmlItem::toNodeModelIndex() const |
|
1290 { |
|
1291 if(isNode()) |
|
1292 return reinterpret_cast<const QXmlNodeModelIndex &>(m_node); |
|
1293 else |
|
1294 return QXmlNodeModelIndex(); |
|
1295 } |
|
1296 |
|
1297 /*! |
|
1298 Returns true if this QXmlItem is neither a node nor an |
|
1299 atomic value. Default constructed instances of QXmlItem |
|
1300 are null. |
|
1301 */ |
|
1302 bool QXmlItem::isNull() const |
|
1303 { |
|
1304 return !m_node.model; |
|
1305 } |
|
1306 |
|
1307 /*! |
|
1308 \class QXmlNodeModelIndex |
|
1309 \brief The QXmlNodeModelIndex class identifies a node in an XML node model subclassed from QAbstractXmlNodeModel. |
|
1310 \reentrant |
|
1311 \since 4.4 |
|
1312 \ingroup xml-tools |
|
1313 |
|
1314 QXmlNodeModelIndex is an index into an \l{QAbstractXmlNodeModel} |
|
1315 {XML node model}. It contains: |
|
1316 |
|
1317 \list |
|
1318 \o A pointer to an \l{QAbstractXmlNodeModel} {XML node model}, |
|
1319 which is returned by model(), and |
|
1320 \o Some data, which is returned by data(), internalPointer(), |
|
1321 and additionalData(). |
|
1322 \endlist |
|
1323 |
|
1324 Because QXmlNodeModelIndex is intentionally a simple class, it |
|
1325 doesn't have member functions for accessing the properties of |
|
1326 nodes. For example, it doesn't have functions for getting a |
|
1327 node's name or its list of attributes or child nodes. If you find |
|
1328 that you need to retrieve this kind of information from your |
|
1329 query results, there are two ways to proceed. |
|
1330 |
|
1331 \list |
|
1332 |
|
1333 \o Send the output of your XQuery to an \l{QAbstractXmlReceiver} |
|
1334 {XML receiver}, or |
|
1335 |
|
1336 \o Let your XQuery do all the work to produce the desired result. |
|
1337 |
|
1338 \endlist |
|
1339 |
|
1340 The second case is explained by example. Suppose you want to |
|
1341 populate a list widget with the values of certain attributes from a |
|
1342 set of result elements. You could write an XQuery to return the set |
|
1343 of elements, and then you would write the code to iterate over the |
|
1344 result elements, get their attributes, and extract the desired |
|
1345 string values. But the simpler way is to just augment your XQuery to |
|
1346 finding the desired attribute values. Then all you have to do is |
|
1347 evaluate the XQuery using the version of QXmlQuery::evaluateTo() |
|
1348 that populates a QStringList, which you can send directly to your |
|
1349 widget. |
|
1350 |
|
1351 QXmlNodeModelIndex doesn't impose any restrictions on the \c data |
|
1352 value an QXmlNodeModelIndex should contain. The meaning of the data |
|
1353 left to the associated \l {QAbstractXmlNodeModel} {node model}. |
|
1354 Because QXmlNodeModelIndex depends on a particular subclass of |
|
1355 QAbstractXmlNodeModel for its existence, the only way you can create |
|
1356 an instance of QXmlNodeModelIndex is by asking the node model to |
|
1357 create one for you with QAbstractXmlNodeModel::createIndex(). Since |
|
1358 that function is protected, it is usually a good ide to write a |
|
1359 public function that creates a QXmlNodeModelIndex from arguments that |
|
1360 are appropriate for your particular node model. |
|
1361 |
|
1362 A default constructed node index is said to be null, i.e., isNull() |
|
1363 returns true. |
|
1364 |
|
1365 QXmlNodeModelIndex and QAbstractXmlNodeModel follow the same design |
|
1366 pattern used for QModelIndex and QAbstractItemModel. |
|
1367 */ |
|
1368 |
|
1369 /*! |
|
1370 \since 4.4 |
|
1371 \relates QHash |
|
1372 |
|
1373 Computes a hash key from the QXmlNodeModelIndex \a index, and |
|
1374 returns it. This function would be used by QHash if you wanted |
|
1375 to build a hash table for instances of QXmlNodeModelIndex. |
|
1376 |
|
1377 The hash is computed on QXmlNodeModelIndex::data(), |
|
1378 QXmlNodeModelIndex::additionalData(), and |
|
1379 QXmlNodeModelIndex::model(). This means the hash key can be used for |
|
1380 node indexes from different node models. |
|
1381 */ |
|
1382 uint qHash(const QXmlNodeModelIndex &index) |
|
1383 { |
|
1384 return uint(index.data() + index.additionalData() + quintptr(index.model())); |
|
1385 } |
|
1386 |
|
1387 /*! |
|
1388 \enum QXmlNodeModelIndex::NodeKind |
|
1389 |
|
1390 Identifies a kind of node. |
|
1391 |
|
1392 \value Attribute Identifies an attribute node |
|
1393 \value Text Identifies a text node |
|
1394 \value Comment Identifies a comment node |
|
1395 \value Document Identifies a document node |
|
1396 \value Element Identifies an element node |
|
1397 \value Namespace Identifies a namespace node |
|
1398 \value ProcessingInstruction Identifies a processing instruction. |
|
1399 |
|
1400 Note that the optional XML declaration at very beginning of the XML |
|
1401 document is not a processing instruction |
|
1402 |
|
1403 \sa QAbstractXmlNodeModel::kind() |
|
1404 */ |
|
1405 |
|
1406 /*! |
|
1407 \typedef QXmlNodeModelIndex::List |
|
1408 |
|
1409 Typedef for QList<QXmlNodeModelIndex>. |
|
1410 */ |
|
1411 |
|
1412 /*! |
|
1413 Returns true if this node is the same as \a other. This operator |
|
1414 does not compare values, children, or names of nodes. It compares |
|
1415 node identities, i.e., whether two nodes are from the same document |
|
1416 and are found at the exact same place. |
|
1417 */ |
|
1418 bool QXmlNodeModelIndex::operator==(const QXmlNodeModelIndex &other) const |
|
1419 { |
|
1420 return !(m_storage != other.m_storage); |
|
1421 } |
|
1422 |
|
1423 /*! |
|
1424 Returns true if \a other is the same node as this. |
|
1425 */ |
|
1426 bool QXmlNodeModelIndex::operator!=(const QXmlNodeModelIndex &other) const |
|
1427 { |
|
1428 return !(operator==(other)); |
|
1429 } |
|
1430 |
|
1431 /*! |
|
1432 \fn QXmlNodeModelIndex::QXmlNodeModelIndex() |
|
1433 |
|
1434 Default constructor. Creates an item that is \c null. |
|
1435 |
|
1436 \sa isNull() |
|
1437 */ |
|
1438 |
|
1439 /*! |
|
1440 \fn QXmlNodeModelIndex::QXmlNodeModelIndex(const QXmlNodeModelIndex &other) |
|
1441 |
|
1442 Standard copy constructor. Creates a QXmlNodeModelIndex instance that |
|
1443 is a copy of \a other. |
|
1444 */ |
|
1445 |
|
1446 /*! |
|
1447 \fn bool QXmlNodeModelIndex::isNull() const |
|
1448 |
|
1449 Returns true if this QXmlNodeModelIndex is a default constructed |
|
1450 value, otherwise false. |
|
1451 |
|
1452 A null QXmlNodeModelIndex doesn't represent any node and cannot |
|
1453 be used in conjunction with QAbstractXmlNodeModel. |
|
1454 */ |
|
1455 |
|
1456 /*! |
|
1457 \fn const QAbstractXmlNodeModel *QXmlNodeModelIndex::model() const |
|
1458 |
|
1459 Returns the QAbstractXmlNodeModel that this node index refers to. |
|
1460 QXmlNodeModelIndex does not own QAbstractXmlNodeModel and does not |
|
1461 keep track of its lifetime, so this pointer will dangle if the |
|
1462 QAbstractXmlNodeModel is deallocated first. |
|
1463 |
|
1464 There is no setter for the node model because instances of |
|
1465 QXmlNodeModelIndex instances are only created with |
|
1466 QAbstractXmlNodeModel::createIndex(). |
|
1467 */ |
|
1468 |
|
1469 /*! |
|
1470 \fn qint64 QXmlNodeModelIndex::data() const |
|
1471 |
|
1472 Returns the first data value. The node index holds two data values. |
|
1473 additionalData() returns the second one. |
|
1474 |
|
1475 \sa additionalData() |
|
1476 */ |
|
1477 |
|
1478 /*! |
|
1479 \fn void *QXmlNodeModelIndex::internalPointer() const |
|
1480 |
|
1481 Returns the first data value as a void* pointer. |
|
1482 |
|
1483 \sa additionalData() |
|
1484 */ |
|
1485 |
|
1486 /*! |
|
1487 \fn qint64 QXmlNodeModelIndex::additionalData() const |
|
1488 |
|
1489 Returns the second data value. The node index holds two data values. |
|
1490 data() returns the first one. |
|
1491 |
|
1492 \sa data() |
|
1493 */ |
|
1494 |
|
1495 /*! |
|
1496 \fn void QXmlNodeModelIndex::reset() |
|
1497 \internal |
|
1498 |
|
1499 Resets this QXmlNodeModelIndex to be null. It is equivalent to |
|
1500 writing: |
|
1501 |
|
1502 \snippet doc/src/snippets/code/src_xmlpatterns_api_qabstractxmlnodemodel.cpp 0 |
|
1503 */ |
|
1504 |
|
1505 /*! |
|
1506 \fn QXmlName QXmlNodeModelIndex::name() const |
|
1507 \internal |
|
1508 */ |
|
1509 |
|
1510 /*! |
|
1511 \typedef QXmlNodeModelIndex::Iterator |
|
1512 \internal |
|
1513 |
|
1514 Typedef for QAbstractXmlForwardIterator<QXmlNodeModelIndex>. |
|
1515 */ |
|
1516 /*! |
|
1517 \fn QXmlNodeModelIndex QXmlNodeModelIndex::root() const |
|
1518 \internal |
|
1519 */ |
|
1520 |
|
1521 /*! |
|
1522 \fn QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > QXmlNodeModelIndex::iterate(const Axis axis) const |
|
1523 \internal |
|
1524 */ |
|
1525 |
|
1526 /*! |
|
1527 \fn QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QPatternist::Item> > QXmlNodeModelIndex::sequencedTypedValue() const |
|
1528 \internal |
|
1529 */ |
|
1530 |
|
1531 /*! |
|
1532 \fn QUrl QXmlNodeModelIndex::documentUri() const |
|
1533 \internal |
|
1534 */ |
|
1535 |
|
1536 /*! |
|
1537 \fn QUrl QXmlNodeModelIndex::baseUri() const |
|
1538 \internal |
|
1539 */ |
|
1540 |
|
1541 /*! |
|
1542 \fn NodeKind QXmlNodeModelIndex::kind() const |
|
1543 \internal |
|
1544 */ |
|
1545 |
|
1546 /*! |
|
1547 \fn bool QXmlNodeModelIndex::isDeepEqual(const QXmlNodeModelIndex &other) const |
|
1548 \internal |
|
1549 */ |
|
1550 |
|
1551 /*! |
|
1552 \fn DocumentOrder QXmlNodeModelIndex::compareOrder(const QXmlNodeModelIndex &other) const |
|
1553 \internal |
|
1554 */ |
|
1555 |
|
1556 /*! |
|
1557 \fn void QXmlNodeModelIndex::sendNamespaces(QAbstractXmlReceiver *const receiver) const |
|
1558 \internal |
|
1559 */ |
|
1560 |
|
1561 /*! |
|
1562 \fn QVector<QXmlName> QXmlNodeModelIndex::namespaceBindings() const |
|
1563 \internal |
|
1564 */ |
|
1565 |
|
1566 /*! |
|
1567 \fn QXmlNodeModelIndex QAbstractXmlNodeModel::elementById(const QXmlName &id) const |
|
1568 |
|
1569 Returns the index of the element identified as \a id. XQuery's \c |
|
1570 id() function calls this function. |
|
1571 |
|
1572 The node index returned will be the element node whose value is of |
|
1573 type \c ID and equals \a id, or it will be the element node that has |
|
1574 an attribute whose typed value is of type \c ID and equals \a id. If |
|
1575 there is no such element, a default constructed QXmlNodeModelIndex |
|
1576 instance is returned. The implementor guarantees that if the returned |
|
1577 node index is not null, it identifies an element. |
|
1578 |
|
1579 It is not sufficient for an attribute or element to merely be called |
|
1580 \c id. Its value type must also be \c ID. However, the reserved name |
|
1581 \c xml:id is sufficient. |
|
1582 |
|
1583 In \a id, the \c{namespace URI} and the \c{prefix} are undefined, and |
|
1584 the \c{local name} is the ID that should be looked up. |
|
1585 |
|
1586 \sa {http://www.w3.org/TR/xpath-functions/#func-id}{XQuery 1.0 and XPath 2.0 Functions and Operators, 15.5.2 fn:id} |
|
1587 */ |
|
1588 |
|
1589 /*! |
|
1590 \fn QVector<QXmlNodeModelIndex> QAbstractXmlNodeModel::nodesByIdref(const QXmlName &idref) const |
|
1591 |
|
1592 Returns the elements and/or attributes that have an \c IDREF value |
|
1593 equal to \a idref. XQuery's \c idref() function calls this function. |
|
1594 |
|
1595 The implementor guarantees that the nodes identified by the returned |
|
1596 indexes are elements or attributes. |
|
1597 |
|
1598 It is not sufficient for an attribute or element to merely be called |
|
1599 \c idref. It must also be of type \c IDREF. Elements must be typed as |
|
1600 \c xs:IDREF or \c xs:IDREFS, or, in the case of attributes, as \c |
|
1601 IDREF or \c IDREFS in the schema. |
|
1602 |
|
1603 In \a idref, the \c{namespace URI} and the \c{prefix} are undefined, |
|
1604 and the \c{local name} is the ID that should be looked up. |
|
1605 |
|
1606 \sa {http://www.w3.org/TR/xpath-functions/#func-idref}{XQuery 1.0 and XPath 2.0 Functions and Operators, 15.5.3 fn:idref} |
|
1607 */ |
|
1608 |
|
1609 /*! |
|
1610 \fn QXmlName::NamespaceCode QXmlNodeModelIndex::namespaceForPrefix(const QXmlName::PrefixCode prefix) const |
|
1611 \internal |
|
1612 */ |
|
1613 |
|
1614 /*! |
|
1615 \fn QString QXmlNodeModelIndex::stringValue() const |
|
1616 \internal |
|
1617 */ |
|
1618 |
|
1619 /*! |
|
1620 \fn QPatternist::ItemTypePtr QXmlNodeModelIndex::type() const |
|
1621 \internal |
|
1622 */ |
|
1623 |
|
1624 /*! |
|
1625 \fn bool QXmlNodeModelIndex::is(const QXmlNodeModelIndex &other) const |
|
1626 \internal |
|
1627 */ |
|
1628 |
|
1629 /*! |
|
1630 \enum QAbstractXmlNodeModel::NodeCopySetting |
|
1631 \internal |
|
1632 |
|
1633 Controls how nodes are copied with copyNodeTo. |
|
1634 |
|
1635 \value InheritNamespaces Copies the node with the \c copy-namespaces |
|
1636 setting being \c inherit. If not set, \c no-inherit is assumed. |
|
1637 \value PreserveNamespaces Copies the node with the \c copy-namespaces |
|
1638 settings being \c preserve. If not set, \c no-preserve is assumed. |
|
1639 */ |
|
1640 |
|
1641 /*! |
|
1642 \typedef QAbstractXmlNodeModel::NodeCopySettings |
|
1643 \internal |
|
1644 */ |
|
1645 |
|
1646 /*! |
|
1647 \internal |
|
1648 |
|
1649 Copies node \a node to \a receiver, steered by \a copySettings. |
|
1650 |
|
1651 The caller guarantees that \a node is not \c null, and that is |
|
1652 belongs to this QAbstractXmlNodeModel instance. |
|
1653 |
|
1654 The caller guarantees that \a receiver is not \c null. |
|
1655 */ |
|
1656 void QAbstractXmlNodeModel::copyNodeTo(const QXmlNodeModelIndex &node, |
|
1657 QAbstractXmlReceiver *const receiver, |
|
1658 const NodeCopySettings ©Settings) const |
|
1659 { |
|
1660 Q_UNUSED(node); |
|
1661 Q_UNUSED(receiver); |
|
1662 Q_UNUSED(copySettings); |
|
1663 Q_ASSERT_X(false, Q_FUNC_INFO, |
|
1664 "This function is not expected to be called."); |
|
1665 } |
|
1666 |
|
1667 /*! |
|
1668 Returns the source location for the object with the given \a index |
|
1669 or a default constructed QSourceLocation in case no location |
|
1670 information is available. |
|
1671 |
|
1672 \since 4.6 |
|
1673 */ |
|
1674 QSourceLocation QAbstractXmlNodeModel::sourceLocation(const QXmlNodeModelIndex &index) const |
|
1675 { |
|
1676 // TODO: make this method virtual in Qt5 to allow source location support in custom models |
|
1677 if (d_ptr) |
|
1678 return d_ptr->sourceLocation(index); |
|
1679 else |
|
1680 return QSourceLocation(); |
|
1681 } |
|
1682 |
|
1683 QT_END_NAMESPACE |