Home | History | Annotate | Download | only in Api
      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 
     51 using namespace WebCore;
     52 
     53 class QWebElementPrivate {
     54 public:
     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 */
    114 QWebElement::QWebElement()
    115     : d(0)
    116     , m_element(0)
    117 {
    118 }
    119 
    120 /*!
    121     \internal
    122 */
    123 QWebElement::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 */
    134 QWebElement::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 */
    147 QWebElement::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 */
    158 QWebElement &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 */
    175 QWebElement::~QWebElement()
    176 {
    177     delete d;
    178     if (m_element)
    179         m_element->deref();
    180 }
    181 
    182 bool QWebElement::operator==(const QWebElement& o) const
    183 {
    184     return m_element == o.m_element;
    185 }
    186 
    187 bool 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 */
    195 bool 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 */
    211 QWebElementCollection 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 */
    226 QWebElement 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 */
    241 void 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 */
    257 QString 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 */
    273 void 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 */
    291 QString 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 */
    308 void 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 */
    325 QString 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 */
    339 void 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 */
    354 void 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 */
    368 QString 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 */
    384 QString 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 */
    400 bool 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 */
    413 bool 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 */
    425 void 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 */
    439 void 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 */
    453 bool 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 */
    465 QStringList 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 */
    489 bool 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 */
    503 void 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 */
    516 QRect 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 */
    528 QString 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 */
    539 QString 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 */
    550 QString 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 */
    561 QString 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 */
    572 QWebElement 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 */
    584 QWebElement 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 */
    602 QWebElement 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 */
    620 QWebElement 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 */
    638 QWebElement 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 */
    654 QWebElement 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 */
    668 QWebFrame *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 
    683 static 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 */
    715 QVariant 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 
    775 QString 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 */
    844 void 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 */
    861 QStringList 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 */
    893 bool 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 */
    902 void 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 */
    915 void 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 */
    929 void 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 */
    952 void 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 */
    968 void 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 */
    994 void 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 */
   1014 void 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 */
   1044 void 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 */
   1063 void 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 */
   1091 void 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 */
   1113 void 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 */
   1141 QWebElement 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 */
   1157 QWebElement &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 */
   1173 void 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 */
   1189 void QWebElement::removeAllChildren()
   1190 {
   1191     if (!m_element)
   1192         return;
   1193 
   1194     m_element->removeAllChildren();
   1195 }
   1196 
   1197 static 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 */
   1227 void 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 */
   1258 void 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 */
   1301 void 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 */
   1333 void 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 */
   1378 void 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 */
   1394 void 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 */
   1409 QWebElement 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 */
   1438 void 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 
   1468 class QWebElementCollectionPrivate : public QSharedData
   1469 {
   1470 public:
   1471     static QWebElementCollectionPrivate* create(const PassRefPtr<Node> &context, const QString &query);
   1472 
   1473     RefPtr<NodeList> m_result;
   1474 
   1475 private:
   1476     inline QWebElementCollectionPrivate() {}
   1477 };
   1478 
   1479 QWebElementCollectionPrivate* 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 */
   1522 QWebElementCollection::QWebElementCollection()
   1523 {
   1524 }
   1525 
   1526 /*!
   1527     Constructs a copy of \a other.
   1528 */
   1529 QWebElementCollection::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 */
   1538 QWebElementCollection::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 */
   1546 QWebElementCollection &QWebElementCollection::operator=(const QWebElementCollection &other)
   1547 {
   1548     d = other.d;
   1549     return *this;
   1550 }
   1551 
   1552 /*!
   1553     Destroys the collection.
   1554 */
   1555 QWebElementCollection::~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 */
   1573 QWebElementCollection 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 */
   1585 void 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 */
   1612 int 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 */
   1622 QWebElement 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 */
   1653 QList<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