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 */
QWebElement()114 QWebElement::QWebElement()
115 : d(0)
116 , m_element(0)
117 {
118 }
119
120 /*!
121 \internal
122 */
QWebElement(WebCore::Element * domElement)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 */
QWebElement(WebCore::Node * node)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 */
QWebElement(const QWebElement & other)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 */
operator =(const QWebElement & other)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 */
~QWebElement()175 QWebElement::~QWebElement()
176 {
177 delete d;
178 if (m_element)
179 m_element->deref();
180 }
181
operator ==(const QWebElement & o) const182 bool QWebElement::operator==(const QWebElement& o) const
183 {
184 return m_element == o.m_element;
185 }
186
operator !=(const QWebElement & o) const187 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 */
isNull() const195 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 */
findAll(const QString & selectorQuery) const211 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 */
findFirst(const QString & selectorQuery) const226 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 */
setPlainText(const QString & text)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 */
toPlainText() const257 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 */
setOuterXml(const QString & markup)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 */
toOuterXml() const291 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 */
setInnerXml(const QString & markup)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 */
toInnerXml() const325 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 */
setAttribute(const QString & name,const QString & value)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 */
setAttributeNS(const QString & namespaceUri,const QString & name,const QString & value)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 */
attribute(const QString & name,const QString & defaultValue) const368 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 */
attributeNS(const QString & namespaceUri,const QString & name,const QString & defaultValue) const384 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 */
hasAttribute(const QString & name) const400 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 */
hasAttributeNS(const QString & namespaceUri,const QString & name) const413 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 */
removeAttribute(const QString & name)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 */
removeAttributeNS(const QString & namespaceUri,const QString & name)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 */
hasAttributes() const453 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 */
attributeNames(const QString & namespaceUri) const465 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 */
hasFocus() const489 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 */
setFocus()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 */
geometry() const516 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 */
tagName() const528 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 */
prefix() const539 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 */
localName() const550 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 */
namespaceUri() const561 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 */
parent() const572 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 */
firstChild() const584 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 */
lastChild() const602 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 */
nextSibling() const620 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 */
previousSibling() const638 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 */
document() const654 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 */
webFrame() const668 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
setupScriptContext(WebCore::Element * element,JSC::JSValue & thisValue,ScriptState * & state,ScriptController * & scriptController)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 */
evaluateJavaScript(const QString & scriptSource)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
styleProperty(const QString & name,StyleResolveStrategy strategy) const775 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 */
setStyleProperty(const QString & name,const QString & value)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 */
classes() const861 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 */
hasClass(const QString & name) const893 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 */
addClass(const QString & name)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 */
removeClass(const QString & name)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 */
toggleClass(const QString & name)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 */
appendInside(const QWebElement & element)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 */
appendInside(const QString & markup)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 */
prependInside(const QWebElement & element)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 */
prependInside(const QString & markup)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 */
prependOutside(const QWebElement & element)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 */
prependOutside(const QString & markup)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 */
appendOutside(const QWebElement & element)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 */
appendOutside(const QString & markup)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 */
clone() const1141 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 */
takeFromDocument()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 */
removeFromDocument()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 */
removeAllChildren()1189 void QWebElement::removeAllChildren()
1190 {
1191 if (!m_element)
1192 return;
1193
1194 m_element->removeAllChildren();
1195 }
1196
findInsertionPoint(PassRefPtr<Node> root)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 */
encloseContentsWith(const QWebElement & element)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 */
encloseContentsWith(const QString & markup)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 */
encloseWith(const QWebElement & element)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 */
encloseWith(const QString & markup)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 */
replace(const QWebElement & element)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 */
replace(const QString & markup)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 */
enclosingElement(WebCore::Node * node)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 */
render(QPainter * painter)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:
QWebElementCollectionPrivate()1476 inline QWebElementCollectionPrivate() {}
1477 };
1478
create(const PassRefPtr<Node> & context,const QString & query)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 */
QWebElementCollection()1522 QWebElementCollection::QWebElementCollection()
1523 {
1524 }
1525
1526 /*!
1527 Constructs a copy of \a other.
1528 */
QWebElementCollection(const QWebElementCollection & other)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 */
QWebElementCollection(const QWebElement & contextElement,const QString & query)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 */
operator =(const QWebElementCollection & other)1546 QWebElementCollection &QWebElementCollection::operator=(const QWebElementCollection &other)
1547 {
1548 d = other.d;
1549 return *this;
1550 }
1551
1552 /*!
1553 Destroys the collection.
1554 */
~QWebElementCollection()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 */
operator +(const QWebElementCollection & other) const1573 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 */
append(const QWebElementCollection & other)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 */
count() const1612 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 */
at(int i) const1622 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 */
toList() const1653 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