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