89221501607ff9c271f42dd5e1617eeffda22a18
[WebKit-https.git] / WebKit / qt / Api / qwebelement.cpp
1 /*
2     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21 #include "qwebelement.h"
22
23 #include "CSSComputedStyleDeclaration.h"
24 #include "CSSMutableStyleDeclaration.h"
25 #include "CSSParser.h"
26 #include "CSSRule.h"
27 #include "CSSRuleList.h"
28 #include "CSSStyleRule.h"
29 #include "CString.h"
30 #include "Document.h"
31 #include "DocumentFragment.h"
32 #include "FrameView.h"
33 #include "GraphicsContext.h"
34 #include "HTMLElement.h"
35 #include "JSGlobalObject.h"
36 #include "JSHTMLElement.h"
37 #include "JSObject.h"
38 #include "NodeList.h"
39 #include "PropertyNameArray.h"
40 #include "RenderImage.h"
41 #include "ScriptFunctionCall.h"
42 #include "StaticNodeList.h"
43 #include "qt_runtime.h"
44 #include "qwebframe.h"
45 #include "qwebframe_p.h"
46 #include "runtime_root.h"
47 #include <parser/SourceCode.h>
48 #include <wtf/Vector.h>
49
50 #include <QPainter>
51
52 using namespace WebCore;
53
54 class QWebElementPrivate {
55 public:
56 };
57
58 /*!
59     \class QWebElement
60     \since 4.6
61     \brief The QWebElement class provides convenient access to DOM elements in
62     a QWebFrame.
63     \inmodule QtWebKit
64
65     A QWebElement object allows easy access to the document model, represented
66     by a tree-like structure of DOM elements. The root of the tree is called
67     the document element and can be accessed using
68     QWebFrame::documentElement().
69
70     Specific elements can be accessed using findAll() and findFirst(). These
71     elements are identified using CSS selectors. The code snippet below
72     demonstrates the use of findAll().
73
74     \snippet webkitsnippets/webelement/main.cpp FindAll
75
76     The first list contains all \c span elements in the document. The second
77     list contains \c span elements that are children of \c p, classified with
78     \c intro.
79
80     Using findFirst() is more efficient than calling findAll(), and extracting
81     the first element only in the list returned.
82
83     Alternatively you can traverse the document manually using firstChild() and
84     nextSibling():
85
86     \snippet webkitsnippets/webelement/main.cpp Traversing with QWebElement
87
88     The underlying content of QWebElement is explicitly shared. Creating a copy
89     of a QWebElement does not create a copy of the content. Instead, both
90     instances point to the same element.
91
92     The element's attributes can be read using attribute() and modified with
93     setAttribute().
94
95     The contents of child elements can be converted to plain text with
96     toPlainText(); to XHTML using toInnerXml(). To include the element's tag in
97     the output, use toOuterXml().
98
99     It is possible to replace the contents of child elements using
100     setPlainText() and setInnerXml(). To replace the element itself and its
101     contents, use setOuterXml().
102 */
103
104 /*!
105     Constructs a null web element.
106 */
107 QWebElement::QWebElement()
108     : d(0)
109     , m_element(0)
110 {
111 }
112
113 /*!
114     \internal
115 */
116 QWebElement::QWebElement(WebCore::Element* domElement)
117     : d(0)
118     , m_element(domElement)
119 {
120     if (m_element)
121         m_element->ref();
122 }
123
124 /*!
125     \internal
126 */
127 QWebElement::QWebElement(WebCore::Node* node)
128     : d(0)
129     , m_element(0)
130 {
131     if (node && node->isHTMLElement()) {
132         m_element = static_cast<HTMLElement*>(node);
133         m_element->ref();
134     }
135 }
136
137 /*!
138     Constructs a copy of \a other.
139 */
140 QWebElement::QWebElement(const QWebElement &other)
141     : d(0)
142     , m_element(other.m_element)
143 {
144     if (m_element)
145         m_element->ref();
146 }
147
148 /*!
149     Assigns \a other to this element and returns a reference to this element.
150 */
151 QWebElement &QWebElement::operator=(const QWebElement &other)
152 {
153     // ### handle "d" assignment
154     if (this != &other) {
155         Element *otherElement = other.m_element;
156         if (otherElement)
157             otherElement->ref();
158         if (m_element)
159             m_element->deref();
160         m_element = otherElement;
161     }
162     return *this;
163 }
164
165 /*!
166     Destroys the element. However, the underlying DOM element is not destroyed.
167 */
168 QWebElement::~QWebElement()
169 {
170     delete d;
171     if (m_element)
172         m_element->deref();
173 }
174
175 bool QWebElement::operator==(const QWebElement& o) const
176 {
177     return m_element == o.m_element;
178 }
179
180 bool QWebElement::operator!=(const QWebElement& o) const
181 {
182     return m_element != o.m_element;
183 }
184
185 /*!
186     Returns true if the element is a null element; otherwise returns false.
187 */
188 bool QWebElement::isNull() const
189 {
190     return !m_element;
191 }
192
193 /*!
194     Returns a new list of child elements matching the given CSS selector
195     \a selectorQuery. If there are no matching elements, an empty list is
196     returned.
197
198     \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector}
199     syntax is used for the query.
200
201     \note This search is performed recursively.
202
203     \sa findFirst()
204 */
205 QWebElementCollection QWebElement::findAll(const QString &selectorQuery) const
206 {
207     return QWebElementCollection(*this, selectorQuery);
208 }
209
210 /*!
211     Returns the first child element that matches the given CSS selector
212     \a selectorQuery.
213
214     \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector}
215     syntax is used for the query.
216
217     \note This search is performed recursively.
218
219     \sa findAll()
220 */
221 QWebElement QWebElement::findFirst(const QString &selectorQuery) const
222 {
223     if (!m_element)
224         return QWebElement();
225     ExceptionCode exception = 0; // ###
226     return QWebElement(m_element->querySelector(selectorQuery, exception).get());
227 }
228
229 /*!
230     Replaces the existing content of this element with \a text.
231
232     This is equivalent to setting the HTML innerText property.
233
234     \sa toPlainText()
235 */
236 void QWebElement::setPlainText(const QString &text)
237 {
238     if (!m_element || !m_element->isHTMLElement())
239         return;
240     ExceptionCode exception = 0;
241     static_cast<HTMLElement*>(m_element)->setInnerText(text, exception);
242 }
243
244 /*!
245     Returns the text between the start and the end tag of this
246     element.
247
248     This is equivalent to reading the HTML innerText property.
249
250     \sa setPlainText()
251 */
252 QString QWebElement::toPlainText() const
253 {
254     if (!m_element || !m_element->isHTMLElement())
255         return QString();
256     return static_cast<HTMLElement*>(m_element)->innerText();
257 }
258
259 /*!
260     Replaces the contents of this element as well as its own tag with
261     \a markup. The string may contain HTML or XML tags, which is parsed and
262     formatted before insertion into the document.
263
264     \note This is currently only implemented for (X)HTML elements.
265
266     \sa toOuterXml(), toInnerXml(), setInnerXml()
267 */
268 void QWebElement::setOuterXml(const QString &markup)
269 {
270     if (!m_element || !m_element->isHTMLElement())
271         return;
272
273     ExceptionCode exception = 0;
274
275     static_cast<HTMLElement*>(m_element)->setOuterHTML(markup, exception);
276 }
277
278 /*!
279     Returns this element converted to XML, including the start and the end
280     tags as well as its attributes.
281
282     \note This is currently implemented for (X)HTML elements only.
283
284     \sa setOuterXml(), setInnerXml(), toInnerXml()
285 */
286 QString QWebElement::toOuterXml() const
287 {
288     if (!m_element || !m_element->isHTMLElement())
289         return QString();
290
291     return static_cast<HTMLElement*>(m_element)->outerHTML();
292 }
293
294 /*!
295     Replaces the contents of this element with \a markup. The string may
296     contain HTML or XML tags, which is parsed and formatted before insertion
297     into the document.
298
299     \note This is currently implemented for (X)HTML elements only.
300
301     \sa toInnerXml(), toOuterXml(), setOuterXml()
302 */
303 void QWebElement::setInnerXml(const QString &markup)
304 {
305     if (!m_element || !m_element->isHTMLElement())
306         return;
307
308     ExceptionCode exception = 0;
309
310     static_cast<HTMLElement*>(m_element)->setInnerHTML(markup, exception);
311 }
312
313 /*!
314     Returns the XML content between the element's start and end tags.
315
316     \note This is currently implemented for (X)HTML elements only.
317
318     \sa setInnerXml(), setOuterXml(), toOuterXml()
319 */
320 QString QWebElement::toInnerXml() const
321 {
322     if (!m_element || !m_element->isHTMLElement())
323         return QString();
324
325     return static_cast<HTMLElement*>(m_element)->innerHTML();
326 }
327
328 /*!
329     Adds an attribute with the given \a name and \a value. If an attribute with
330     the same name exists, its value is replaced by \a value.
331
332     \sa attribute(), attributeNS(), setAttributeNS()
333 */
334 void QWebElement::setAttribute(const QString &name, const QString &value)
335 {
336     if (!m_element)
337         return;
338     ExceptionCode exception = 0;
339     m_element->setAttribute(name, value, exception);
340 }
341
342 /*!
343     Adds an attribute with the given \a name in \a namespaceUri with \a value.
344     If an attribute with the same name exists, its value is replaced by
345     \a value.
346
347     \sa attributeNS(), attribute(), setAttribute()
348 */
349 void QWebElement::setAttributeNS(const QString &namespaceUri, const QString &name, const QString &value)
350 {
351     if (!m_element)
352         return;
353     WebCore::ExceptionCode exception = 0;
354     m_element->setAttributeNS(namespaceUri, name, value, exception);
355 }
356
357 /*!
358     Returns the attribute with the given \a name. If the attribute does not
359     exist, \a defaultValue is returned.
360
361     \sa setAttribute(), setAttributeNS(), attributeNS()
362 */
363 QString QWebElement::attribute(const QString &name, const QString &defaultValue) const
364 {
365     if (!m_element)
366         return QString();
367     if (m_element->hasAttribute(name))
368         return m_element->getAttribute(name);
369     else
370         return defaultValue;
371 }
372
373 /*!
374     Returns the attribute with the given \a name in \a namespaceUri. If the
375     attribute does not exist, \a defaultValue is returned.
376
377     \sa setAttributeNS(), setAttribute(), attribute()
378 */
379 QString QWebElement::attributeNS(const QString &namespaceUri, const QString &name, const QString &defaultValue) const
380 {
381     if (!m_element)
382         return QString();
383     if (m_element->hasAttributeNS(namespaceUri, name))
384         return m_element->getAttributeNS(namespaceUri, name);
385     else
386         return defaultValue;
387 }
388
389 /*!
390     Returns true if this element has an attribute with the given \a name;
391     otherwise returns false.
392
393     \sa attribute(), setAttribute()
394 */
395 bool QWebElement::hasAttribute(const QString &name) const
396 {
397     if (!m_element)
398         return false;
399     return m_element->hasAttribute(name);
400 }
401
402 /*!
403     Returns true if this element has an attribute with the given \a name, in
404     \a namespaceUri; otherwise returns false.
405
406     \sa attributeNS(), setAttributeNS()
407 */
408 bool QWebElement::hasAttributeNS(const QString &namespaceUri, const QString &name) const
409 {
410     if (!m_element)
411         return false;
412     return m_element->hasAttributeNS(namespaceUri, name);
413 }
414
415 /*!
416     Removes the attribute with the given \a name from this element.
417
418     \sa attribute(), setAttribute(), hasAttribute()
419 */
420 void QWebElement::removeAttribute(const QString &name)
421 {
422     if (!m_element)
423         return;
424     ExceptionCode exception = 0;
425     m_element->removeAttribute(name, exception);
426 }
427
428 /*!
429     Removes the attribute with the given \a name, in \a namespaceUri, from this
430     element.
431
432     \sa attributeNS(), setAttributeNS(), hasAttributeNS()
433 */
434 void QWebElement::removeAttributeNS(const QString &namespaceUri, const QString &name)
435 {
436     if (!m_element)
437         return;
438     WebCore::ExceptionCode exception = 0;
439     m_element->removeAttributeNS(namespaceUri, name, exception);
440 }
441
442 /*!
443     Returns true if the element has any attributes defined; otherwise returns
444     false;
445
446     \sa attribute(), setAttribute()
447 */
448 bool QWebElement::hasAttributes() const
449 {
450     if (!m_element)
451         return false;
452     return m_element->hasAttributes();
453 }
454
455 /*!
456     Return the list of attributes for the namespace given as \a namespaceUri.
457
458     \sa attribute(), setAttribute()
459 */
460 QStringList QWebElement::attributeNames(const QString& namespaceUri) const
461 {
462     if (!m_element)
463         return QStringList();
464
465     QStringList attributeNameList;
466     const NamedNodeMap* const attrs = m_element->attributes(/* read only = */ true);
467     if (attrs) {
468         const String namespaceUriString(namespaceUri); // convert QString -> String once
469         const unsigned attrsCount = attrs->length();
470         for (unsigned i = 0; i < attrsCount; ++i) {
471             const Attribute* const attribute = attrs->attributeItem(i);
472             if (namespaceUriString == attribute->namespaceURI())
473                 attributeNameList.append(attribute->localName());
474         }
475     }
476     return attributeNameList;
477 }
478
479 /*!
480     Returns true if the element has keyboard input focus; otherwise, returns false
481
482     \sa setFocus()
483 */
484 bool QWebElement::hasFocus() const
485 {
486     if (!m_element)
487         return false;
488     if (m_element->document())
489         return m_element == m_element->document()->focusedNode();
490     return false;
491 }
492
493 /*!
494     Gives keyboard input focus to this element
495
496     \sa hasFocus()
497 */
498 void QWebElement::setFocus()
499 {
500     if (!m_element)
501         return;
502     if (m_element->document() && m_element->isFocusable())
503         m_element->document()->setFocusedNode(m_element);
504 }
505
506 /*!
507     Returns the geometry of this element, relative to its containing frame.
508
509     \sa tagName()
510 */
511 QRect QWebElement::geometry() const
512 {
513     if (!m_element)
514         return QRect();
515     return m_element->getRect();
516 }
517
518 /*!
519     Returns the tag name of this element.
520
521     \sa geometry()
522 */
523 QString QWebElement::tagName() const
524 {
525     if (!m_element)
526         return QString();
527     return m_element->tagName();
528 }
529
530 /*!
531     Returns the namespace prefix of the element. If the element has no\
532     namespace prefix, empty string is returned.
533 */
534 QString QWebElement::prefix() const
535 {
536     if (!m_element)
537         return QString();
538     return m_element->prefix();
539 }
540
541 /*!
542     Returns the local name of the element. If the element does not use
543     namespaces, an empty string is returned.
544 */
545 QString QWebElement::localName() const
546 {
547     if (!m_element)
548         return QString();
549     return m_element->localName();
550 }
551
552 /*!
553     Returns the namespace URI of this element. If the element has no namespace
554     URI, an empty string is returned.
555 */
556 QString QWebElement::namespaceUri() const
557 {
558     if (!m_element)
559         return QString();
560     return m_element->namespaceURI();
561 }
562
563 /*!
564     Returns the parent element of this elemen. If this element is the root
565     document element, a null element is returned.
566 */
567 QWebElement QWebElement::parent() const
568 {
569     if (m_element)
570         return QWebElement(m_element->parentElement());
571     return QWebElement();
572 }
573
574 /*!
575     Returns the element's first child.
576
577     \sa lastChild(), previousSibling(), nextSibling()
578 */
579 QWebElement QWebElement::firstChild() const
580 {
581     if (!m_element)
582         return QWebElement();
583     for (Node* child = m_element->firstChild(); child; child = child->nextSibling()) {
584         if (!child->isElementNode())
585             continue;
586         Element* e = static_cast<Element*>(child);
587         return QWebElement(e);
588     }
589     return QWebElement();
590 }
591
592 /*!
593     Returns the element's last child.
594
595     \sa firstChild(), previousSibling(), nextSibling()
596 */
597 QWebElement QWebElement::lastChild() const
598 {
599     if (!m_element)
600         return QWebElement();
601     for (Node* child = m_element->lastChild(); child; child = child->previousSibling()) {
602         if (!child->isElementNode())
603             continue;
604         Element* e = static_cast<Element*>(child);
605         return QWebElement(e);
606     }
607     return QWebElement();
608 }
609
610 /*!
611     Returns the element's next sibling.
612
613     \sa firstChild(), previousSibling(), lastChild()
614 */
615 QWebElement QWebElement::nextSibling() const
616 {
617     if (!m_element)
618         return QWebElement();
619     for (Node* sib = m_element->nextSibling(); sib; sib = sib->nextSibling()) {
620         if (!sib->isElementNode())
621             continue;
622         Element* e = static_cast<Element*>(sib);
623         return QWebElement(e);
624     }
625     return QWebElement();
626 }
627
628 /*!
629     Returns the element's previous sibling.
630
631     \sa firstChild(), nextSibling(), lastChild()
632 */
633 QWebElement QWebElement::previousSibling() const
634 {
635     if (!m_element)
636         return QWebElement();
637     for (Node* sib = m_element->previousSibling(); sib; sib = sib->previousSibling()) {
638         if (!sib->isElementNode())
639             continue;
640         Element* e = static_cast<Element*>(sib);
641         return QWebElement(e);
642     }
643     return QWebElement();
644 }
645
646 /*!
647     Returns the document which this element belongs to.
648 */
649 QWebElement QWebElement::document() const
650 {
651     if (!m_element)
652         return QWebElement();
653     Document* document = m_element->document();
654     if (!document)
655         return QWebElement();
656     return QWebElement(document->documentElement());
657 }
658
659 /*!
660     Returns the web frame which this element is a part of. If the element is a
661     null element, null is returned.
662 */
663 QWebFrame *QWebElement::webFrame() const
664 {
665     if (!m_element)
666         return 0;
667
668     Document* document = m_element->document();
669     if (!document)
670         return 0;
671
672     Frame* frame = document->frame();
673     if (!frame)
674         return 0;
675     return QWebFramePrivate::kit(frame);
676 }
677
678 static bool setupScriptContext(WebCore::Element* element, JSC::JSValue& thisValue, ScriptState*& state, ScriptController*& scriptController)
679 {
680     if (!element)
681         return false;
682
683     Document* document = element->document();
684     if (!document)
685         return false;
686
687     Frame* frame = document->frame();
688     if (!frame)
689         return false;
690
691     scriptController = frame->script();
692     if (!scriptController)
693         return false;
694
695     state = scriptController->globalObject(mainThreadNormalWorld())->globalExec();
696     if (!state)
697         return false;
698
699     thisValue = toJS(state, element);
700     if (!thisValue)
701         return false;
702
703     return true;
704 }
705
706
707 /*!
708     Executes \a scriptSource with this element as \c this object.
709 */
710 QVariant QWebElement::evaluateJavaScript(const QString& scriptSource)
711 {
712     if (scriptSource.isEmpty())
713         return QVariant();
714
715     ScriptState* state = 0;
716     JSC::JSValue thisValue;
717     ScriptController* scriptController = 0;
718
719     if (!setupScriptContext(m_element, thisValue, state, scriptController))
720         return QVariant();
721
722     JSC::ScopeChain& scopeChain = state->dynamicGlobalObject()->globalScopeChain();
723     JSC::UString script((const UChar*)scriptSource.data(), scriptSource.length());
724     JSC::Completion completion = JSC::evaluate(state, scopeChain, JSC::makeSource(script), thisValue);
725     if ((completion.complType() != JSC::ReturnValue) && (completion.complType() != JSC::Normal))
726         return QVariant();
727
728     JSC::JSValue result = completion.value();
729     if (!result)
730         return QVariant();
731
732     int distance = 0;
733     return JSC::Bindings::convertValueToQVariant(state, result, QMetaType::Void, &distance);
734 }
735
736 /*!
737     \enum QWebElement::StyleResolveStrategy
738
739     This enum describes how QWebElement's styleProperty resolves the given
740     property name.
741
742     \value InlineStyle Return the property value as it is defined in
743            the element, without respecting style inheritance and other CSS
744            rules.
745     \value CascadedStyle The property's value is determined using the
746            inheritance and importance rules defined in the document's
747            stylesheet.
748     \value ComputedStyle The property's value is the absolute value
749            of the style property resolved from the environment.
750 */
751
752 /*!
753     Returns the value of the style with the given \a name using the specified
754     \a strategy. If a style with \a name does not exist, an empty string is
755     returned.
756
757     In CSS, the cascading part depends on which CSS rule has priority and is
758     thus applied. Generally, the last defined rule has priority. Thus, an
759     inline style rule has priority over an embedded block style rule, which
760     in return has priority over an external style rule.
761
762     If the "!important" declaration is set on one of those, the declaration
763     receives highest priority, unless other declarations also use the
764     "!important" declaration. Then, the last "!important" declaration takes
765     predecence.
766
767     \sa setStyleProperty()
768 */
769
770 QString QWebElement::styleProperty(const QString &name, StyleResolveStrategy strategy) const
771 {
772     if (!m_element || !m_element->isStyledElement())
773         return QString();
774
775     int propID = cssPropertyID(name);
776
777     if (!propID)
778         return QString();
779
780     CSSStyleDeclaration* style = static_cast<StyledElement*>(m_element)->style();
781
782     if (strategy == InlineStyle)
783         return style->getPropertyValue(propID);
784
785     if (strategy == CascadedStyle) {
786         if (style->getPropertyPriority(propID))
787             return style->getPropertyValue(propID);
788
789         // We are going to resolve the style property by walking through the
790         // list of non-inline matched CSS rules for the element, looking for
791         // the highest priority definition.
792
793         // Get an array of matched CSS rules for the given element sorted
794         // by importance and inheritance order. This include external CSS
795         // declarations, as well as embedded and inline style declarations.
796
797         DOMWindow* domWindow = m_element->document()->frame()->domWindow();
798         if (RefPtr<CSSRuleList> rules = domWindow->getMatchedCSSRules(m_element, "")) {
799             for (int i = rules->length(); i > 0; --i) {
800                 CSSStyleRule* rule = static_cast<CSSStyleRule*>(rules->item(i - 1));
801
802                 if (rule->style()->getPropertyPriority(propID))
803                     return rule->style()->getPropertyValue(propID);
804
805                 if (style->getPropertyValue(propID).isEmpty())
806                     style = rule->style();
807             }
808         }
809
810         return style->getPropertyValue(propID);
811     }
812
813     if (strategy == ComputedStyle) {
814         if (!m_element || !m_element->isStyledElement())
815             return QString();
816
817         int propID = cssPropertyID(name);
818
819         RefPtr<CSSComputedStyleDeclaration> style = computedStyle(m_element);
820         if (!propID || !style)
821             return QString();
822
823         return style->getPropertyValue(propID);
824     }
825
826     return QString();
827 }
828
829 /*!
830     Sets the value of the inline style with the given \a name to \a value.
831
832     Setting a value, does not necessarily mean that it will become the applied
833     value, due to the fact that the style property's value might have been set
834     earlier with a higher priority in external or embedded style declarations.
835
836     In order to ensure that the value will be applied, you may have to append
837     "!important" to the value.
838 */
839 void QWebElement::setStyleProperty(const QString &name, const QString &value)
840 {
841     if (!m_element || !m_element->isStyledElement())
842         return;
843
844     int propID = cssPropertyID(name);
845     CSSStyleDeclaration* style = static_cast<StyledElement*>(m_element)->style();
846     if (!propID || !style)
847         return;
848
849     ExceptionCode exception = 0;
850     style->setProperty(name, value, exception);
851 }
852
853 /*!
854     Returns the list of classes of this element.
855 */
856 QStringList QWebElement::classes() const
857 {
858     if (!hasAttribute(QLatin1String("class")))
859         return QStringList();
860
861     QStringList classes =  attribute(QLatin1String("class")).simplified().split(QLatin1Char(' '), QString::SkipEmptyParts);
862 #if QT_VERSION >= 0x040500
863     classes.removeDuplicates();
864 #else
865     int n = classes.size();
866     int j = 0;
867     QSet<QString> seen;
868     seen.reserve(n);
869     for (int i = 0; i < n; ++i) {
870         const QString& s = classes.at(i);
871         if (seen.contains(s))
872             continue;
873         seen.insert(s);
874         if (j != i)
875             classes[j] = s;
876         ++j;
877     }
878     if (n != j)
879         classes.erase(classes.begin() + j, classes.end());
880 #endif
881     return classes;
882 }
883
884 /*!
885     Returns true if this element has a class with the given \a name; otherwise
886     returns false.
887 */
888 bool QWebElement::hasClass(const QString &name) const
889 {
890     QStringList list = classes();
891     return list.contains(name);
892 }
893
894 /*!
895     Adds the specified class with the given \a name to the element.
896 */
897 void QWebElement::addClass(const QString &name)
898 {
899     QStringList list = classes();
900     if (!list.contains(name)) {
901         list.append(name);
902         QString value = list.join(QLatin1String(" "));
903         setAttribute(QLatin1String("class"), value);
904     }
905 }
906
907 /*!
908     Removes the specified class with the given \a name from the element.
909 */
910 void QWebElement::removeClass(const QString &name)
911 {
912     QStringList list = classes();
913     if (list.contains(name)) {
914         list.removeAll(name);
915         QString value = list.join(QLatin1String(" "));
916         setAttribute(QLatin1String("class"), value);
917     }
918 }
919
920 /*!
921     Adds the specified class with the given \a name if it is not present. If
922     the class is already present, it will be removed.
923 */
924 void QWebElement::toggleClass(const QString &name)
925 {
926     QStringList list = classes();
927     if (list.contains(name))
928         list.removeAll(name);
929     else
930         list.append(name);
931
932     QString value = list.join(QLatin1String(" "));
933     setAttribute(QLatin1String("class"), value);
934 }
935
936 /*!
937     Appends the given \a element as the element's last child.
938
939     If \a element is the child of another element, it is re-parented to this
940     element. If \a element is a child of this element, then its position in
941     the list of children is changed.
942
943     Calling this function on a null element does nothing.
944
945     \sa prependInside(), prependOutside(), appendOutside()
946 */
947 void QWebElement::appendInside(const QWebElement &element)
948 {
949     if (!m_element || element.isNull())
950         return;
951
952     ExceptionCode exception = 0;
953     m_element->appendChild(element.m_element, exception);
954 }
955
956 /*!
957     Appends the result of parsing \a markup as the element's last child.
958
959     Calling this function on a null element does nothing.
960
961     \sa prependInside(), prependOutside(), appendOutside()
962 */
963 void QWebElement::appendInside(const QString &markup)
964 {
965     if (!m_element)
966         return;
967
968     if (!m_element->isHTMLElement())
969         return;
970
971     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
972     RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
973
974     ExceptionCode exception = 0;
975     m_element->appendChild(fragment, exception);
976 }
977
978 /*!
979     Prepends \a element as the element's first child.
980
981     If \a element is the child of another element, it is re-parented to this
982     element. If \a element is a child of this element, then its position in
983     the list of children is changed.
984
985     Calling this function on a null element does nothing.
986
987     \sa appendInside(), prependOutside(), appendOutside()
988 */
989 void QWebElement::prependInside(const QWebElement &element)
990 {
991     if (!m_element || element.isNull())
992         return;
993
994     ExceptionCode exception = 0;
995
996     if (m_element->hasChildNodes())
997         m_element->insertBefore(element.m_element, m_element->firstChild(), exception);
998     else
999         m_element->appendChild(element.m_element, exception);
1000 }
1001
1002 /*!
1003     Prepends the result of parsing \a markup as the element's first child.
1004
1005     Calling this function on a null element does nothing.
1006
1007     \sa appendInside(), prependOutside(), appendOutside()
1008 */
1009 void QWebElement::prependInside(const QString &markup)
1010 {
1011     if (!m_element)
1012         return;
1013
1014     if (!m_element->isHTMLElement())
1015         return;
1016
1017     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1018     RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1019
1020     ExceptionCode exception = 0;
1021
1022     if (m_element->hasChildNodes())
1023         m_element->insertBefore(fragment, m_element->firstChild(), exception);
1024     else
1025         m_element->appendChild(fragment, exception);
1026 }
1027
1028
1029 /*!
1030     Inserts the given \a element before this element.
1031
1032     If \a element is the child of another element, it is re-parented to the
1033     parent of this element.
1034
1035     Calling this function on a null element does nothing.
1036
1037     \sa appendInside(), prependInside(), appendOutside()
1038 */
1039 void QWebElement::prependOutside(const QWebElement &element)
1040 {
1041     if (!m_element || element.isNull())
1042         return;
1043
1044     if (!m_element->parent())
1045         return;
1046
1047     ExceptionCode exception = 0;
1048     m_element->parent()->insertBefore(element.m_element, m_element, exception);
1049 }
1050
1051 /*!
1052     Inserts the result of parsing \a markup before this element.
1053
1054     Calling this function on a null element does nothing.
1055
1056     \sa appendInside(), prependInside(), appendOutside()
1057 */
1058 void QWebElement::prependOutside(const QString &markup)
1059 {
1060     if (!m_element)
1061         return;
1062
1063     if (!m_element->parent())
1064         return;
1065
1066     if (!m_element->isHTMLElement())
1067         return;
1068
1069     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1070     RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1071
1072     ExceptionCode exception = 0;
1073     m_element->parent()->insertBefore(fragment, m_element, exception);
1074 }
1075
1076 /*!
1077     Inserts the given \a element after this element.
1078
1079     If \a element is the child of another element, it is re-parented to the
1080     parent of this element.
1081
1082     Calling this function on a null element does nothing.
1083
1084     \sa appendInside(), prependInside(), prependOutside()
1085 */
1086 void QWebElement::appendOutside(const QWebElement &element)
1087 {
1088     if (!m_element || element.isNull())
1089         return;
1090
1091     if (!m_element->parent())
1092         return;
1093
1094     ExceptionCode exception = 0;
1095     if (!m_element->nextSibling())
1096         m_element->parent()->appendChild(element.m_element, exception);
1097     else
1098         m_element->parent()->insertBefore(element.m_element, m_element->nextSibling(), exception);
1099 }
1100
1101 /*!
1102     Inserts the result of parsing \a markup after this element.
1103
1104     Calling this function on a null element does nothing.
1105
1106     \sa appendInside(), prependInside(), prependOutside()
1107 */
1108 void QWebElement::appendOutside(const QString &markup)
1109 {
1110     if (!m_element)
1111         return;
1112
1113     if (!m_element->parent())
1114         return;
1115
1116     if (!m_element->isHTMLElement())
1117         return;
1118
1119     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1120     RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1121
1122     ExceptionCode exception = 0;
1123     if (!m_element->nextSibling())
1124         m_element->parent()->appendChild(fragment, exception);
1125     else
1126         m_element->parent()->insertBefore(fragment, m_element->nextSibling(), exception);
1127 }
1128
1129 /*!
1130     Returns a clone of this element.
1131
1132     The clone may be inserted at any point in the document.
1133
1134     \sa appendInside(), prependInside(), prependOutside(), appendOutside()
1135 */
1136 QWebElement QWebElement::clone() const
1137 {
1138     if (!m_element)
1139         return QWebElement();
1140
1141     return QWebElement(m_element->cloneElementWithChildren().get());
1142 }
1143
1144 /*!
1145     Removes this element from the document and returns a reference to it.
1146
1147     The element is still valid after removal, and can be inserted into other
1148     parts of the document.
1149
1150     \sa removeAllChildren(), removeFromDocument()
1151 */
1152 QWebElement &QWebElement::takeFromDocument()
1153 {
1154     if (!m_element)
1155         return *this;
1156
1157     ExceptionCode exception = 0;
1158     m_element->remove(exception);
1159
1160     return *this;
1161 }
1162
1163 /*!
1164     Removes this element from the document and makes it a null element.
1165
1166     \sa removeAllChildren(), takeFromDocument()
1167 */
1168 void QWebElement::removeFromDocument()
1169 {
1170     if (!m_element)
1171         return;
1172
1173     ExceptionCode exception = 0;
1174     m_element->remove(exception);
1175     m_element->deref();
1176     m_element = 0;
1177 }
1178
1179 /*!
1180     Removes all children from this element.
1181
1182     \sa removeFromDocument(), takeFromDocument()
1183 */
1184 void QWebElement::removeAllChildren()
1185 {
1186     if (!m_element)
1187         return;
1188
1189     m_element->removeAllChildren();
1190 }
1191
1192 static RefPtr<Node> findInsertionPoint(PassRefPtr<Node> root)
1193 {
1194     RefPtr<Node> node = root;
1195
1196     // Go as far down the tree as possible.
1197     while (node->hasChildNodes() && node->firstChild()->isElementNode())
1198         node = node->firstChild();
1199
1200     // TODO: Implement SVG support
1201     if (node->isHTMLElement()) {
1202         HTMLElement* element = static_cast<HTMLElement*>(node.get());
1203
1204         // The insert point could be a non-enclosable tag and it can thus
1205         // never have children, so go one up. Get the parent element, and not
1206         // note as a root note will always exist.
1207         if (element->endTagRequirement() == TagStatusForbidden)
1208             node = node->parentElement();
1209     }
1210
1211     return node;
1212 }
1213
1214 /*!
1215     Encloses the contents of this element with \a element. This element becomes
1216     the child of the deepest descendant within \a element.
1217
1218     ### illustration
1219
1220     \sa encloseWith()
1221 */
1222 void QWebElement::encloseContentsWith(const QWebElement &element)
1223 {
1224     if (!m_element || element.isNull())
1225         return;
1226
1227     RefPtr<Node> insertionPoint = findInsertionPoint(element.m_element);
1228
1229     if (!insertionPoint)
1230         return;
1231
1232     ExceptionCode exception = 0;
1233
1234     // reparent children
1235     for (RefPtr<Node> child = m_element->firstChild(); child;) {
1236         RefPtr<Node> next = child->nextSibling();
1237         insertionPoint->appendChild(child, exception);
1238         child = next;
1239     }
1240
1241     if (m_element->hasChildNodes())
1242         m_element->insertBefore(element.m_element, m_element->firstChild(), exception);
1243     else
1244         m_element->appendChild(element.m_element, exception);
1245 }
1246
1247 /*!
1248     Encloses the contents of this element with the result of parsing \a markup.
1249     This element becomes the child of the deepest descendant within \a markup.
1250
1251     \sa encloseWith()
1252 */
1253 void QWebElement::encloseContentsWith(const QString &markup)
1254 {
1255     if (!m_element)
1256         return;
1257
1258     if (!m_element->parent())
1259         return;
1260
1261     if (!m_element->isHTMLElement())
1262         return;
1263
1264     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1265     RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1266
1267     if (!fragment || !fragment->firstChild())
1268         return;
1269
1270     RefPtr<Node> insertionPoint = findInsertionPoint(fragment->firstChild());
1271
1272     if (!insertionPoint)
1273         return;
1274
1275     ExceptionCode exception = 0;
1276
1277     // reparent children
1278     for (RefPtr<Node> child = m_element->firstChild(); child;) {
1279         RefPtr<Node> next = child->nextSibling();
1280         insertionPoint->appendChild(child, exception);
1281         child = next;
1282     }
1283
1284     if (m_element->hasChildNodes())
1285         m_element->insertBefore(fragment, m_element->firstChild(), exception);
1286     else
1287         m_element->appendChild(fragment, exception);
1288 }
1289
1290 /*!
1291     Encloses this element with \a element. This element becomes the child of
1292     the deepest descendant within \a element.
1293
1294     \sa replace()
1295 */
1296 void QWebElement::encloseWith(const QWebElement &element)
1297 {
1298     if (!m_element || element.isNull())
1299         return;
1300
1301     RefPtr<Node> insertionPoint = findInsertionPoint(element.m_element);
1302
1303     if (!insertionPoint)
1304         return;
1305
1306     // Keep reference to these two nodes before pulling out this element and
1307     // wrapping it in the fragment. The reason for doing it in this order is
1308     // that once the fragment has been added to the document it is empty, so
1309     // we no longer have access to the nodes it contained.
1310     Node* parentNode = m_element->parent();
1311     Node* siblingNode = m_element->nextSibling();
1312
1313     ExceptionCode exception = 0;
1314     insertionPoint->appendChild(m_element, exception);
1315
1316     if (!siblingNode)
1317         parentNode->appendChild(element.m_element, exception);
1318     else
1319         parentNode->insertBefore(element.m_element, siblingNode, exception);
1320 }
1321
1322 /*!
1323     Encloses this element with the result of parsing \a markup. This element
1324     becomes the child of the deepest descendant within \a markup.
1325
1326     \sa replace()
1327 */
1328 void QWebElement::encloseWith(const QString &markup)
1329 {
1330     if (!m_element)
1331         return;
1332
1333     if (!m_element->parent())
1334         return;
1335
1336     if (!m_element->isHTMLElement())
1337         return;
1338
1339     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1340     RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1341
1342     if (!fragment || !fragment->firstChild())
1343         return;
1344
1345     RefPtr<Node> insertionPoint = findInsertionPoint(fragment->firstChild());
1346
1347     if (!insertionPoint)
1348         return;
1349
1350     // Keep reference to these two nodes before pulling out this element and
1351     // wrapping it in the fragment. The reason for doing it in this order is
1352     // that once the fragment has been added to the document it is empty, so
1353     // we no longer have access to the nodes it contained.
1354     Node* parentNode = m_element->parent();
1355     Node* siblingNode = m_element->nextSibling();
1356
1357     ExceptionCode exception = 0;
1358     insertionPoint->appendChild(m_element, exception);
1359
1360     if (!siblingNode)
1361         parentNode->appendChild(fragment, exception);
1362     else
1363         parentNode->insertBefore(fragment, siblingNode, exception);
1364 }
1365
1366 /*!
1367     Replaces this element with \a element.
1368
1369     This method will not replace the <html>, <head> or <body> elements.
1370
1371     \sa encloseWith()
1372 */
1373 void QWebElement::replace(const QWebElement &element)
1374 {
1375     if (!m_element || element.isNull())
1376         return;
1377
1378     appendOutside(element);
1379     takeFromDocument();
1380 }
1381
1382 /*!
1383     Replaces this element with the result of parsing \a markup.
1384
1385     This method will not replace the <html>, <head> or <body> elements.
1386
1387     \sa encloseWith()
1388 */
1389 void QWebElement::replace(const QString &markup)
1390 {
1391     if (!m_element)
1392         return;
1393
1394     appendOutside(markup);
1395     takeFromDocument();
1396 }
1397
1398 /*!
1399     \internal
1400     Walk \a node's parents until a valid QWebElement is found.
1401     For example, a WebCore::Text node is not a valid Html QWebElement, but its
1402     enclosing p tag is.
1403 */
1404 QWebElement QWebElement::enclosingElement(WebCore::Node* node)
1405 {
1406     QWebElement element(node);
1407
1408     while (element.isNull() && node) {
1409         node = node->parentNode();
1410         element = QWebElement(node);
1411     }
1412     return element;
1413 }
1414
1415 /*!
1416     \fn inline bool QWebElement::operator==(const QWebElement& o) const;
1417
1418     Returns true if this element points to the same underlying DOM object as
1419     \a o; otherwise returns false.
1420 */
1421
1422 /*!
1423     \fn inline bool QWebElement::operator!=(const QWebElement& o) const;
1424
1425     Returns true if this element points to a different underlying DOM object
1426     than \a o; otherwise returns false.
1427 */
1428
1429
1430 /*! 
1431   Render the element into \a painter .
1432 */
1433 void QWebElement::render(QPainter* painter)
1434 {
1435     WebCore::Element* e = m_element;
1436     Document* doc = e ? e->document() : 0;
1437     if (!doc)
1438         return;
1439
1440     Frame* frame = doc->frame();
1441     if (!frame || !frame->view() || !frame->contentRenderer())
1442         return;
1443
1444     FrameView* view = frame->view();
1445
1446     view->layoutIfNeededRecursive();
1447
1448     IntRect rect = e->getRect();
1449
1450     if (rect.size().isEmpty())
1451         return;
1452
1453     GraphicsContext context(painter);
1454
1455     context.save();
1456     context.translate(-rect.x(), -rect.y());
1457     view->setNodeToDraw(e);
1458     view->paintContents(&context, rect);
1459     view->setNodeToDraw(0);
1460     context.restore();
1461 }
1462
1463 class QWebElementCollectionPrivate : public QSharedData
1464 {
1465 public:
1466     static QWebElementCollectionPrivate* create(const PassRefPtr<Node> &context, const QString &query);
1467
1468     RefPtr<NodeList> m_result;
1469
1470 private:
1471     inline QWebElementCollectionPrivate() {}
1472 };
1473
1474 QWebElementCollectionPrivate* QWebElementCollectionPrivate::create(const PassRefPtr<Node> &context, const QString &query)
1475 {
1476     if (!context)
1477         return 0;
1478
1479     // Let WebKit do the hard work hehehe
1480     ExceptionCode exception = 0; // ###
1481     RefPtr<NodeList> nodes = context->querySelectorAll(query, exception);
1482     if (!nodes)
1483         return 0;
1484
1485     QWebElementCollectionPrivate* priv = new QWebElementCollectionPrivate;
1486     priv->m_result = nodes;
1487     return priv;
1488 }
1489
1490 /*!
1491     \class QWebElementCollection
1492     \since 4.6
1493     \brief The QWebElementCollection class represents a collection of web elements.
1494     \preliminary
1495
1496     Elements in a document can be selected using QWebElement::findAll() or using the
1497     QWebElement constructor. The collection is composed by choosing all elements in the
1498     document that match a specified CSS selector expression.
1499
1500     The number of selected elements is provided through the count() property. Individual
1501     elements can be retrieved by index using at().
1502
1503     It is also possible to iterate through all elements in the collection using Qt's foreach
1504     macro:
1505
1506     \code
1507         QWebElementCollection collection = document.findAll("p");
1508         foreach (QWebElement paraElement, collection) {
1509             ...
1510         }
1511     \endcode
1512 */
1513
1514 /*!
1515     Constructs an empty collection.
1516 */
1517 QWebElementCollection::QWebElementCollection()
1518 {
1519 }
1520
1521 /*!
1522     Constructs a copy of \a other.
1523 */
1524 QWebElementCollection::QWebElementCollection(const QWebElementCollection &other)
1525     : d(other.d)
1526 {
1527 }
1528
1529 /*!
1530     Constructs a collection of elements from the list of child elements of \a contextElement that
1531     match the specified CSS selector \a query.
1532 */
1533 QWebElementCollection::QWebElementCollection(const QWebElement &contextElement, const QString &query)
1534 {
1535     d = QExplicitlySharedDataPointer<QWebElementCollectionPrivate>(QWebElementCollectionPrivate::create(contextElement.m_element, query));
1536 }
1537
1538 /*!
1539     Assigns \a other to this collection and returns a reference to this collection.
1540 */
1541 QWebElementCollection &QWebElementCollection::operator=(const QWebElementCollection &other)
1542 {
1543     d = other.d;
1544     return *this;
1545 }
1546
1547 /*!
1548     Destroys the collection.
1549 */
1550 QWebElementCollection::~QWebElementCollection()
1551 {
1552 }
1553
1554 /*! \fn QWebElementCollection &QWebElementCollection::operator+=(const QWebElementCollection &other)
1555
1556     Appends the items of the \a other list to this list and returns a
1557     reference to this list.
1558
1559     \sa operator+(), append()
1560 */
1561
1562 /*!
1563     Returns a collection that contains all the elements of this collection followed
1564     by all the elements in the \a other collection. Duplicates may occur in the result.
1565
1566     \sa operator+=()
1567 */
1568 QWebElementCollection QWebElementCollection::operator+(const QWebElementCollection &other) const
1569 {
1570     QWebElementCollection n = *this; n.d.detach(); n += other; return n;
1571 }
1572
1573 /*!
1574     Extends the collection by appending all items of \a other.
1575
1576     The resulting collection may include duplicate elements.
1577
1578     \sa operator+=()
1579 */
1580 void QWebElementCollection::append(const QWebElementCollection &other)
1581 {
1582     if (!d) {
1583         *this = other;
1584         return;
1585     }
1586     if (!other.d)
1587         return;
1588     Vector<RefPtr<Node> > nodes;
1589     RefPtr<NodeList> results[] = { d->m_result, other.d->m_result };
1590     nodes.reserveInitialCapacity(results[0]->length() + results[1]->length());
1591
1592     for (int i = 0; i < 2; ++i) {
1593         int j = 0;
1594         Node* n = results[i]->item(j);
1595         while (n) {
1596             nodes.append(n);
1597             n = results[i]->item(++j);
1598         }
1599     }
1600
1601     d->m_result = StaticNodeList::adopt(nodes);
1602 }
1603
1604 /*!
1605     Returns the number of elements in the collection.
1606 */
1607 int QWebElementCollection::count() const
1608 {
1609     if (!d)
1610         return 0;
1611     return d->m_result->length();
1612 }
1613
1614 /*!
1615     Returns the element at index position \a i in the collection.
1616 */
1617 QWebElement QWebElementCollection::at(int i) const
1618 {
1619     if (!d)
1620         return QWebElement();
1621     Node* n = d->m_result->item(i);
1622     return QWebElement(static_cast<Element*>(n));
1623 }
1624
1625 /*!
1626     \fn const QWebElement QWebElementCollection::operator[](int position) const
1627
1628     Returns the element at the specified \a position in the collection.
1629 */
1630
1631 /*! \fn QWebElement QWebElementCollection::first() const
1632
1633     Returns the first element in the collection.
1634
1635     \sa last(), operator[](), at(), count()
1636 */
1637
1638 /*! \fn QWebElement QWebElementCollection::last() const
1639
1640     Returns the last element in the collection.
1641
1642     \sa first(), operator[](), at(), count()
1643 */
1644
1645 /*!
1646     Returns a QList object with the elements contained in this collection.
1647 */
1648 QList<QWebElement> QWebElementCollection::toList() const
1649 {
1650     if (!d)
1651         return QList<QWebElement>();
1652     QList<QWebElement> elements;
1653     int i = 0;
1654     Node* n = d->m_result->item(i);
1655     while (n) {
1656         if (n->isElementNode())
1657             elements.append(QWebElement(static_cast<Element*>(n)));
1658         n = d->m_result->item(++i);
1659     }
1660     return elements;
1661 }
1662
1663 /*!
1664     \fn QWebElementCollection::const_iterator QWebElementCollection::begin() const
1665
1666     Returns an STL-style iterator pointing to the first element in the collection.
1667
1668     \sa end()
1669 */
1670
1671 /*!
1672     \fn QWebElementCollection::const_iterator QWebElementCollection::end() const
1673
1674     Returns an STL-style iterator pointing to the imaginary element after the
1675     last element in the list.
1676
1677     \sa begin()
1678 */
1679
1680 /*!
1681     \class QWebElementCollection::const_iterator
1682     \since 4.6
1683     \brief The QWebElementCollection::const_iterator class provides an STL-style const iterator for QWebElementCollection.
1684
1685     QWebElementCollection provides STL style const iterators for fast low-level access to the elements.
1686
1687     QWebElementCollection::const_iterator allows you to iterate over a QWebElementCollection.
1688 */
1689
1690 /*!
1691     \fn QWebElementCollection::const_iterator::const_iterator(const const_iterator &other)
1692
1693     Constructs a copy of \a other.
1694 */
1695
1696 /*!
1697     \fn QWebElementCollection::const_iterator::const_iterator(const QWebElementCollection *collection, int index)
1698     \internal
1699 */
1700
1701 /*!
1702     \fn const QWebElement QWebElementCollection::const_iterator::operator*() const
1703
1704     Returns the current element.
1705 */
1706
1707 /*!
1708     \fn bool QWebElementCollection::const_iterator::operator==(const const_iterator &other) const
1709
1710     Returns true if \a other points to the same item as this iterator;
1711     otherwise returns false.
1712
1713     \sa operator!=()
1714 */
1715
1716 /*!
1717     \fn bool QWebElementCollection::const_iterator::operator!=(const const_iterator &other) const
1718
1719     Returns true if \a other points to a different element than this;
1720     iterator; otherwise returns false.
1721
1722     \sa operator==()
1723 */
1724
1725 /*!
1726     \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator++()
1727
1728     The prefix ++ operator (\c{++it}) advances the iterator to the next element in the collection
1729     and returns an iterator to the new current element.
1730
1731     Calling this function on QWebElementCollection::end() leads to undefined results.
1732
1733     \sa operator--()
1734 */
1735
1736 /*!
1737     \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator++(int)
1738
1739     \overload
1740
1741     The postfix ++ operator (\c{it++}) advances the iterator to the next element in the collection
1742     and returns an iterator to the previously current element.
1743
1744     Calling this function on QWebElementCollection::end() leads to undefined results.
1745 */
1746
1747 /*!
1748     \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator--()
1749
1750     The prefix -- operator (\c{--it}) makes the preceding element current and returns an
1751     iterator to the new current element.
1752
1753     Calling this function on QWebElementCollection::begin() leads to undefined results.
1754
1755     \sa operator++()
1756 */
1757
1758 /*!
1759     \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator--(int)
1760
1761     \overload
1762
1763     The postfix -- operator (\c{it--}) makes the preceding element current and returns
1764     an iterator to the previously current element.
1765 */
1766
1767 /*!
1768     \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator+=(int j)
1769
1770     Advances the iterator by \a j elements. If \a j is negative, the iterator goes backward.
1771
1772     \sa operator-=(), operator+()
1773 */
1774
1775 /*!
1776     \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator-=(int j)
1777
1778     Makes the iterator go back by \a j elements. If \a j is negative, the iterator goes forward.
1779
1780     \sa operator+=(), operator-()
1781 */
1782
1783 /*!
1784     \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator+(int j) const
1785
1786     Returns an iterator to the element at \a j positions forward from this iterator. If \a j
1787     is negative, the iterator goes backward.
1788
1789     \sa operator-(), operator+=()
1790 */
1791
1792 /*!
1793     \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator-(int j) const
1794
1795     Returns an iterator to the element at \a j positiosn backward from this iterator.
1796     If \a j is negative, the iterator goes forward.
1797
1798     \sa operator+(), operator-=()
1799 */
1800
1801 /*!
1802     \fn int QWebElementCollection::const_iterator::operator-(const_iterator other) const
1803
1804     Returns the number of elements between the item point to by \a other
1805     and the element pointed to by this iterator.
1806 */
1807
1808 /*!
1809     \fn bool QWebElementCollection::const_iterator::operator<(const const_iterator &other) const
1810
1811     Returns true if the element pointed to by this iterator is less than the element pointed to
1812     by the \a other iterator.
1813 */
1814
1815 /*!
1816     \fn bool QWebElementCollection::const_iterator::operator<=(const const_iterator &other) const
1817
1818     Returns true if the element pointed to by this iterator is less than or equal to the
1819     element pointed to by the \a other iterator.
1820 */
1821
1822 /*!
1823     \fn bool QWebElementCollection::const_iterator::operator>(const const_iterator &other) const
1824
1825     Returns true if the element pointed to by this iterator is greater than the element pointed to
1826     by the \a other iterator.
1827 */
1828
1829 /*!
1830     \fn bool QWebElementCollection::const_iterator::operator>=(const const_iterator &other) const
1831
1832     Returns true if the element pointed to by this iterator is greater than or equal to the
1833     element pointed to by the \a other iterator.
1834 */
1835
1836 /*!
1837     \fn QWebElementCollection::iterator QWebElementCollection::begin()
1838
1839     Returns an STL-style iterator pointing to the first element in the collection.
1840
1841     \sa end()
1842 */
1843
1844 /*!
1845     \fn QWebElementCollection::iterator QWebElementCollection::end()
1846
1847     Returns an STL-style iterator pointing to the imaginary element after the
1848     last element in the list.
1849
1850     \sa begin()
1851 */
1852
1853 /*!
1854     \fn QWebElementCollection::const_iterator QWebElementCollection::constBegin() const
1855
1856     Returns an STL-style iterator pointing to the first element in the collection.
1857
1858     \sa end()
1859 */
1860
1861 /*!
1862     \fn QWebElementCollection::const_iterator QWebElementCollection::constEnd() const
1863
1864     Returns an STL-style iterator pointing to the imaginary element after the
1865     last element in the list.
1866
1867     \sa begin()
1868 */
1869
1870 /*!
1871     \class QWebElementCollection::iterator
1872     \since 4.6
1873     \brief The QWebElementCollection::iterator class provides an STL-style iterator for QWebElementCollection.
1874
1875     QWebElementCollection provides STL style iterators for fast low-level access to the elements.
1876
1877     QWebElementCollection::iterator allows you to iterate over a QWebElementCollection.
1878 */
1879
1880 /*!
1881     \fn QWebElementCollection::iterator::iterator(const iterator &other)
1882
1883     Constructs a copy of \a other.
1884 */
1885
1886 /*!
1887     \fn QWebElementCollection::iterator::iterator(const QWebElementCollection *collection, int index)
1888     \internal
1889 */
1890
1891 /*!
1892     \fn const QWebElement QWebElementCollection::iterator::operator*() const
1893
1894     Returns the current element.
1895 */
1896
1897 /*!
1898     \fn bool QWebElementCollection::iterator::operator==(const iterator &other) const
1899
1900     Returns true if \a other points to the same item as this iterator;
1901     otherwise returns false.
1902
1903     \sa operator!=()
1904 */
1905
1906 /*!
1907     \fn bool QWebElementCollection::iterator::operator!=(const iterator &other) const
1908
1909     Returns true if \a other points to a different element than this;
1910     iterator; otherwise returns false.
1911
1912     \sa operator==()
1913 */
1914
1915 /*!
1916     \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator++()
1917
1918     The prefix ++ operator (\c{++it}) advances the iterator to the next element in the collection
1919     and returns an iterator to the new current element.
1920
1921     Calling this function on QWebElementCollection::end() leads to undefined results.
1922
1923     \sa operator--()
1924 */
1925
1926 /*!
1927     \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator++(int)
1928
1929     \overload
1930
1931     The postfix ++ operator (\c{it++}) advances the iterator to the next element in the collection
1932     and returns an iterator to the previously current element.
1933
1934     Calling this function on QWebElementCollection::end() leads to undefined results.
1935 */
1936
1937 /*!
1938     \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator--()
1939
1940     The prefix -- operator (\c{--it}) makes the preceding element current and returns an
1941     iterator to the new current element.
1942
1943     Calling this function on QWebElementCollection::begin() leads to undefined results.
1944
1945     \sa operator++()
1946 */
1947
1948 /*!
1949     \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator--(int)
1950
1951     \overload
1952
1953     The postfix -- operator (\c{it--}) makes the preceding element current and returns
1954     an iterator to the previously current element.
1955 */
1956
1957 /*!
1958     \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator+=(int j)
1959
1960     Advances the iterator by \a j elements. If \a j is negative, the iterator goes backward.
1961
1962     \sa operator-=(), operator+()
1963 */
1964
1965 /*!
1966     \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator-=(int j)
1967
1968     Makes the iterator go back by \a j elements. If \a j is negative, the iterator goes forward.
1969
1970     \sa operator+=(), operator-()
1971 */
1972
1973 /*!
1974     \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator+(int j) const
1975
1976     Returns an iterator to the element at \a j positions forward from this iterator. If \a j
1977     is negative, the iterator goes backward.
1978
1979     \sa operator-(), operator+=()
1980 */
1981
1982 /*!
1983     \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator-(int j) const
1984
1985     Returns an iterator to the element at \a j positiosn backward from this iterator.
1986     If \a j is negative, the iterator goes forward.
1987
1988     \sa operator+(), operator-=()
1989 */
1990
1991 /*!
1992     \fn int QWebElementCollection::iterator::operator-(iterator other) const
1993
1994     Returns the number of elements between the item point to by \a other
1995     and the element pointed to by this iterator.
1996 */
1997
1998 /*!
1999     \fn bool QWebElementCollection::iterator::operator<(const iterator &other) const
2000
2001     Returns true if the element pointed to by this iterator is less than the element pointed to
2002     by the \a other iterator.
2003 */
2004
2005 /*!
2006     \fn bool QWebElementCollection::iterator::operator<=(const iterator &other) const
2007
2008     Returns true if the element pointed to by this iterator is less than or equal to the
2009     element pointed to by the \a other iterator.
2010 */
2011
2012 /*!
2013     \fn bool QWebElementCollection::iterator::operator>(const iterator &other) const
2014
2015     Returns true if the element pointed to by this iterator is greater than the element pointed to
2016     by the \a other iterator.
2017 */
2018
2019 /*!
2020     \fn bool QWebElementCollection::iterator::operator>=(const iterator &other) const
2021
2022     Returns true if the element pointed to by this iterator is greater than or equal to the
2023     element pointed to by the \a other iterator.
2024 */