1/*
2    Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
3    Copyright (C) 2008 Holger Hans Peter Freyther
4    Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public License
17    along with this library; see the file COPYING.LIB.  If not, write to
18    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19    Boston, MA 02110-1301, USA.
20*/
21
22#include "config.h"
23#include "qwebview.h"
24
25#include "Page.h"
26#include "QWebPageClient.h"
27#include "Settings.h"
28#include "qwebframe.h"
29#include "qwebpage_p.h"
30#include "qbitmap.h"
31#include "qevent.h"
32#include "qpainter.h"
33#include "qprinter.h"
34#include "qdir.h"
35#include "qfile.h"
36
37class QWebViewPrivate {
38public:
39    QWebViewPrivate(QWebView *view)
40        : view(view)
41        , page(0)
42        , renderHints(QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform)
43    {
44        Q_ASSERT(view);
45    }
46
47    virtual ~QWebViewPrivate();
48
49    void _q_pageDestroyed();
50    void detachCurrentPage();
51
52    QWebView *view;
53    QWebPage *page;
54
55    QPainter::RenderHints renderHints;
56};
57
58QWebViewPrivate::~QWebViewPrivate()
59{
60    detachCurrentPage();
61}
62
63void QWebViewPrivate::_q_pageDestroyed()
64{
65    page = 0;
66    view->setPage(0);
67}
68
69#ifdef Q_WS_MAEMO_5
70#include "qabstractkineticscroller.h"
71#include "qapplication.h"
72
73// QCoreApplication::sendSpontaneousEvent() is private, hence this friend wrapper
74bool qt_sendSpontaneousEvent(QObject* receiver, QEvent* ev)
75{
76    return QCoreApplication::sendSpontaneousEvent(receiver, ev);
77}
78
79class QWebViewKineticScroller : public QObject, public QAbstractKineticScroller {
80public:
81    QWebViewKineticScroller()
82        : QObject()
83        , QAbstractKineticScroller()
84        , m_view(0)
85        , m_ignoreEvents(false)
86    {
87    }
88
89    void setWidget(QWebView* widget)
90    {
91        if (m_view) {
92            m_view->removeEventFilter(this);
93            QWebFrame* frame = m_view->page()->mainFrame();
94            frame->setScrollBarPolicy(Qt::Vertical, m_oldVerticalScrollBarPolicy);
95            frame->setScrollBarPolicy(Qt::Horizontal, m_oldHorizontalScrollBarPolicy);
96        }
97
98        m_view = widget;
99        setParent(m_view);
100        if (m_view) {
101            QWebFrame* frame = m_view->page()->mainFrame();
102            m_oldHorizontalScrollBarPolicy = frame->scrollBarPolicy(Qt::Horizontal);
103            m_oldVerticalScrollBarPolicy = frame->scrollBarPolicy(Qt::Vertical);
104            frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
105            frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
106            m_view->installEventFilter(this);
107        }
108    }
109
110protected:
111    bool eventFilter(QObject* o, QEvent* ev)
112    {
113        if (!o || m_view != o || m_ignoreEvents || !m_view->isEnabled())
114            return QObject::eventFilter(o, ev);
115
116        bool res = false;
117
118        switch (ev->type()) {
119        case QEvent::MouseButtonPress: {
120            // remember the frame where the button was pressed
121            QWebFrame* hitFrame = scrollingFrameAt(static_cast<QMouseEvent*>(ev)->pos());
122            if (hitFrame)
123                m_frame = hitFrame;
124            // fall through
125        }
126        case QEvent::MouseMove:
127        case QEvent::MouseButtonRelease:
128        case QEvent::MouseButtonDblClick:
129            res = handleMouseEvent(static_cast<QMouseEvent*>(ev));
130            break;
131        default:
132            break;
133        }
134        return res ? true : QObject::eventFilter(o, ev);
135    }
136
137    void cancelLeftMouseButtonPress(const QPoint& /* globalPressPos */)
138    {
139        QMouseEvent cmem(QEvent::MouseMove, QPoint(-INT_MAX, -INT_MAX), Qt::LeftButton, QApplication::mouseButtons() | Qt::LeftButton, QApplication::keyboardModifiers());
140        sendEvent(m_view, &cmem);
141        QMouseEvent cmer(QEvent::MouseButtonRelease, QPoint(-INT_MAX, -INT_MAX), Qt::LeftButton, QApplication::mouseButtons() & ~Qt::LeftButton, QApplication::keyboardModifiers());
142        sendEvent(m_view, &cmer);
143    }
144
145    QWebFrame* currentFrame() const
146    {
147        if (m_frame)
148            return m_frame;
149
150        if (m_view)
151            return m_view->page()->mainFrame();
152
153        return 0;
154    }
155
156    // Returns the innermost frame at the given position that can scroll.
157    QWebFrame* scrollingFrameAt(const QPoint& pos) const
158    {
159        QWebFrame* hitFrame = 0;
160        if (m_view) {
161            QWebFrame* frame = m_view->page()->mainFrame();
162            hitFrame = frame->hitTestContent(pos).frame();
163            QSize range = hitFrame->contentsSize() - hitFrame->geometry().size();
164
165            while (hitFrame && range.width() <= 1 && range.height() <= 1)
166                hitFrame = hitFrame->parentFrame();
167
168            return hitFrame;
169        }
170    }
171
172    QPoint maximumScrollPosition() const
173    {
174        QWebFrame* frame = currentFrame();
175        QSize s = frame ? frame->contentsSize() - frame->geometry().size() : QSize(0, 0);
176        return QPoint(qMax(0, s.width()), qMax(0, s.height()));
177    }
178
179    QPoint scrollPosition() const
180    {
181        QWebFrame* frame = currentFrame();
182        return frame ? frame->scrollPosition() : QPoint();
183    }
184
185    QSize viewportSize() const
186    {
187        return m_view ? m_view->page()->viewportSize() : QSize();
188    }
189
190    void setScrollPosition(const QPoint& point, const QPoint& /* overShootDelta */)
191    {
192        QWebFrame* frame = currentFrame();
193        if (frame)
194            frame->setScrollPosition(point);
195    }
196
197    void sendEvent(QWidget* w, QEvent* ev)
198    {
199        m_ignoreEvents = true;
200        qt_sendSpontaneousEvent(w, ev);
201        m_ignoreEvents = false;
202    }
203
204    QWebView* m_view;
205    bool m_ignoreEvents;
206    QPointer<QWebFrame> m_frame;
207    Qt::ScrollBarPolicy m_oldVerticalScrollBarPolicy;
208    Qt::ScrollBarPolicy m_oldHorizontalScrollBarPolicy;
209};
210
211#endif // Q_WS_MAEMO_5
212
213
214/*!
215    \class QWebView
216    \since 4.4
217    \brief The QWebView class provides a widget that is used to view and edit
218    web documents.
219    \ingroup advanced
220
221    \inmodule QtWebKit
222
223    QWebView is the main widget component of the QtWebKit web browsing module.
224    It can be used in various applications to display web content live from the
225    Internet.
226
227    The image below shows QWebView previewed in \QD with a Nokia website.
228
229    \image qwebview-url.png
230
231    A web site can be loaded onto QWebView with the load() function. Like all
232    Qt widgets, the show() function must be invoked in order to display
233    QWebView. The snippet below illustrates this:
234
235    \snippet webkitsnippets/simple/main.cpp Using QWebView
236
237    Alternatively, setUrl() can also be used to load a web site. If you have
238    the HTML content readily available, you can use setHtml() instead.
239
240    The loadStarted() signal is emitted when the view begins loading. The
241    loadProgress() signal, on the other hand, is emitted whenever an element of
242    the web view completes loading, such as an embedded image, a script, etc.
243    Finally, the loadFinished() signal is emitted when the view has loaded
244    completely. It's argument - either \c true or \c false - indicates
245    load success or failure.
246
247    The page() function returns a pointer to the web page object. See
248    \l{Elements of QWebView} for an explanation of how the web page
249    is related to the view. To modify your web view's settings, you can access
250    the QWebSettings object with the settings() function. With QWebSettings,
251    you can change the default fonts, enable or disable features such as
252    JavaScript and plugins.
253
254    The title of an HTML document can be accessed with the title() property.
255    Additionally, a web site may also specify an icon, which can be accessed
256    using the icon() property. If the title or the icon changes, the corresponding
257    titleChanged() and iconChanged() signals will be emitted. The
258    textSizeMultiplier() property can be used to change the overall size of
259    the text displayed in the web view.
260
261    If you require a custom context menu, you can implement it by reimplementing
262    \l{QWidget::}{contextMenuEvent()} and populating your QMenu with the actions
263    obtained from pageAction(). More functionality such as reloading the view,
264    copying selected text to the clipboard, or pasting into the view, is also
265    encapsulated within the QAction objects returned by pageAction(). These
266    actions can be programmatically triggered using triggerPageAction().
267    Alternatively, the actions can be added to a toolbar or a menu directly.
268    QWebView maintains the state of the returned actions but allows
269    modification of action properties such as \l{QAction::}{text} or
270    \l{QAction::}{icon}.
271
272    A QWebView can be printed onto a QPrinter using the print() function.
273    This function is marked as a slot and can be conveniently connected to
274    \l{QPrintPreviewDialog}'s \l{QPrintPreviewDialog::}{paintRequested()}
275    signal.
276
277    If you want to provide support for web sites that allow the user to open
278    new windows, such as pop-up windows, you can subclass QWebView and
279    reimplement the createWindow() function.
280
281    \section1 Elements of QWebView
282
283    QWebView consists of other objects such as QWebFrame and QWebPage. The
284    flowchart below shows these elements are related.
285
286    \image qwebview-diagram.png
287
288    \note It is possible to use QWebPage and QWebFrame, without using QWebView,
289    if you do not require QWidget attributes. Nevertheless, QtWebKit depends
290    on QtGui, so you should use a QApplication instead of QCoreApplication.
291
292    \sa {Previewer Example}, {Web Browser}, {Form Extractor Example},
293    {Google Chat Example}, {Fancy Browser Example}
294*/
295
296/*!
297    Constructs an empty QWebView with parent \a parent.
298
299    \sa load()
300*/
301QWebView::QWebView(QWidget *parent)
302    : QWidget(parent)
303{
304    d = new QWebViewPrivate(this);
305
306#if !defined(Q_WS_QWS) && !defined(Q_OS_SYMBIAN)
307    setAttribute(Qt::WA_InputMethodEnabled);
308#endif
309
310    setAttribute(Qt::WA_AcceptTouchEvents);
311#if defined(Q_WS_MAEMO_5)
312    QAbstractKineticScroller* scroller = new QWebViewKineticScroller();
313    static_cast<QWebViewKineticScroller*>(scroller)->setWidget(this);
314    setProperty("kineticScroller", QVariant::fromValue(scroller));
315#endif
316    setAcceptDrops(true);
317
318    setMouseTracking(true);
319    setFocusPolicy(Qt::WheelFocus);
320}
321
322/*!
323    Destroys the web view.
324*/
325QWebView::~QWebView()
326{
327    delete d;
328}
329
330/*!
331    Returns a pointer to the underlying web page.
332
333    \sa setPage()
334*/
335QWebPage *QWebView::page() const
336{
337    if (!d->page) {
338        QWebView *that = const_cast<QWebView *>(this);
339        that->setPage(new QWebPage(that));
340    }
341    return d->page;
342}
343
344void QWebViewPrivate::detachCurrentPage()
345{
346    if (!page)
347        return;
348
349    page->d->view.clear();
350
351    // if the page client is the special client constructed for
352    // delegating the responsibilities to a QWidget, we need
353    // to destroy it.
354
355    if (page->d->client && page->d->client->isQWidgetClient())
356        page->d->client.clear();
357
358    page->d->client.release();
359
360    // if the page was created by us, we own it and need to
361    // destroy it as well.
362
363    if (page->parent() == view)
364        delete page;
365    else
366        page->disconnect(view);
367
368    page = 0;
369}
370
371/*!
372    Makes \a page the new web page of the web view.
373
374    The parent QObject of the provided page remains the owner
375    of the object. If the current document is a child of the web
376    view, it will be deleted.
377
378    \sa page()
379*/
380void QWebView::setPage(QWebPage* page)
381{
382    if (d->page == page)
383        return;
384
385    d->detachCurrentPage();
386    d->page = page;
387
388    if (d->page) {
389        d->page->setView(this);
390        d->page->setPalette(palette());
391        // #### connect signals
392        QWebFrame *mainFrame = d->page->mainFrame();
393        connect(mainFrame, SIGNAL(titleChanged(QString)),
394                this, SIGNAL(titleChanged(QString)));
395        connect(mainFrame, SIGNAL(iconChanged()),
396                this, SIGNAL(iconChanged()));
397        connect(mainFrame, SIGNAL(urlChanged(QUrl)),
398                this, SIGNAL(urlChanged(QUrl)));
399
400        connect(d->page, SIGNAL(loadStarted()),
401                this, SIGNAL(loadStarted()));
402        connect(d->page, SIGNAL(loadProgress(int)),
403                this, SIGNAL(loadProgress(int)));
404        connect(d->page, SIGNAL(loadFinished(bool)),
405                this, SIGNAL(loadFinished(bool)));
406        connect(d->page, SIGNAL(statusBarMessage(QString)),
407                this, SIGNAL(statusBarMessage(QString)));
408        connect(d->page, SIGNAL(linkClicked(QUrl)),
409                this, SIGNAL(linkClicked(QUrl)));
410        connect(d->page, SIGNAL(selectionChanged()),
411                this, SIGNAL(selectionChanged()));
412
413        connect(d->page, SIGNAL(microFocusChanged()),
414                this, SLOT(updateMicroFocus()));
415        connect(d->page, SIGNAL(destroyed()),
416                this, SLOT(_q_pageDestroyed()));
417    }
418    setAttribute(Qt::WA_OpaquePaintEvent, d->page);
419    update();
420}
421
422/*!
423    Loads the specified \a url and displays it.
424
425    \note The view remains the same until enough data has arrived to display the new \a url.
426
427    \sa setUrl(), url(), urlChanged(), QUrl::fromUserInput()
428*/
429void QWebView::load(const QUrl &url)
430{
431    page()->mainFrame()->load(url);
432}
433
434/*!
435    \fn void QWebView::load(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, const QByteArray &body)
436
437    Loads a network request, \a request, using the method specified in \a operation.
438
439    \a body is optional and is only used for POST operations.
440
441    \note The view remains the same until enough data has arrived to display the new url.
442
443    \sa url(), urlChanged()
444*/
445
446void QWebView::load(const QNetworkRequest &request,
447                    QNetworkAccessManager::Operation operation,
448                    const QByteArray &body)
449{
450    page()->mainFrame()->load(request, operation, body);
451}
452
453/*!
454    Sets the content of the web view to the specified \a html.
455
456    External objects such as stylesheets or images referenced in the HTML
457    document are located relative to \a baseUrl.
458
459    The \a html is loaded immediately; external objects are loaded asynchronously.
460
461    When using this method, WebKit assumes that external resources such as
462    JavaScript programs or style sheets are encoded in UTF-8 unless otherwise
463    specified. For example, the encoding of an external script can be specified
464    through the charset attribute of the HTML script tag. Alternatively, the
465    encoding can also be specified by the web server.
466
467    This is a convenience function equivalent to setContent(html, "text/html", baseUrl).
468
469    \warning This function works only for HTML, for other mime types (i.e. XHTML, SVG)
470    setContent() should be used instead.
471
472    \sa load(), setContent(), QWebFrame::toHtml(), QWebFrame::setContent()
473*/
474void QWebView::setHtml(const QString &html, const QUrl &baseUrl)
475{
476    page()->mainFrame()->setHtml(html, baseUrl);
477}
478
479/*!
480    Sets the content of the web view to the specified content \a data. If the \a mimeType argument
481    is empty it is currently assumed that the content is HTML but in future versions we may introduce
482    auto-detection.
483
484    External objects referenced in the content are located relative to \a baseUrl.
485
486    The \a data is loaded immediately; external objects are loaded asynchronously.
487
488    \sa load(), setHtml(), QWebFrame::toHtml()
489*/
490void QWebView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
491{
492    page()->mainFrame()->setContent(data, mimeType, baseUrl);
493}
494
495/*!
496    Returns a pointer to the view's history of navigated web pages.
497
498    It is equivalent to
499
500    \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 0
501*/
502QWebHistory *QWebView::history() const
503{
504    return page()->history();
505}
506
507/*!
508    Returns a pointer to the view/page specific settings object.
509
510    It is equivalent to
511
512    \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 1
513
514    \sa QWebSettings::globalSettings()
515*/
516QWebSettings *QWebView::settings() const
517{
518    return page()->settings();
519}
520
521/*!
522    \property QWebView::title
523    \brief the title of the web page currently viewed
524
525    By default, this property contains an empty string.
526
527    \sa titleChanged()
528*/
529QString QWebView::title() const
530{
531    if (d->page)
532        return d->page->mainFrame()->title();
533    return QString();
534}
535
536/*!
537    \property QWebView::url
538    \brief the url of the web page currently viewed
539
540    Setting this property clears the view and loads the URL.
541
542    By default, this property contains an empty, invalid URL.
543
544    \sa load(), urlChanged()
545*/
546
547void QWebView::setUrl(const QUrl &url)
548{
549    page()->mainFrame()->setUrl(url);
550}
551
552QUrl QWebView::url() const
553{
554    if (d->page)
555        return d->page->mainFrame()->url();
556    return QUrl();
557}
558
559/*!
560    \property QWebView::icon
561    \brief the icon associated with the web page currently viewed
562
563    By default, this property contains a null icon.
564
565    \sa iconChanged(), QWebSettings::iconForUrl()
566*/
567QIcon QWebView::icon() const
568{
569    if (d->page)
570        return d->page->mainFrame()->icon();
571    return QIcon();
572}
573
574/*!
575    \property QWebView::hasSelection
576    \brief whether this page contains selected content or not.
577
578    By default, this property is false.
579
580    \sa selectionChanged()
581*/
582bool QWebView::hasSelection() const
583{
584    if (d->page)
585        return d->page->hasSelection();
586    return false;
587}
588
589/*!
590    \property QWebView::selectedText
591    \brief the text currently selected
592
593    By default, this property contains an empty string.
594
595    \sa findText(), selectionChanged(), selectedHtml()
596*/
597QString QWebView::selectedText() const
598{
599    if (d->page)
600        return d->page->selectedText();
601    return QString();
602}
603
604/*!
605    \since 4.8
606    \property QWebView::selectedHtml
607    \brief the HTML currently selected
608
609    By default, this property contains an empty string.
610
611    \sa findText(), selectionChanged(), selectedText()
612*/
613QString QWebView::selectedHtml() const
614{
615    if (d->page)
616        return d->page->selectedHtml();
617    return QString();
618}
619
620#ifndef QT_NO_ACTION
621/*!
622    Returns a pointer to a QAction that encapsulates the specified web action \a action.
623*/
624QAction *QWebView::pageAction(QWebPage::WebAction action) const
625{
626    return page()->action(action);
627}
628#endif
629
630/*!
631    Triggers the specified \a action. If it is a checkable action the specified
632    \a checked state is assumed.
633
634    The following example triggers the copy action and therefore copies any
635    selected text to the clipboard.
636
637    \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 2
638
639    \sa pageAction()
640*/
641void QWebView::triggerPageAction(QWebPage::WebAction action, bool checked)
642{
643    page()->triggerAction(action, checked);
644}
645
646/*!
647    \property QWebView::modified
648    \brief whether the document was modified by the user
649
650    Parts of HTML documents can be editable for example through the
651    \c{contenteditable} attribute on HTML elements.
652
653    By default, this property is false.
654*/
655bool QWebView::isModified() const
656{
657    if (d->page)
658        return d->page->isModified();
659    return false;
660}
661
662/*
663Qt::TextInteractionFlags QWebView::textInteractionFlags() const
664{
665    // ### FIXME (add to page)
666    return Qt::TextInteractionFlags();
667}
668*/
669
670/*
671    \property QWebView::textInteractionFlags
672    \brief how the view should handle user input
673
674    Specifies how the user can interact with the text on the page.
675*/
676
677/*
678void QWebView::setTextInteractionFlags(Qt::TextInteractionFlags flags)
679{
680    Q_UNUSED(flags)
681    // ### FIXME (add to page)
682}
683*/
684
685/*!
686    \reimp
687*/
688QSize QWebView::sizeHint() const
689{
690    return QSize(800, 600); // ####...
691}
692
693/*!
694    \property QWebView::zoomFactor
695    \since 4.5
696    \brief the zoom factor for the view
697*/
698
699void QWebView::setZoomFactor(qreal factor)
700{
701    page()->mainFrame()->setZoomFactor(factor);
702}
703
704qreal QWebView::zoomFactor() const
705{
706    return page()->mainFrame()->zoomFactor();
707}
708
709/*!
710  \property QWebView::textSizeMultiplier
711  \brief the scaling factor for all text in the frame
712  \obsolete
713
714  Use setZoomFactor instead, in combination with the
715  ZoomTextOnly attribute in QWebSettings.
716
717  \note Setting this property also enables the
718  ZoomTextOnly attribute in QWebSettings.
719
720  By default, this property contains a value of 1.0.
721*/
722
723/*!
724    Sets the value of the multiplier used to scale the text in a Web page to
725    the \a factor specified.
726*/
727void QWebView::setTextSizeMultiplier(qreal factor)
728{
729    page()->mainFrame()->setTextSizeMultiplier(factor);
730}
731
732/*!
733    Returns the value of the multiplier used to scale the text in a Web page.
734*/
735qreal QWebView::textSizeMultiplier() const
736{
737    return page()->mainFrame()->textSizeMultiplier();
738}
739
740/*!
741    \property QWebView::renderHints
742    \since 4.6
743    \brief the default render hints for the view
744
745    These hints are used to initialize QPainter before painting the Web page.
746
747    QPainter::TextAntialiasing and QPainter::SmoothPixmapTransform are enabled by default.
748
749    \note This property is not available on Symbian. However, the getter and
750    setter functions can still be used directly.
751
752    \sa QPainter::renderHints()
753*/
754
755/*!
756    \since 4.6
757    Returns the render hints used by the view to render content.
758
759    \sa QPainter::renderHints()
760*/
761QPainter::RenderHints QWebView::renderHints() const
762{
763    return d->renderHints;
764}
765
766/*!
767    \since 4.6
768    Sets the render hints used by the view to the specified \a hints.
769
770    \sa QPainter::setRenderHints()
771*/
772void QWebView::setRenderHints(QPainter::RenderHints hints)
773{
774    if (hints == d->renderHints)
775        return;
776    d->renderHints = hints;
777    update();
778}
779
780/*!
781    \since 4.6
782    If \a enabled is true, enables the specified render \a hint; otherwise
783    disables it.
784
785    \sa renderHints, QPainter::renderHints()
786*/
787void QWebView::setRenderHint(QPainter::RenderHint hint, bool enabled)
788{
789    QPainter::RenderHints oldHints = d->renderHints;
790    if (enabled)
791        d->renderHints |= hint;
792    else
793        d->renderHints &= ~hint;
794    if (oldHints != d->renderHints)
795        update();
796}
797
798
799/*!
800    Finds the specified string, \a subString, in the page, using the given \a options.
801
802    If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
803    that exist in the page. All subsequent calls will extend the highlight, rather than
804    replace it, with occurrences of the new string.
805
806    If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
807    and all subsequent calls will replace the current occurrence with the next one.
808
809    To clear the selection, just pass an empty string.
810
811    Returns true if \a subString was found; otherwise returns false.
812
813    \sa selectedText(), selectionChanged()
814*/
815bool QWebView::findText(const QString &subString, QWebPage::FindFlags options)
816{
817    if (d->page)
818        return d->page->findText(subString, options);
819    return false;
820}
821
822/*! \reimp
823*/
824bool QWebView::event(QEvent *e)
825{
826    if (d->page) {
827#ifndef QT_NO_CONTEXTMENU
828        if (e->type() == QEvent::ContextMenu) {
829            if (!isEnabled())
830                return false;
831            QContextMenuEvent *event = static_cast<QContextMenuEvent *>(e);
832            if (d->page->swallowContextMenuEvent(event)) {
833                e->accept();
834                return true;
835            }
836            d->page->updatePositionDependentActions(event->pos());
837        } else
838#endif // QT_NO_CONTEXTMENU
839        if (e->type() == QEvent::ShortcutOverride) {
840            d->page->event(e);
841#ifndef QT_NO_CURSOR
842        } else if (e->type() == QEvent::CursorChange) {
843            // An unsetCursor will set the cursor to Qt::ArrowCursor.
844            // Thus this cursor change might be a QWidget::unsetCursor()
845            // If this is not the case and it came from WebCore, the
846            // QWebPageClient already has set its cursor internally
847            // to Qt::ArrowCursor, so updating the cursor is always
848            // right, as it falls back to the last cursor set by
849            // WebCore.
850            // FIXME: Add a QEvent::CursorUnset or similar to Qt.
851            if (cursor().shape() == Qt::ArrowCursor)
852                d->page->d->client->resetCursor();
853#endif
854        } else if (e->type() == QEvent::TouchBegin
855                   || e->type() == QEvent::TouchEnd
856                   || e->type() == QEvent::TouchUpdate) {
857            d->page->event(e);
858
859            // Always return true so that we'll receive also TouchUpdate and TouchEnd events
860            return true;
861        } else if (e->type() == QEvent::Leave)
862            d->page->event(e);
863    }
864
865    return QWidget::event(e);
866}
867
868/*!
869    Prints the main frame to the given \a printer.
870
871    \sa QWebFrame::print(), QPrintPreviewDialog
872*/
873void QWebView::print(QPrinter *printer) const
874{
875#ifndef QT_NO_PRINTER
876    page()->mainFrame()->print(printer);
877#endif
878}
879
880/*!
881    Convenience slot that stops loading the document.
882
883    It is equivalent to
884
885    \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 3
886
887    \sa reload(), pageAction(), loadFinished()
888*/
889void QWebView::stop()
890{
891    if (d->page)
892        d->page->triggerAction(QWebPage::Stop);
893}
894
895/*!
896    Convenience slot that loads the previous document in the list of documents
897    built by navigating links. Does nothing if there is no previous document.
898
899    It is equivalent to
900
901    \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 4
902
903    \sa forward(), pageAction()
904*/
905void QWebView::back()
906{
907    if (d->page)
908        d->page->triggerAction(QWebPage::Back);
909}
910
911/*!
912    Convenience slot that loads the next document in the list of documents
913    built by navigating links. Does nothing if there is no next document.
914
915    It is equivalent to
916
917    \snippet webkitsnippets/qtwebkit_qwebview_snippet.cpp 5
918
919    \sa back(), pageAction()
920*/
921void QWebView::forward()
922{
923    if (d->page)
924        d->page->triggerAction(QWebPage::Forward);
925}
926
927/*!
928    Reloads the current document.
929
930    \sa stop(), pageAction(), loadStarted()
931*/
932void QWebView::reload()
933{
934    if (d->page)
935        d->page->triggerAction(QWebPage::Reload);
936}
937
938/*! \reimp
939*/
940void QWebView::resizeEvent(QResizeEvent *e)
941{
942    if (d->page)
943        d->page->setViewportSize(e->size());
944}
945
946/*! \reimp
947*/
948void QWebView::paintEvent(QPaintEvent *ev)
949{
950    if (!d->page)
951        return;
952#ifdef QWEBKIT_TIME_RENDERING
953    QTime time;
954    time.start();
955#endif
956
957    QWebFrame *frame = d->page->mainFrame();
958    QPainter p(this);
959    p.setRenderHints(d->renderHints);
960
961    frame->render(&p, ev->region());
962
963#ifdef    QWEBKIT_TIME_RENDERING
964    int elapsed = time.elapsed();
965    qDebug() << "paint event on " << ev->region() << ", took to render =  " << elapsed;
966#endif
967}
968
969/*!
970    This function is called from the createWindow() method of the associated QWebPage,
971    each time the page wants to create a new window of the given \a type. This might
972    be the result, for example, of a JavaScript request to open a document in a new window.
973
974    \note If the createWindow() method of the associated page is reimplemented, this
975    method is not called, unless explicitly done so in the reimplementation.
976
977    \note In the cases when the window creation is being triggered by JavaScript, apart from
978    reimplementing this method application must also set the JavaScriptCanOpenWindows attribute
979    of QWebSettings to true in order for it to get called.
980
981    \sa QWebPage::createWindow(), QWebPage::acceptNavigationRequest()
982*/
983QWebView *QWebView::createWindow(QWebPage::WebWindowType type)
984{
985    Q_UNUSED(type)
986    return 0;
987}
988
989/*! \reimp
990*/
991void QWebView::mouseMoveEvent(QMouseEvent* ev)
992{
993    if (d->page) {
994        const bool accepted = ev->isAccepted();
995        d->page->event(ev);
996        ev->setAccepted(accepted);
997    }
998}
999
1000/*! \reimp
1001*/
1002void QWebView::mousePressEvent(QMouseEvent* ev)
1003{
1004    if (d->page) {
1005        const bool accepted = ev->isAccepted();
1006        d->page->event(ev);
1007        ev->setAccepted(accepted);
1008    }
1009}
1010
1011/*! \reimp
1012*/
1013void QWebView::mouseDoubleClickEvent(QMouseEvent* ev)
1014{
1015    if (d->page) {
1016        const bool accepted = ev->isAccepted();
1017        d->page->event(ev);
1018        ev->setAccepted(accepted);
1019    }
1020}
1021
1022/*! \reimp
1023*/
1024void QWebView::mouseReleaseEvent(QMouseEvent* ev)
1025{
1026    if (d->page) {
1027        const bool accepted = ev->isAccepted();
1028        d->page->event(ev);
1029        ev->setAccepted(accepted);
1030    }
1031}
1032
1033#ifndef QT_NO_CONTEXTMENU
1034/*! \reimp
1035*/
1036void QWebView::contextMenuEvent(QContextMenuEvent* ev)
1037{
1038    if (d->page) {
1039        const bool accepted = ev->isAccepted();
1040        d->page->event(ev);
1041        ev->setAccepted(accepted);
1042    }
1043}
1044#endif // QT_NO_CONTEXTMENU
1045
1046#ifndef QT_NO_WHEELEVENT
1047/*! \reimp
1048*/
1049void QWebView::wheelEvent(QWheelEvent* ev)
1050{
1051    if (d->page) {
1052        const bool accepted = ev->isAccepted();
1053        d->page->event(ev);
1054        ev->setAccepted(accepted);
1055    }
1056}
1057#endif // QT_NO_WHEELEVENT
1058
1059/*! \reimp
1060*/
1061void QWebView::keyPressEvent(QKeyEvent* ev)
1062{
1063    if (d->page)
1064        d->page->event(ev);
1065    if (!ev->isAccepted())
1066        QWidget::keyPressEvent(ev);
1067}
1068
1069/*! \reimp
1070*/
1071void QWebView::keyReleaseEvent(QKeyEvent* ev)
1072{
1073    if (d->page)
1074        d->page->event(ev);
1075    if (!ev->isAccepted())
1076        QWidget::keyReleaseEvent(ev);
1077}
1078
1079/*! \reimp
1080*/
1081void QWebView::focusInEvent(QFocusEvent* ev)
1082{
1083    if (d->page)
1084        d->page->event(ev);
1085    else
1086        QWidget::focusInEvent(ev);
1087}
1088
1089/*! \reimp
1090*/
1091void QWebView::focusOutEvent(QFocusEvent* ev)
1092{
1093    if (d->page)
1094        d->page->event(ev);
1095    else
1096        QWidget::focusOutEvent(ev);
1097}
1098
1099/*! \reimp
1100*/
1101void QWebView::dragEnterEvent(QDragEnterEvent* ev)
1102{
1103#ifndef QT_NO_DRAGANDDROP
1104    if (d->page)
1105        d->page->event(ev);
1106#endif
1107}
1108
1109/*! \reimp
1110*/
1111void QWebView::dragLeaveEvent(QDragLeaveEvent* ev)
1112{
1113#ifndef QT_NO_DRAGANDDROP
1114    if (d->page)
1115        d->page->event(ev);
1116#endif
1117}
1118
1119/*! \reimp
1120*/
1121void QWebView::dragMoveEvent(QDragMoveEvent* ev)
1122{
1123#ifndef QT_NO_DRAGANDDROP
1124    if (d->page)
1125        d->page->event(ev);
1126#endif
1127}
1128
1129/*! \reimp
1130*/
1131void QWebView::dropEvent(QDropEvent* ev)
1132{
1133#ifndef QT_NO_DRAGANDDROP
1134    if (d->page)
1135        d->page->event(ev);
1136#endif
1137}
1138
1139/*! \reimp
1140*/
1141bool QWebView::focusNextPrevChild(bool next)
1142{
1143    if (d->page && d->page->focusNextPrevChild(next))
1144        return true;
1145    return QWidget::focusNextPrevChild(next);
1146}
1147
1148/*!\reimp
1149*/
1150QVariant QWebView::inputMethodQuery(Qt::InputMethodQuery property) const
1151{
1152    if (d->page)
1153        return d->page->inputMethodQuery(property);
1154    return QVariant();
1155}
1156
1157/*!\reimp
1158*/
1159void QWebView::inputMethodEvent(QInputMethodEvent *e)
1160{
1161    if (d->page)
1162       d->page->event(e);
1163}
1164
1165/*!\reimp
1166*/
1167void QWebView::changeEvent(QEvent *e)
1168{
1169    if (d->page && e->type() == QEvent::PaletteChange)
1170        d->page->setPalette(palette());
1171    QWidget::changeEvent(e);
1172}
1173
1174/*!
1175    \fn void QWebView::titleChanged(const QString &title)
1176
1177    This signal is emitted whenever the \a title of the main frame changes.
1178
1179    \sa title()
1180*/
1181
1182/*!
1183    \fn void QWebView::urlChanged(const QUrl &url)
1184
1185    This signal is emitted when the \a url of the view changes.
1186
1187    \sa url(), load()
1188*/
1189
1190/*!
1191    \fn void QWebView::statusBarMessage(const QString& text)
1192
1193    This signal is emitted when the status bar \a text is changed by the page.
1194*/
1195
1196/*!
1197    \fn void QWebView::iconChanged()
1198
1199    This signal is emitted whenever the icon of the page is loaded or changes.
1200
1201    In order for icons to be loaded, you will need to set an icon database path
1202    using QWebSettings::setIconDatabasePath().
1203
1204    \sa icon(), QWebSettings::setIconDatabasePath()
1205*/
1206
1207/*!
1208    \fn void QWebView::loadStarted()
1209
1210    This signal is emitted when a new load of the page is started.
1211
1212    \sa loadProgress(), loadFinished()
1213*/
1214
1215/*!
1216    \fn void QWebView::loadFinished(bool ok)
1217
1218    This signal is emitted when a load of the page is finished.
1219    \a ok will indicate whether the load was successful or any error occurred.
1220
1221    \sa loadStarted()
1222*/
1223
1224/*!
1225    \fn void QWebView::selectionChanged()
1226
1227    This signal is emitted whenever the selection changes.
1228
1229    \sa selectedText()
1230*/
1231
1232/*!
1233    \fn void QWebView::loadProgress(int progress)
1234
1235    This signal is emitted every time an element in the web page
1236    completes loading and the overall loading progress advances.
1237
1238    This signal tracks the progress of all child frames.
1239
1240    The current value is provided by \a progress and scales from 0 to 100,
1241    which is the default range of QProgressBar.
1242
1243    \sa loadStarted(), loadFinished()
1244*/
1245
1246/*!
1247    \fn void QWebView::linkClicked(const QUrl &url)
1248
1249    This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
1250    property is set to delegate the link handling for the specified \a url.
1251
1252    \sa QWebPage::linkDelegationPolicy()
1253*/
1254
1255#include "moc_qwebview.cpp"
1256
1257