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