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