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