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