1/*
2    Copyright (C) 2008, 2009, 2012 Nokia Corporation and/or its subsidiary(-ies)
3    Copyright (C) 2007 Staikos Computing Services Inc.
4    Copyright (C) 2007 Apple Inc.
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 "qwebpage.h"
24
25#include "DefaultFullScreenVideoHandler.h"
26#include "InitWebKitQt.h"
27#include "InspectorClientQt.h"
28#include "InspectorClientWebPage.h"
29#include "InspectorServerQt.h"
30#include "PageClientQt.h"
31#include "QGraphicsWidgetPluginImpl.h"
32#include "QWebUndoCommand.h"
33#include "QWidgetPluginImpl.h"
34#include "QtFallbackWebPopup.h"
35#include "QtPlatformPlugin.h"
36#include "UndoStepQt.h"
37#include "WebEventConversion.h"
38
39#include "qwebframe.h"
40#include "qwebframe_p.h"
41#include "qwebhistory.h"
42#include "qwebinspector.h"
43#include "qwebinspector_p.h"
44#include "qwebkitplatformplugin.h"
45#include "qwebpage_p.h"
46#include "qwebsettings.h"
47#include "qwebview.h"
48
49#include <QAction>
50#include <QApplication>
51#include <QBasicTimer>
52#include <QBitArray>
53#include <QClipboard>
54#include <QColorDialog>
55#include <QDebug>
56#include <QDesktopWidget>
57#include <QDragEnterEvent>
58#include <QDragLeaveEvent>
59#include <QDragMoveEvent>
60#include <QDropEvent>
61#include <QFileDialog>
62#include <QGestureEvent>
63#include <QInputDialog>
64#include <QLabel>
65#include <QMenu>
66#include <QMessageBox>
67#include <QNetworkAccessManager>
68#include <QNetworkProxy>
69#include <QNetworkRequest>
70#include <QPainter>
71#include <QSslSocket>
72#include <QStyle>
73#include <QSysInfo>
74#if USE(QT_MOBILITY_SYSTEMINFO)
75#include <qsysteminfo.h>
76#endif
77#include <QSystemTrayIcon>
78#include <QTextCharFormat>
79#include <QToolTip>
80#include <QTouchEvent>
81#include <QUndoStack>
82#include <QUrl>
83#if defined(Q_WS_X11)
84#include <QX11Info>
85#endif
86
87using namespace WebCore;
88
89// Lookup table mapping QWebPage::WebActions to the associated Editor commands
90static const char* editorCommandWebActions[] =
91{
92    0, // OpenLink,
93
94    0, // OpenLinkInNewWindow,
95    0, // OpenFrameInNewWindow,
96
97    0, // DownloadLinkToDisk,
98    0, // CopyLinkToClipboard,
99
100    0, // OpenImageInNewWindow,
101    0, // DownloadImageToDisk,
102    0, // CopyImageToClipboard,
103
104    0, // Back,
105    0, // Forward,
106    0, // Stop,
107    0, // Reload,
108
109    "Cut", // Cut,
110    "Copy", // Copy,
111    "Paste", // Paste,
112
113    "Undo", // Undo,
114    "Redo", // Redo,
115    "MoveForward", // MoveToNextChar,
116    "MoveBackward", // MoveToPreviousChar,
117    "MoveWordForward", // MoveToNextWord,
118    "MoveWordBackward", // MoveToPreviousWord,
119    "MoveDown", // MoveToNextLine,
120    "MoveUp", // MoveToPreviousLine,
121    "MoveToBeginningOfLine", // MoveToStartOfLine,
122    "MoveToEndOfLine", // MoveToEndOfLine,
123    "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
124    "MoveToEndOfParagraph", // MoveToEndOfBlock,
125    "MoveToBeginningOfDocument", // MoveToStartOfDocument,
126    "MoveToEndOfDocument", // MoveToEndOfDocument,
127    "MoveForwardAndModifySelection", // SelectNextChar,
128    "MoveBackwardAndModifySelection", // SelectPreviousChar,
129    "MoveWordForwardAndModifySelection", // SelectNextWord,
130    "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
131    "MoveDownAndModifySelection", // SelectNextLine,
132    "MoveUpAndModifySelection", // SelectPreviousLine,
133    "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
134    "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
135    "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
136    "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
137    "MoveToBeginningOfDocumentAndModifySelection", // SelectStartOfDocument,
138    "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
139    "DeleteWordBackward", // DeleteStartOfWord,
140    "DeleteWordForward", // DeleteEndOfWord,
141
142    0, // SetTextDirectionDefault,
143    0, // SetTextDirectionLeftToRight,
144    0, // SetTextDirectionRightToLeft,
145
146    "ToggleBold", // ToggleBold,
147    "ToggleItalic", // ToggleItalic,
148    "ToggleUnderline", // ToggleUnderline,
149
150    0, // InspectElement,
151
152    "InsertNewline", // InsertParagraphSeparator
153    "InsertLineBreak", // InsertLineSeparator
154
155    "SelectAll", // SelectAll
156    0, // ReloadAndBypassCache,
157
158    "PasteAndMatchStyle", // PasteAndMatchStyle
159    "RemoveFormat", // RemoveFormat
160    "Strikethrough", // ToggleStrikethrough,
161    "Subscript", // ToggleSubscript
162    "Superscript", // ToggleSuperscript
163    "InsertUnorderedList", // InsertUnorderedList
164    "InsertOrderedList", // InsertOrderedList
165    "Indent", // Indent
166    "Outdent", // Outdent,
167
168    "AlignCenter", // AlignCenter,
169    "AlignJustified", // AlignJustified,
170    "AlignLeft", // AlignLeft,
171    "AlignRight", // AlignRight,
172
173    0, // StopScheduledPageRefresh,
174
175    0, // CopyImageUrlToClipboard,
176
177    0, // OpenLinkInThisWindow,
178
179    0 // WebActionCount
180};
181
182// Lookup the appropriate editor command to use for WebAction \a action
183const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
184{
185    if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
186        return editorCommandWebActions[action];
187    return 0;
188}
189
190QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
191    : q(qq)
192#ifndef QT_NO_UNDOSTACK
193    , undoStack(0)
194#endif
195    , linkPolicy(QWebPage::DontDelegateLinks)
196    , m_viewportSize(QSize(0, 0))
197    , useFixedLayout(false)
198    , inspectorFrontend(0)
199    , inspector(0)
200    , inspectorIsInternalOnly(false)
201    , m_lastDropAction(Qt::IgnoreAction)
202{
203    WebKit::initializeWebKitWidgets();
204    initializeWebCorePage();
205    memset(actions, 0, sizeof(actions));
206
207#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
208    addNotificationPresenterClient();
209#ifndef QT_NO_SYSTEMTRAYICON
210    if (!hasSystemTrayIcon())
211        setSystemTrayIcon(new QSystemTrayIcon);
212#endif // QT_NO_SYSTEMTRAYICON
213#endif // ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
214}
215
216QWebPagePrivate::~QWebPagePrivate()
217{
218#ifndef QT_NO_CONTEXTMENU
219    delete currentContextMenu.data();
220#endif
221#ifndef QT_NO_UNDOSTACK
222    delete undoStack;
223    undoStack = 0;
224#endif
225
226    if (inspector) {
227        // If the inspector is ours, delete it, otherwise just detach from it.
228        if (inspectorIsInternalOnly)
229            delete inspector;
230        else
231            inspector->setPage(0);
232    }
233    // Explicitly destruct the WebCore page at this point when the
234    // QWebPagePrivate / QWebPageAdapater vtables are still intact,
235    // in order for various destruction callbacks out of WebCore to
236    // work.
237    deletePage();
238}
239
240void QWebPagePrivate::show()
241{
242    if (!view)
243        return;
244    view->window()->show();
245}
246
247void QWebPagePrivate::setFocus()
248{
249    if (!view)
250        return;
251    view->setFocus();
252}
253
254void QWebPagePrivate::unfocus()
255{
256    if (!view)
257        return;
258    view->clearFocus();
259}
260
261void QWebPagePrivate::setWindowRect(const QRect &rect)
262{
263    emit q->geometryChangeRequested(rect);
264}
265
266QSize QWebPagePrivate::viewportSize() const
267{
268    return q->viewportSize();
269}
270
271QWebPageAdapter *QWebPagePrivate::createWindow(bool dialog)
272{
273    QWebPage *newPage = q->createWindow(dialog ? QWebPage::WebModalDialog : QWebPage::WebBrowserWindow);
274    if (!newPage)
275        return 0;
276    // Make sure the main frame exists, as WebCore expects it when returning from this ChromeClient::createWindow()
277    newPage->d->createMainFrame();
278    return newPage->d;
279}
280
281void QWebPagePrivate::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID)
282{
283    q->javaScriptConsoleMessage(message, lineNumber, sourceID);
284}
285
286void QWebPagePrivate::javaScriptAlert(QWebFrameAdapter* frame, const QString& msg)
287{
288    q->javaScriptAlert(QWebFramePrivate::kit(frame), msg);
289}
290
291bool QWebPagePrivate::javaScriptConfirm(QWebFrameAdapter* frame, const QString& msg)
292{
293    return q->javaScriptConfirm(QWebFramePrivate::kit(frame), msg);
294}
295
296bool QWebPagePrivate::javaScriptPrompt(QWebFrameAdapter *frame, const QString &msg, const QString &defaultValue, QString *result)
297{
298    return q->javaScriptPrompt(QWebFramePrivate::kit(frame), msg, defaultValue, result);
299}
300
301bool QWebPagePrivate::shouldInterruptJavaScript()
302{
303    return q->shouldInterruptJavaScript();
304}
305
306void QWebPagePrivate::printRequested(QWebFrameAdapter *frame)
307{
308    emit q->printRequested(QWebFramePrivate::kit(frame));
309}
310
311void QWebPagePrivate::databaseQuotaExceeded(QWebFrameAdapter* frame, const QString& databaseName)
312{
313    emit q->databaseQuotaExceeded(QWebFramePrivate::kit(frame), databaseName);
314}
315
316void QWebPagePrivate::applicationCacheQuotaExceeded(QWebSecurityOrigin *origin, quint64 defaultOriginQuota, quint64 c)
317{
318    emit q->applicationCacheQuotaExceeded(origin, defaultOriginQuota, c);
319}
320
321void QWebPagePrivate::setToolTip(const QString &tip)
322{
323#ifndef QT_NO_TOOLTIP
324    if (!view)
325        return;
326
327    if (tip.isEmpty()) {
328        view->setToolTip(QString());
329        QToolTip::hideText();
330    } else {
331        QString dtip = QLatin1String("<p>") + QString(tip).toHtmlEscaped() + QLatin1String("</p>");
332        view->setToolTip(dtip);
333    }
334#else
335    Q_UNUSED(tip);
336#endif
337}
338
339#if USE(QT_MULTIMEDIA)
340QWebFullScreenVideoHandler *QWebPagePrivate::createFullScreenVideoHandler()
341{
342    return new WebKit::DefaultFullScreenVideoHandler;
343}
344#endif
345
346QWebFrameAdapter *QWebPagePrivate::mainFrameAdapter()
347{
348    return q->mainFrame()->d;
349}
350
351QStringList QWebPagePrivate::chooseFiles(QWebFrameAdapter *frame, bool allowMultiple, const QStringList &suggestedFileNames)
352{
353    if (allowMultiple && q->supportsExtension(QWebPage::ChooseMultipleFilesExtension)) {
354        QWebPage::ChooseMultipleFilesExtensionOption option;
355        option.parentFrame = QWebFramePrivate::kit(frame);
356        option.suggestedFileNames = suggestedFileNames;
357
358        QWebPage::ChooseMultipleFilesExtensionReturn output;
359        q->extension(QWebPage::ChooseMultipleFilesExtension, &option, &output);
360
361        return output.fileNames;
362    }
363    // Single file
364    QStringList result;
365    QString suggestedFile;
366    if (!suggestedFileNames.isEmpty())
367        suggestedFile = suggestedFileNames.first();
368    QString file = q->chooseFile(QWebFramePrivate::kit(frame), suggestedFile);
369    if (!file.isEmpty())
370        result << file;
371    return result;
372}
373
374bool QWebPagePrivate::acceptNavigationRequest(QWebFrameAdapter *frameAdapter, const QNetworkRequest &request, int type)
375{
376    QWebFrame *frame = frameAdapter ? QWebFramePrivate::kit(frameAdapter): 0;
377    if (insideOpenCall
378        && frame == mainFrame.data())
379        return true;
380    return q->acceptNavigationRequest(frame, request, QWebPage::NavigationType(type));
381}
382
383void QWebPagePrivate::emitRestoreFrameStateRequested(QWebFrameAdapter *frame)
384{
385    emit q->restoreFrameStateRequested(QWebFramePrivate::kit(frame));
386}
387
388void QWebPagePrivate::emitSaveFrameStateRequested(QWebFrameAdapter *frame, QWebHistoryItem *item)
389{
390    emit q->saveFrameStateRequested(QWebFramePrivate::kit(frame), item);
391}
392
393void QWebPagePrivate::emitDownloadRequested(const QNetworkRequest &request)
394{
395    emit q->downloadRequested(request);
396}
397
398void QWebPagePrivate::emitFrameCreated(QWebFrameAdapter *frame)
399{
400    emit q->frameCreated(QWebFramePrivate::kit(frame));
401}
402
403bool QWebPagePrivate::errorPageExtension(QWebPageAdapter::ErrorPageOption *opt, QWebPageAdapter::ErrorPageReturn *out)
404{
405    QWebPage::ErrorPageExtensionOption option;
406    if (opt->domain == QLatin1String("QtNetwork"))
407        option.domain = QWebPage::QtNetwork;
408    else if (opt->domain == QLatin1String("HTTP"))
409        option.domain = QWebPage::Http;
410    else if (opt->domain == QLatin1String("WebKit"))
411        option.domain = QWebPage::WebKit;
412    else
413        return false;
414    option.url = opt->url;
415    option.frame = QWebFramePrivate::kit(opt->frame);
416    option.error = opt->error;
417    option.errorString = opt->errorString;
418    QWebPage::ErrorPageExtensionReturn output;
419    if (!q->extension(QWebPage::ErrorPageExtension, &option, &output))
420        return false;
421    out->baseUrl = output.baseUrl;
422    out->content = output.content;
423    out->contentType = output.contentType;
424    out->encoding = output.encoding;
425    return true;
426}
427
428QtPluginWidgetAdapter *QWebPagePrivate::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
429{
430    QObject *widget = q->createPlugin(classid, url, paramNames, paramValues);
431    return adapterForWidget(widget);
432}
433
434QtPluginWidgetAdapter *QWebPagePrivate::adapterForWidget(QObject *object) const
435{
436    if (QWidget *widget = qobject_cast<QWidget*>(object))
437        return new QWidgetPluginImpl(widget);
438    if (QGraphicsWidget *widget = qobject_cast<QGraphicsWidget*>(object))
439        return new QGraphicsWidgetPluginImpl(widget);
440    return 0;
441}
442
443void QWebPagePrivate::createMainFrame()
444{
445    if (!mainFrame) {
446        mainFrame = new QWebFrame(q);
447        emit q->frameCreated(mainFrame.data());
448    }
449}
450
451#define MAP_WEB_ACTION_FROM_ADAPTER_EQUIVALENT(Name, Value) \
452    case QWebPageAdapter::Name: return QWebPage::Name
453
454static QWebPage::WebAction webActionForAdapterMenuAction(QWebPageAdapter::MenuAction action)
455{
456    switch (action) {
457        FOR_EACH_MAPPED_MENU_ACTION(MAP_WEB_ACTION_FROM_ADAPTER_EQUIVALENT, SEMICOLON_SEPARATOR);
458#if ENABLE(INSPECTOR)
459    case QWebPageAdapter::InspectElement: return QWebPage::InspectElement;
460#endif
461    default:
462        ASSERT_NOT_REACHED();
463        break;
464    }
465    return QWebPage::NoWebAction;
466}
467
468#define MAP_ADAPTER_ACTION_FROM_WEBACTION_EQUIVALENT(Name, Value) \
469    case QWebPage::Name: return QWebPageAdapter::Name
470
471static QWebPageAdapter::MenuAction adapterMenuActionForWebAction(QWebPage::WebAction action)
472{
473    switch (action) {
474        FOR_EACH_MAPPED_MENU_ACTION(MAP_ADAPTER_ACTION_FROM_WEBACTION_EQUIVALENT, SEMICOLON_SEPARATOR);
475#if ENABLE(INSPECTOR)
476    case QWebPage::InspectElement: return QWebPageAdapter::InspectElement;
477#endif
478    default:
479        ASSERT_NOT_REACHED();
480        break;
481    }
482    return QWebPageAdapter::NoAction;
483}
484
485#ifndef QT_NO_CONTEXTMENU
486typedef QWebPageAdapter::MenuItemDescription MenuItem;
487QMenu *createContextMenu(QWebPage* page, const QList<MenuItem>& items, QBitArray *visitedWebActions)
488{
489    if (items.isEmpty())
490        return 0;
491
492    QMenu* menu = new QMenu(page->view());
493    for (int i = 0; i < items.count(); ++i) {
494        const MenuItem &item = items.at(i);
495        switch (item.type) {
496        case MenuItem::Action: {
497            QWebPage::WebAction action = webActionForAdapterMenuAction(item.action);
498            QAction *a = page->action(action);
499            if (a) {
500                a->setEnabled(item.traits & MenuItem::Enabled);
501                a->setCheckable(item.traits & MenuItem::Checkable);
502                a->setChecked(item.traits & MenuItem::Checked);
503
504                menu->addAction(a);
505                visitedWebActions->setBit(action);
506            }
507            break;
508        }
509        case MenuItem::Separator:
510            menu->addSeparator();
511            break;
512        case MenuItem::SubMenu: {
513            QMenu *subMenu = createContextMenu(page, item.subMenu, visitedWebActions);
514            Q_ASSERT(subMenu);
515
516            bool anyEnabledAction = false;
517
518            QList<QAction *> actions = subMenu->actions();
519            for (int i = 0; i < actions.count(); ++i) {
520                if (actions.at(i)->isVisible())
521                    anyEnabledAction |= actions.at(i)->isEnabled();
522            }
523
524            // don't show sub-menus with just disabled actions
525            if (anyEnabledAction) {
526                subMenu->setTitle(item.subMenuTitle);
527                menu->addAction(subMenu->menuAction());
528            } else
529                delete subMenu;
530            break;
531        }
532        }
533    }
534    return menu;
535}
536#endif // QT_NO_CONTEXTMENU
537
538void QWebPagePrivate::createAndSetCurrentContextMenu(const QList<MenuItemDescription>& items, QBitArray* visitedWebActions)
539{
540#ifndef QT_NO_CONTEXTMENU
541    delete currentContextMenu.data();
542
543    currentContextMenu = createContextMenu(q, items, visitedWebActions);
544#else
545    Q_UNUSED(menuDescription);
546    Q_UNUSED(visitedWebActions);
547#endif // QT_NO_CONTEXTMENU
548}
549
550#ifndef QT_NO_ACTION
551void QWebPagePrivate::_q_webActionTriggered(bool checked)
552{
553    QAction *a = qobject_cast<QAction *>(q->sender());
554    if (!a)
555        return;
556    QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
557    q->triggerAction(action, checked);
558}
559#endif // QT_NO_ACTION
560
561void QWebPagePrivate::updateAction(QWebPage::WebAction action)
562{
563#ifdef QT_NO_ACTION
564    Q_UNUSED(action)
565#else
566    QAction *a = actions[action];
567    if (!a || !mainFrame)
568        return;
569
570    bool enabled = a->isEnabled();
571    bool checked = a->isChecked();
572
573    QWebPageAdapter::MenuAction mappedAction = QWebPageAdapter::NoAction;
574    const char* commandName = 0;
575
576    switch (action) {
577    case QWebPage::Back:
578    case QWebPage::Forward:
579    case QWebPage::Stop:
580    case QWebPage::Reload:
581    case QWebPage::SetTextDirectionDefault:
582    case QWebPage::SetTextDirectionLeftToRight:
583    case QWebPage::SetTextDirectionRightToLeft:
584        mappedAction = adapterMenuActionForWebAction(action);
585        break;
586    case QWebPage::ReloadAndBypassCache: // Manual mapping
587        mappedAction = QWebPageAdapter::Reload;
588        break;
589#ifndef QT_NO_UNDOSTACK
590    case QWebPage::Undo:
591    case QWebPage::Redo:
592        // those two are handled by QUndoStack
593        break;
594#endif // QT_NO_UNDOSTACK
595    case QWebPage::SelectAll: // editor command is always enabled
596        break;
597    default: {
598        // see if it's an editor command
599        commandName = editorCommandForWebActions(action);
600        break;
601    }
602    }
603    if (mappedAction != QWebPageAdapter::NoAction || commandName)
604        updateActionInternal(mappedAction, commandName, &enabled, &checked);
605
606    a->setEnabled(enabled);
607
608    if (a->isCheckable())
609        a->setChecked(checked);
610#endif // QT_NO_ACTION
611}
612
613void QWebPagePrivate::updateNavigationActions()
614{
615    updateAction(QWebPage::Back);
616    updateAction(QWebPage::Forward);
617    updateAction(QWebPage::Stop);
618    updateAction(QWebPage::Reload);
619    updateAction(QWebPage::ReloadAndBypassCache);
620}
621
622QObject *QWebPagePrivate::inspectorHandle()
623{
624    return getOrCreateInspector();
625}
626
627void QWebPagePrivate::setInspectorFrontend(QObject* frontend)
628{
629    inspectorFrontend = qobject_cast<QWidget*>(frontend);
630    if (inspector)
631        inspector->d->setFrontend(frontend);
632}
633
634void QWebPagePrivate::setInspectorWindowTitle(const QString& title)
635{
636    if (inspector)
637        inspector->setWindowTitle(title);
638}
639
640void QWebPagePrivate::createWebInspector(QObject** inspectorView, QWebPageAdapter** inspectorPage)
641{
642    QWebPage* page = new WebKit::InspectorClientWebPage;
643    *inspectorView = page->view();
644    *inspectorPage = page->d;
645}
646
647#ifndef QT_NO_MENU
648static QStringList iterateContextMenu(QMenu* menu)
649{
650    if (!menu)
651        return QStringList();
652
653    QStringList items;
654    QList<QAction *> actions = menu->actions();
655    for (int i = 0; i < actions.count(); ++i) {
656        if (actions.at(i)->isSeparator())
657            items << QLatin1String("<separator>");
658        else
659            items << actions.at(i)->text();
660        if (actions.at(i)->menu())
661            items << iterateContextMenu(actions.at(i)->menu());
662    }
663    return items;
664}
665#endif
666
667QStringList QWebPagePrivate::menuActionsAsText()
668{
669#ifndef QT_NO_MENU
670    return iterateContextMenu(currentContextMenu.data());
671#else
672    return QStringList();
673#endif
674}
675
676void QWebPagePrivate::emitViewportChangeRequested()
677{
678    emit q->viewportChangeRequested();
679}
680
681void QWebPagePrivate::updateEditorActions()
682{
683    updateAction(QWebPage::Cut);
684    updateAction(QWebPage::Copy);
685    updateAction(QWebPage::Paste);
686    updateAction(QWebPage::MoveToNextChar);
687    updateAction(QWebPage::MoveToPreviousChar);
688    updateAction(QWebPage::MoveToNextWord);
689    updateAction(QWebPage::MoveToPreviousWord);
690    updateAction(QWebPage::MoveToNextLine);
691    updateAction(QWebPage::MoveToPreviousLine);
692    updateAction(QWebPage::MoveToStartOfLine);
693    updateAction(QWebPage::MoveToEndOfLine);
694    updateAction(QWebPage::MoveToStartOfBlock);
695    updateAction(QWebPage::MoveToEndOfBlock);
696    updateAction(QWebPage::MoveToStartOfDocument);
697    updateAction(QWebPage::MoveToEndOfDocument);
698    updateAction(QWebPage::SelectNextChar);
699    updateAction(QWebPage::SelectPreviousChar);
700    updateAction(QWebPage::SelectNextWord);
701    updateAction(QWebPage::SelectPreviousWord);
702    updateAction(QWebPage::SelectNextLine);
703    updateAction(QWebPage::SelectPreviousLine);
704    updateAction(QWebPage::SelectStartOfLine);
705    updateAction(QWebPage::SelectEndOfLine);
706    updateAction(QWebPage::SelectStartOfBlock);
707    updateAction(QWebPage::SelectEndOfBlock);
708    updateAction(QWebPage::SelectStartOfDocument);
709    updateAction(QWebPage::SelectEndOfDocument);
710    updateAction(QWebPage::DeleteStartOfWord);
711    updateAction(QWebPage::DeleteEndOfWord);
712    updateAction(QWebPage::SetTextDirectionDefault);
713    updateAction(QWebPage::SetTextDirectionLeftToRight);
714    updateAction(QWebPage::SetTextDirectionRightToLeft);
715    updateAction(QWebPage::ToggleBold);
716    updateAction(QWebPage::ToggleItalic);
717    updateAction(QWebPage::ToggleUnderline);
718    updateAction(QWebPage::InsertParagraphSeparator);
719    updateAction(QWebPage::InsertLineSeparator);
720    updateAction(QWebPage::PasteAndMatchStyle);
721    updateAction(QWebPage::RemoveFormat);
722    updateAction(QWebPage::ToggleStrikethrough);
723    updateAction(QWebPage::ToggleSubscript);
724    updateAction(QWebPage::ToggleSuperscript);
725    updateAction(QWebPage::InsertUnorderedList);
726    updateAction(QWebPage::InsertOrderedList);
727    updateAction(QWebPage::Indent);
728    updateAction(QWebPage::Outdent);
729    updateAction(QWebPage::AlignCenter);
730    updateAction(QWebPage::AlignJustified);
731    updateAction(QWebPage::AlignLeft);
732    updateAction(QWebPage::AlignRight);
733}
734
735void QWebPagePrivate::timerEvent(QTimerEvent *ev)
736{
737    int timerId = ev->timerId();
738    if (timerId == tripleClickTimer.timerId())
739        tripleClickTimer.stop();
740    else
741        q->timerEvent(ev);
742}
743
744bool QWebPagePrivate::requestSoftwareInputPanel() const
745{
746    return QStyle::RequestSoftwareInputPanel(client->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel)) == QStyle::RSIP_OnMouseClick;
747}
748
749#ifndef QT_NO_CONTEXTMENU
750void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
751{
752    QMenu *menu = q->createStandardContextMenu();
753    if (menu) {
754        menu->exec(globalPos);
755        delete menu;
756    }
757}
758#endif // QT_NO_CONTEXTMENU
759
760/*!
761    \since 4.5
762    This function creates the standard context menu which is shown when
763    the user clicks on the web page with the right mouse button. It is
764    called from the default contextMenuEvent() handler. The popup menu's
765    ownership is transferred to the caller.
766 */
767QMenu *QWebPage::createStandardContextMenu()
768{
769#ifndef QT_NO_CONTEXTMENU
770    QMenu* menu = d->currentContextMenu.data();
771    d->currentContextMenu = 0;
772    return menu;
773#else
774    return 0;
775#endif
776}
777
778#ifndef QT_NO_SHORTCUT
779QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
780{
781    static struct {
782        QKeySequence::StandardKey standardKey;
783        QWebPage::WebAction action;
784    } editorActions[] = {
785        { QKeySequence::Cut, QWebPage::Cut },
786        { QKeySequence::Copy, QWebPage::Copy },
787        { QKeySequence::Paste, QWebPage::Paste },
788        { QKeySequence::Undo, QWebPage::Undo },
789        { QKeySequence::Redo, QWebPage::Redo },
790        { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
791        { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
792        { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
793        { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
794        { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
795        { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
796        { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
797        { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
798        { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
799        { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
800        { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
801        { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
802        { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
803        { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
804        { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
805        { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
806        { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
807        { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
808        { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
809        { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
810        { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
811        { QKeySequence::SelectEndOfBlock,  QWebPage::SelectEndOfBlock },
812        { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
813        { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
814        { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
815        { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
816        { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
817        { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
818        { QKeySequence::SelectAll, QWebPage::SelectAll },
819        { QKeySequence::UnknownKey, QWebPage::NoWebAction }
820    };
821
822    for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
823        if (event == editorActions[i].standardKey)
824            return editorActions[i].action;
825
826    return QWebPage::NoWebAction;
827}
828#endif // QT_NO_SHORTCUT
829
830void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
831{
832    // we forward the key event to WebCore first to handle potential DOM
833    // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
834    // to trigger editor commands via triggerAction().
835    bool handled = handleKeyEvent(ev);
836
837    if (!handled)
838        handled = handleScrolling(ev);
839
840    if (!handled) {
841        handled = true;
842        switch (ev->key()) {
843        case Qt::Key_Back:
844            q->triggerAction(QWebPage::Back);
845            break;
846        case Qt::Key_Forward:
847            q->triggerAction(QWebPage::Forward);
848            break;
849        case Qt::Key_Stop:
850            q->triggerAction(QWebPage::Stop);
851            break;
852        case Qt::Key_Refresh:
853            q->triggerAction(QWebPage::Reload);
854            break;
855        default:
856            handled = false;
857            break;
858        }
859    }
860
861    ev->setAccepted(handled);
862}
863
864void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
865{
866    if (ev->isAutoRepeat()) {
867        ev->setAccepted(true);
868        return;
869    }
870
871    bool handled = handleKeyEvent(ev);
872    ev->setAccepted(handled);
873}
874
875template<class T>
876void QWebPagePrivate::dragEnterEvent(T* ev)
877{
878#ifndef QT_NO_DRAGANDDROP
879    Qt::DropAction action = dragEntered(ev->mimeData(), QPointF(ev->pos()).toPoint(), ev->possibleActions());
880    ev->setDropAction(action);
881    ev->acceptProposedAction();
882#endif
883}
884
885template<class T>
886void QWebPagePrivate::dragMoveEvent(T *ev)
887{
888#ifndef QT_NO_DRAGANDDROP
889    m_lastDropAction = dragUpdated(ev->mimeData(), QPointF(ev->pos()).toPoint(), ev->possibleActions());
890    ev->setDropAction(m_lastDropAction);
891    if (m_lastDropAction != Qt::IgnoreAction)
892        ev->accept();
893#endif
894}
895
896template<class T>
897void QWebPagePrivate::dropEvent(T *ev)
898{
899#ifndef QT_NO_DRAGANDDROP
900    if (performDrag(ev->mimeData(), QPointF(ev->pos()).toPoint(), ev->possibleActions())) {
901        ev->setDropAction(m_lastDropAction);
902        ev->accept();
903    }
904#endif
905}
906
907void QWebPagePrivate::leaveEvent(QEvent*)
908{
909    // Fake a mouse move event just outside of the widget, since all
910    // the interesting mouse-out behavior like invalidating scrollbars
911    // is handled by the WebKit event handler's mouseMoved function.
912    QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
913    mouseMoveEvent(&fakeEvent);
914}
915
916/*!
917    \property QWebPage::palette
918    \brief the page's palette
919
920    The base brush of the palette is used to draw the background of the main frame.
921
922    By default, this property contains the application's default palette.
923*/
924void QWebPage::setPalette(const QPalette &pal)
925{
926    d->palette = pal;
927    if (!d->mainFrame || !d->mainFrame.data()->d->hasView())
928        return;
929
930    QBrush brush = pal.brush(QPalette::Base);
931    QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
932    d->mainFrame.data()->d->updateBackgroundRecursively(backgroundColor);
933}
934
935QPalette QWebPage::palette() const
936{
937    return d->palette;
938}
939
940void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
941{
942    if (handleShortcutOverrideEvent(event))
943        return;
944#ifndef QT_NO_SHORTCUT
945    if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
946        event->accept();
947#endif
948
949}
950
951bool QWebPagePrivate::gestureEvent(QGestureEvent* event)
952{
953    QWebFrameAdapter* frame = mainFrame.data()->d;
954    if (!frame->hasView())
955        return false;
956    // QGestureEvents can contain updates for multiple gestures.
957    bool handled = false;
958#if ENABLE(GESTURE_EVENTS)
959    // QGestureEvent lives in Widgets, we'll need a dummy struct to mule the info it contains to the "other side"
960    QGestureEventFacade gestureFacade;
961
962    QGesture* gesture = event->gesture(Qt::TapGesture);
963    // Beware that gestures send by DumpRenderTree will have state Qt::NoGesture,
964    // due to not originating from a GestureRecognizer.
965    if (gesture && (gesture->state() == Qt::GestureStarted || gesture->state() == Qt::NoGesture)) {
966        gestureFacade.type = Qt::TapGesture;
967        QPointF globalPos = static_cast<const QTapGesture*>(gesture)->position();
968        gestureFacade.globalPos = globalPos.toPoint();
969        gestureFacade.pos = event->widget()->mapFromGlobal(globalPos.toPoint());
970        frame->handleGestureEvent(&gestureFacade);
971        handled = true;
972    }
973    gesture = event->gesture(Qt::TapAndHoldGesture);
974    if (gesture && (gesture->state() == Qt::GestureStarted || gesture->state() == Qt::NoGesture)) {
975        gestureFacade.type = Qt::TapAndHoldGesture;
976        QPointF globalPos = static_cast<const QTapAndHoldGesture*>(gesture)->position();
977        gestureFacade.globalPos = globalPos.toPoint();
978        gestureFacade.pos = event->widget()->mapFromGlobal(globalPos.toPoint());
979        frame->handleGestureEvent(&gestureFacade);
980        handled = true;
981    }
982#endif // ENABLE(GESTURE_EVENTS)
983
984    event->setAccepted(handled);
985    return handled;
986}
987
988/*!
989  This method is used by the input method to query a set of properties of the page
990  to be able to support complex input method operations as support for surrounding
991  text and reconversions.
992
993  \a property specifies which property is queried.
994
995  \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
996*/
997QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
998{
999    return d->inputMethodQuery(property);
1000}
1001
1002/*!
1003    \internal
1004*/
1005void QWebPagePrivate::setInspector(QWebInspector* insp)
1006{
1007    if (inspector)
1008        inspector->d->setFrontend(0);
1009
1010    inspector = insp;
1011
1012    // Give inspector frontend web view if previously created
1013    if (inspector && inspectorFrontend)
1014        inspector->d->setFrontend(inspectorFrontend);
1015}
1016
1017/*!
1018    \internal
1019    Returns the inspector and creates it if it wasn't created yet.
1020    The instance created here will not be available through QWebPage's API.
1021*/
1022QWebInspector* QWebPagePrivate::getOrCreateInspector()
1023{
1024#if ENABLE(INSPECTOR)
1025    if (!inspector) {
1026        QWebInspector* insp = new QWebInspector;
1027        insp->setPage(q);
1028        inspectorIsInternalOnly = true;
1029
1030        Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1031    }
1032#endif
1033    return inspector;
1034}
1035
1036/*!
1037   \enum QWebPage::FindFlag
1038
1039   This enum describes the options available to the findText() function. The options
1040   can be OR-ed together from the following list:
1041
1042   \value FindBackward Searches backwards instead of forwards.
1043   \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1044   changes the behaviour to a case sensitive find operation.
1045   \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1046   was reached and the text was not found.
1047   \value HighlightAllOccurrences Highlights all existing occurrences of a specific string.
1048       (This value was introduced in 4.6.)
1049   \value FindAtWordBeginningsOnly Searches for the sub-string only at the beginnings of words.
1050       (This value was introduced in 5.2.)
1051   \value TreatMedialCapitalAsWordBeginning Treats a capital letter occurring anywhere in the middle of a word
1052   as the beginning of a new word.
1053       (This value was introduced in 5.2.)
1054   \value FindBeginsInSelection Begin searching inside the text selection first.
1055       (This value was introduced in 5.2.)
1056*/
1057
1058/*!
1059    \enum QWebPage::LinkDelegationPolicy
1060
1061    This enum defines the delegation policies a webpage can have when activating links and emitting
1062    the linkClicked() signal.
1063
1064    \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1065    \value DelegateExternalLinks When activating links that point to documents not stored on the
1066    local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1067    \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1068
1069    \sa QWebPage::linkDelegationPolicy
1070*/
1071
1072/*!
1073    \enum QWebPage::NavigationType
1074
1075    This enum describes the types of navigation available when browsing through hyperlinked
1076    documents.
1077
1078    \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1079    \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1080    \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1081    \value NavigationTypeReload The user activated the reload action.
1082    \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1083    \value NavigationTypeOther A navigation to another document using a method not listed above.
1084
1085    \sa acceptNavigationRequest()
1086*/
1087
1088/*!
1089    \enum QWebPage::WebAction
1090
1091    This enum describes the types of action which can be performed on the web page.
1092
1093    Actions only have an effect when they are applicable. The availability of
1094    actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1095    action returned by action().
1096
1097    One method of enabling the text editing, cursor movement, and text selection actions
1098    is by setting \l contentEditable to true.
1099
1100    \value NoWebAction No action is triggered.
1101    \value OpenLink Open the current link.
1102    \value OpenLinkInNewWindow Open the current link in a new window.
1103    \value OpenLinkInThisWindow Open the current link without opening a new window. Used on links that would default to opening in another frame or a new window. (Added in Qt 5.0)
1104    \value OpenFrameInNewWindow Replicate the current frame in a new window.
1105    \value DownloadLinkToDisk Download the current link to the disk.
1106    \value CopyLinkToClipboard Copy the current link to the clipboard.
1107    \value OpenImageInNewWindow Open the highlighted image in a new window.
1108    \value DownloadImageToDisk Download the highlighted image to the disk.
1109    \value CopyImageToClipboard Copy the highlighted image to the clipboard.  (Added in Qt 4.8)
1110    \value CopyImageUrlToClipboard Copy the highlighted image's URL to the clipboard.
1111    \value Back Navigate back in the history of navigated links.
1112    \value Forward Navigate forward in the history of navigated links.
1113    \value Stop Stop loading the current page.
1114    \value StopScheduledPageRefresh Stop all pending page refresh/redirect requests.  (Added in Qt 4.7)
1115    \value Reload Reload the current page.
1116    \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1117    \value Cut Cut the content currently selected into the clipboard.
1118    \value Copy Copy the content currently selected into the clipboard.
1119    \value Paste Paste content from the clipboard.
1120    \value Undo Undo the last editing action.
1121    \value Redo Redo the last editing action.
1122    \value MoveToNextChar Move the cursor to the next character.
1123    \value MoveToPreviousChar Move the cursor to the previous character.
1124    \value MoveToNextWord Move the cursor to the next word.
1125    \value MoveToPreviousWord Move the cursor to the previous word.
1126    \value MoveToNextLine Move the cursor to the next line.
1127    \value MoveToPreviousLine Move the cursor to the previous line.
1128    \value MoveToStartOfLine Move the cursor to the start of the line.
1129    \value MoveToEndOfLine Move the cursor to the end of the line.
1130    \value MoveToStartOfBlock Move the cursor to the start of the block.
1131    \value MoveToEndOfBlock Move the cursor to the end of the block.
1132    \value MoveToStartOfDocument Move the cursor to the start of the document.
1133    \value MoveToEndOfDocument Move the cursor to the end of the document.
1134    \value SelectNextChar Select to the next character.
1135    \value SelectPreviousChar Select to the previous character.
1136    \value SelectNextWord Select to the next word.
1137    \value SelectPreviousWord Select to the previous word.
1138    \value SelectNextLine Select to the next line.
1139    \value SelectPreviousLine Select to the previous line.
1140    \value SelectStartOfLine Select to the start of the line.
1141    \value SelectEndOfLine Select to the end of the line.
1142    \value SelectStartOfBlock Select to the start of the block.
1143    \value SelectEndOfBlock Select to the end of the block.
1144    \value SelectStartOfDocument Select to the start of the document.
1145    \value SelectEndOfDocument Select to the end of the document.
1146    \value DeleteStartOfWord Delete to the start of the word.
1147    \value DeleteEndOfWord Delete to the end of the word.
1148    \value SetTextDirectionDefault Set the text direction to the default direction.
1149    \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1150    \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1151    \value ToggleBold Toggle the formatting between bold and normal weight.
1152    \value ToggleItalic Toggle the formatting between italic and normal style.
1153    \value ToggleUnderline Toggle underlining.
1154    \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1155    \value InsertParagraphSeparator Insert a new paragraph.
1156    \value InsertLineSeparator Insert a new line.
1157    \value SelectAll Selects all content.
1158    \value PasteAndMatchStyle Paste content from the clipboard with current style. (Added in Qt 4.6)
1159    \value RemoveFormat Removes formatting and style. (Added in Qt 4.6)
1160    \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style. (Added in Qt 4.6)
1161    \value ToggleSubscript Toggle the formatting between subscript and baseline. (Added in Qt 4.6)
1162    \value ToggleSuperscript Toggle the formatting between supercript and baseline. (Added in Qt 4.6)
1163    \value InsertUnorderedList Toggles the selection between an ordered list and a normal block. (Added in Qt 4.6)
1164    \value InsertOrderedList Toggles the selection between an ordered list and a normal block. (Added in Qt 4.6)
1165    \value Indent Increases the indentation of the currently selected format block by one increment. (Added in Qt 4.6)
1166    \value Outdent Decreases the indentation of the currently selected format block by one increment. (Added in Qt 4.6)
1167    \value AlignCenter Applies center alignment to content. (Added in Qt 4.6)
1168    \value AlignJustified Applies full justification to content. (Added in Qt 4.6)
1169    \value AlignLeft Applies left justification to content. (Added in Qt 4.6)
1170    \value AlignRight Applies right justification to content. (Added in Qt 4.6)
1171
1172
1173    \omitvalue WebActionCount
1174
1175*/
1176
1177/*!
1178    \enum QWebPage::WebWindowType
1179
1180    This enum describes the types of window that can be created by the createWindow() function.
1181
1182    \value WebBrowserWindow The window is a regular web browser window.
1183    \value WebModalDialog The window acts as modal dialog.
1184*/
1185
1186
1187/*!
1188    \class QWebPage::ViewportAttributes
1189    \since 4.7
1190    \brief The QWebPage::ViewportAttributes class describes hints that can be applied to a viewport.
1191
1192    QWebPage::ViewportAttributes provides a description of a viewport, such as viewport geometry,
1193    initial scale factor with limits, plus information about whether a user should be able
1194    to scale the contents in the viewport or not, ie. by zooming.
1195
1196    ViewportAttributes can be set by a web author using the viewport meta tag extension, documented
1197    at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
1198
1199    All values might not be set, as such when dealing with the hints, the developer needs to
1200    check whether the values are valid. Negative values denote an invalid qreal value.
1201
1202    \inmodule QtWebKit
1203*/
1204
1205/*!
1206    Constructs an empty QWebPage::ViewportAttributes.
1207*/
1208QWebPage::ViewportAttributes::ViewportAttributes()
1209    : d(0)
1210    , m_initialScaleFactor(-1.0)
1211    , m_minimumScaleFactor(-1.0)
1212    , m_maximumScaleFactor(-1.0)
1213    , m_devicePixelRatio(-1.0)
1214    , m_isUserScalable(true)
1215    , m_isValid(false)
1216{
1217
1218}
1219
1220/*!
1221    Constructs a QWebPage::ViewportAttributes which is a copy from \a other .
1222*/
1223QWebPage::ViewportAttributes::ViewportAttributes(const QWebPage::ViewportAttributes& other)
1224    : d(other.d)
1225    , m_initialScaleFactor(other.m_initialScaleFactor)
1226    , m_minimumScaleFactor(other.m_minimumScaleFactor)
1227    , m_maximumScaleFactor(other.m_maximumScaleFactor)
1228    , m_devicePixelRatio(other.m_devicePixelRatio)
1229    , m_isUserScalable(other.m_isUserScalable)
1230    , m_isValid(other.m_isValid)
1231    , m_size(other.m_size)
1232{
1233
1234}
1235
1236/*!
1237    Destroys the QWebPage::ViewportAttributes.
1238*/
1239QWebPage::ViewportAttributes::~ViewportAttributes()
1240{
1241
1242}
1243
1244/*!
1245    Assigns the given QWebPage::ViewportAttributes to this viewport hints and returns a
1246    reference to this.
1247*/
1248QWebPage::ViewportAttributes& QWebPage::ViewportAttributes::operator=(const QWebPage::ViewportAttributes& other)
1249{
1250    if (this != &other) {
1251        d = other.d;
1252        m_initialScaleFactor = other.m_initialScaleFactor;
1253        m_minimumScaleFactor = other.m_minimumScaleFactor;
1254        m_maximumScaleFactor = other.m_maximumScaleFactor;
1255        m_isUserScalable = other.m_isUserScalable;
1256        m_isValid = other.m_isValid;
1257        m_size = other.m_size;
1258    }
1259
1260    return *this;
1261}
1262
1263/*! \fn inline bool QWebPage::ViewportAttributes::isValid() const
1264    Returns whether this is a valid ViewportAttributes or not.
1265
1266    An invalid ViewportAttributes will have an empty QSize, negative values for scale factors and
1267    true for the boolean isUserScalable.
1268*/
1269
1270/*! \fn inline QSize QWebPage::ViewportAttributes::size() const
1271    Returns the size of the viewport.
1272*/
1273
1274/*! \fn inline qreal QWebPage::ViewportAttributes::initialScaleFactor() const
1275    Returns the initial scale of the viewport as a multiplier.
1276*/
1277
1278/*! \fn inline qreal QWebPage::ViewportAttributes::minimumScaleFactor() const
1279    Returns the minimum scale value of the viewport as a multiplier.
1280*/
1281
1282/*! \fn inline qreal QWebPage::ViewportAttributes::maximumScaleFactor() const
1283    Returns the maximum scale value of the viewport as a multiplier.
1284*/
1285
1286/*! \fn inline bool QWebPage::ViewportAttributes::isUserScalable() const
1287    Determines whether or not the scale can be modified by the user.
1288*/
1289
1290
1291/*!
1292    \class QWebPage
1293    \since 4.4
1294    \brief The QWebPage class provides an object to view and edit web documents.
1295
1296    \inmodule QtWebKit
1297
1298    QWebPage holds a main frame responsible for web content, settings, the history
1299    of navigated links and actions. This class can be used, together with QWebFrame,
1300    to provide functionality like QWebView in a widget-less environment.
1301
1302    QWebPage's API is very similar to QWebView, as you are still provided with
1303    common functions like action() (known as
1304    \l{QWebView::pageAction()}{pageAction}() in QWebView), triggerAction(),
1305    findText() and settings(). More QWebView-like functions can be found in the
1306    main frame of QWebPage, obtained via the mainFrame() function. For example,
1307    the \l{QWebFrame::load()}{load}(), \l{QWebFrame::setUrl()}{setUrl}() and
1308    \l{QWebFrame::setHtml()}{setHtml}() functions for QWebPage can be accessed
1309    using QWebFrame.
1310
1311    The loadStarted() signal is emitted when the page begins to load.The
1312    loadProgress() signal, on the other hand, is emitted whenever an element
1313    of the web page completes loading, such as an embedded image, a script,
1314    etc. Finally, the loadFinished() signal is emitted when the page contents
1315    are loaded completely, independent of script execution or page rendering.
1316    Its argument, either true or false, indicates whether or not the load
1317    operation succeeded.
1318
1319    \section1 Using QWebPage in a Widget-less Environment
1320
1321    Before you begin painting a QWebPage object, you need to set the size of
1322    the viewport by calling setViewportSize(). Then, you invoke the main
1323    frame's render function (QWebFrame::render()). An example of this
1324    is shown in the code snippet below.
1325
1326    Suppose we have a \c Thumbnail class as follows:
1327
1328    \snippet webkitsnippets/webpage/main.cpp 0
1329
1330    The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1331    object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1332    \c render().
1333
1334    \snippet webkitsnippets/webpage/main.cpp 1
1335
1336    The \c render() function shows how we can paint a thumbnail using a
1337    QWebPage object.
1338
1339    \snippet webkitsnippets/webpage/main.cpp 2
1340
1341    We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1342    then we instantiate a QImage object, \c image, with the same size as our
1343    \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1344    as a parameter to \c painter. Next, we render the contents of the main
1345    frame and its subframes into \c painter. Finally, we save the scaled image.
1346
1347    \sa QWebFrame
1348*/
1349
1350/*!
1351    Constructs an empty QWebPage with parent \a parent.
1352*/
1353QWebPage::QWebPage(QObject *parent)
1354    : QObject(parent)
1355    , d(new QWebPagePrivate(this))
1356{
1357    setView(qobject_cast<QWidget*>(parent));
1358
1359    connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1360#ifndef NDEBUG
1361    connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1362#endif
1363}
1364
1365/*!
1366    Destroys the web page.
1367*/
1368QWebPage::~QWebPage()
1369{
1370    delete d;
1371}
1372
1373/*!
1374    Returns the main frame of the page.
1375
1376    The main frame provides access to the hierarchy of sub-frames and is also needed if you
1377    want to explicitly render a web page into a given painter.
1378
1379    \sa currentFrame()
1380*/
1381QWebFrame *QWebPage::mainFrame() const
1382{
1383    d->createMainFrame();
1384    return d->mainFrame.data();
1385}
1386
1387/*!
1388    Returns the frame currently active.
1389
1390    \sa mainFrame(), frameCreated()
1391*/
1392QWebFrame *QWebPage::currentFrame() const
1393{
1394    d->createMainFrame();
1395    return qobject_cast<QWebFrame*>(d->currentFrame());
1396}
1397
1398
1399/*!
1400    \since 4.6
1401
1402    Returns the frame at the given point \a pos, or 0 if there is no frame at
1403    that position.
1404
1405    \sa mainFrame(), currentFrame()
1406*/
1407QWebFrame* QWebPage::frameAt(const QPoint& pos) const
1408{
1409    QWebFrame* webFrame = mainFrame();
1410    if (!webFrame->geometry().contains(pos))
1411        return 0;
1412    QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
1413    return hitTestResult.frame();
1414}
1415
1416/*!
1417    Returns a pointer to the view's history of navigated web pages.
1418*/
1419QWebHistory *QWebPage::history() const
1420{
1421    d->createMainFrame();
1422    return &d->history;
1423}
1424
1425/*!
1426    Sets the \a view that is associated with the web page.
1427
1428    \sa view()
1429*/
1430void QWebPage::setView(QWidget* view)
1431{
1432    if (this->view() == view)
1433        return;
1434
1435    d->view = view;
1436    setViewportSize(view ? view->size() : QSize(0, 0));
1437
1438    // If we have no client, we install a special client delegating
1439    // the responsibility to the QWidget. This is the code path
1440    // handling a.o. the "legacy" QWebView.
1441    //
1442    // If such a special delegate already exist, we substitute the view.
1443
1444    if (d->client) {
1445        if (d->client->isQWidgetClient())
1446            static_cast<PageClientQWidget*>(d->client.data())->view = view;
1447        return;
1448    }
1449
1450    if (view)
1451        d->client.reset(new PageClientQWidget(view, this));
1452}
1453
1454/*!
1455    Returns the view widget that is associated with the web page.
1456
1457    \sa setView()
1458*/
1459QWidget *QWebPage::view() const
1460{
1461    return d->view.data();
1462}
1463
1464/*!
1465    This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
1466
1467    For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
1468
1469    The default implementation prints nothing.
1470*/
1471void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
1472{
1473    Q_UNUSED(sourceID);
1474
1475    // Catch plugin logDestroy message for LayoutTests/plugins/open-and-close-window-with-plugin.html
1476    // At this point DRT's WebPage has already been destroyed
1477    if (QWebPageAdapter::drtRun) {
1478        if (message == QLatin1String("PLUGIN: NPP_Destroy")) {
1479            fprintf(stdout, "CONSOLE MESSAGE: ");
1480            if (lineNumber)
1481                fprintf(stdout, "line %d: ", lineNumber);
1482            fprintf(stdout, "%s\n", message.toUtf8().constData());
1483        }
1484    }
1485}
1486
1487/*!
1488    This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
1489    the message \a msg.
1490
1491    The default implementation shows the message, \a msg, with QMessageBox::information.
1492*/
1493void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
1494{
1495    Q_UNUSED(frame);
1496#ifndef QT_NO_MESSAGEBOX
1497    QMessageBox box(view());
1498    box.setWindowTitle(tr("JavaScript Alert - %1").arg(mainFrame()->url().host()));
1499    box.setTextFormat(Qt::PlainText);
1500    box.setText(msg);
1501    box.setStandardButtons(QMessageBox::Ok);
1502    box.exec();
1503#endif
1504}
1505
1506/*!
1507    This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
1508    with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
1509
1510    The default implementation executes the query using QMessageBox::information with QMessageBox::Ok and QMessageBox::Cancel buttons.
1511*/
1512bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
1513{
1514    Q_UNUSED(frame);
1515#ifdef QT_NO_MESSAGEBOX
1516    return true;
1517#else
1518    QMessageBox box(view());
1519    box.setWindowTitle(tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()));
1520    box.setTextFormat(Qt::PlainText);
1521    box.setText(msg);
1522    box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1523    return QMessageBox::Ok == box.exec();
1524#endif
1525}
1526
1527/*!
1528    This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
1529    The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
1530
1531    If the prompt was cancelled by the user the implementation should return false; otherwise the
1532    result should be written to \a result and true should be returned. If the prompt was not cancelled by the
1533    user, the implementation should return true and the result string must not be null.
1534
1535    The default implementation uses QInputDialog::getText().
1536*/
1537bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
1538{
1539    Q_UNUSED(frame);
1540    bool ok = false;
1541#ifndef QT_NO_INPUTDIALOG
1542
1543    QInputDialog dlg(view());
1544    dlg.setWindowTitle(tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()));
1545
1546    // Hack to force the dialog's QLabel into plain text mode
1547    // prevents https://bugs.webkit.org/show_bug.cgi?id=34429
1548    QLabel* label = dlg.findChild<QLabel*>();
1549    if (label)
1550        label->setTextFormat(Qt::PlainText);
1551
1552    // double the &'s because single & will underline the following character
1553    // (Accelerator mnemonics)
1554    QString escMsg(msg);
1555    escMsg.replace(QChar::fromLatin1('&'), QLatin1String("&&"));
1556    dlg.setLabelText(escMsg);
1557
1558    dlg.setTextEchoMode(QLineEdit::Normal);
1559    dlg.setTextValue(defaultValue);
1560
1561    ok = !!dlg.exec();
1562
1563    if (ok && result)
1564        *result = dlg.textValue();
1565#endif
1566    return ok;
1567}
1568
1569/*!
1570    \fn bool QWebPage::shouldInterruptJavaScript()
1571    \since 4.6
1572    This function is called when a JavaScript program is running for a long period of time.
1573
1574    If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
1575
1576    The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1577*/
1578bool QWebPage::shouldInterruptJavaScript()
1579{
1580#ifdef QT_NO_MESSAGEBOX
1581    return false;
1582#else
1583    return QMessageBox::Yes == QMessageBox::information(view(), tr("JavaScript Problem - %1").arg(mainFrame()->url().host()), tr("The script on this page appears to have a problem. Do you want to stop the script?"), QMessageBox::Yes, QMessageBox::No);
1584#endif
1585}
1586
1587void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy)
1588{
1589#if !ENABLE(NOTIFICATIONS) && !ENABLE(LEGACY_NOTIFICATIONS) && !ENABLE(GEOLOCATION)
1590    Q_UNUSED(frame);
1591    Q_UNUSED(policy);
1592#endif
1593    switch (feature) {
1594    case Notifications:
1595#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
1596        if (policy != PermissionUnknown)
1597            d->setNotificationsAllowedForFrame(frame->d, (policy == PermissionGrantedByUser));
1598#endif
1599        break;
1600    case Geolocation:
1601#if ENABLE(GEOLOCATION) && HAVE(QTLOCATION)
1602        if (policy != PermissionUnknown)
1603            d->setGeolocationEnabledForFrame(frame->d, (policy == PermissionGrantedByUser));
1604#endif
1605        break;
1606
1607    default:
1608        break;
1609    }
1610}
1611
1612/*!
1613    This function is called whenever WebKit wants to create a new window of the given \a type, for
1614    example when a JavaScript program requests to open a document in a new window.
1615
1616    If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
1617
1618    If the view associated with the web page is a QWebView object, then the default implementation forwards
1619    the request to QWebView's createWindow() function; otherwise it returns a null pointer.
1620
1621    If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
1622
1623    \note In the cases when the window creation is being triggered by JavaScript, apart from
1624    reimplementing this method application must also set the JavaScriptCanOpenWindows attribute
1625    of QWebSettings to true in order for it to get called.
1626
1627    \sa acceptNavigationRequest(), QWebView::createWindow()
1628*/
1629QWebPage *QWebPage::createWindow(WebWindowType type)
1630{
1631    QWebView *webView = qobject_cast<QWebView*>(view());
1632    if (webView) {
1633        QWebView *newView = webView->createWindow(type);
1634        if (newView)
1635            return newView->page();
1636    }
1637    return 0;
1638}
1639
1640/*!
1641    This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is
1642    called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues
1643    correspond to the HTML object element attributes and child elements to configure the embeddable object.
1644*/
1645QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
1646{
1647    Q_UNUSED(classid);
1648    Q_UNUSED(url);
1649    Q_UNUSED(paramNames);
1650    Q_UNUSED(paramValues);
1651    return 0;
1652}
1653
1654/*!
1655 *  Returns the list of all content types supported by QWebPage.
1656 */
1657QStringList QWebPage::supportedContentTypes() const
1658{
1659    return d->supportedContentTypes();
1660}
1661
1662/*!
1663 *  Returns true if QWebPage can handle the given \a mimeType; otherwise, returns false.
1664 */
1665bool QWebPage::supportsContentType(const QString& mimeType) const
1666{
1667    return d->supportsContentType(mimeType);
1668}
1669
1670static void collectChildFrames(QWebFrame* frame, QList<QWebFrame*>& list)
1671{
1672    list << frame->childFrames();
1673    QListIterator<QWebFrame*> it(frame->childFrames());
1674    while (it.hasNext())
1675        collectChildFrames(it.next(), list);
1676}
1677
1678/*!
1679    This function can be called to trigger the specified \a action.
1680    It is also called by Qt WebKit if the user triggers the action, for example
1681    through a context menu item.
1682
1683    If \a action is a checkable action then \a checked specified whether the action
1684    is toggled or not.
1685
1686    \sa action()
1687*/
1688void QWebPage::triggerAction(WebAction action, bool)
1689{
1690    const char *command = 0;
1691    QWebPageAdapter::MenuAction mappedAction = QWebPageAdapter::NoAction;
1692    QWebHitTestResultPrivate* hitTestResult = d->hitTestResult.d;
1693
1694    switch (action) {
1695    case OpenLink:
1696    case OpenLinkInNewWindow:
1697    case OpenLinkInThisWindow:
1698    case OpenFrameInNewWindow:
1699    case CopyLinkToClipboard:
1700    case OpenImageInNewWindow:
1701    case DownloadImageToDisk:
1702    case DownloadLinkToDisk:
1703    case Back:
1704    case Forward:
1705    case Stop:
1706    case Reload:
1707    case SetTextDirectionDefault:
1708    case SetTextDirectionLeftToRight:
1709    case SetTextDirectionRightToLeft:
1710        mappedAction = adapterMenuActionForWebAction(action);
1711        break;
1712    case ReloadAndBypassCache: // Manual mapping
1713        mappedAction = QWebPageAdapter::Reload;
1714        break;
1715#ifndef QT_NO_CLIPBOARD
1716    case CopyImageToClipboard:
1717        QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
1718        break;
1719    case CopyImageUrlToClipboard:
1720        QApplication::clipboard()->setText(d->hitTestResult.imageUrl().toString());
1721        break;
1722#endif
1723    case InspectElement: {
1724#if ENABLE(INSPECTOR)
1725        if (!d->hitTestResult.isNull()) {
1726            d->getOrCreateInspector(); // Make sure the inspector is created
1727            d->inspector->show(); // The inspector is expected to be shown on inspection
1728            mappedAction = QWebPageAdapter::InspectElement;
1729        }
1730#endif
1731        break;
1732    }
1733    case StopScheduledPageRefresh: {
1734        QWebFrame* topFrame = mainFrame();
1735        topFrame->d->cancelLoad();
1736        QList<QWebFrame*> childFrames;
1737        collectChildFrames(topFrame, childFrames);
1738        QListIterator<QWebFrame*> it(childFrames);
1739        while (it.hasNext())
1740            it.next()->d->cancelLoad();
1741        break;
1742    }
1743    default:
1744        command = QWebPagePrivate::editorCommandForWebActions(action);
1745        break;
1746    }
1747    if (command || mappedAction != QWebPageAdapter::NoAction)
1748        d->triggerAction(mappedAction, hitTestResult, command, /*endToEndReload*/ action == ReloadAndBypassCache);
1749}
1750
1751
1752QColor QWebPagePrivate::colorSelectionRequested(const QColor &selectedColor)
1753{
1754    QColor ret = selectedColor;
1755#ifndef QT_NO_COLORDIALOG
1756    ret = QColorDialog::getColor(selectedColor, q->view());
1757    if (!ret.isValid())
1758        ret = selectedColor;
1759#endif
1760    return ret;
1761}
1762
1763QWebSelectMethod *QWebPagePrivate::createSelectPopup()
1764{
1765    return new QtFallbackWebPopup(this);
1766}
1767
1768QRect QWebPagePrivate::viewRectRelativeToWindow()
1769{
1770
1771    QWidget* ownerWidget= client.isNull() ? 0 : qobject_cast<QWidget*>(client->ownerWidget());
1772    if (!ownerWidget)
1773        return QRect();
1774    QWidget* topLevelWidget = ownerWidget->window();
1775
1776    QPoint topLeftCorner = ownerWidget->mapFrom(topLevelWidget, QPoint(0, 0));
1777    return QRect(topLeftCorner, ownerWidget->size());
1778}
1779
1780void QWebPagePrivate::geolocationPermissionRequested(QWebFrameAdapter* frame)
1781{
1782    emit q->featurePermissionRequested(QWebFramePrivate::kit(frame), QWebPage::Geolocation);
1783}
1784
1785void QWebPagePrivate::geolocationPermissionRequestCancelled(QWebFrameAdapter* frame)
1786{
1787    emit q->featurePermissionRequestCanceled(QWebFramePrivate::kit(frame), QWebPage::Geolocation);
1788}
1789
1790void QWebPagePrivate::notificationsPermissionRequested(QWebFrameAdapter* frame)
1791{
1792    emit q->featurePermissionRequested(QWebFramePrivate::kit(frame), QWebPage::Notifications);
1793}
1794
1795void QWebPagePrivate::notificationsPermissionRequestCancelled(QWebFrameAdapter* frame)
1796{
1797    emit q->featurePermissionRequestCanceled(QWebFramePrivate::kit(frame), QWebPage::Notifications);
1798}
1799
1800void QWebPagePrivate::respondToChangedContents()
1801{
1802    updateEditorActions();
1803
1804    emit q->contentsChanged();
1805}
1806
1807void QWebPagePrivate::respondToChangedSelection()
1808{
1809    updateEditorActions();
1810    emit q->selectionChanged();
1811}
1812
1813void QWebPagePrivate::microFocusChanged()
1814{
1815    emit q->microFocusChanged();
1816}
1817
1818void QWebPagePrivate::triggerCopyAction()
1819{
1820    q->triggerAction(QWebPage::Copy);
1821}
1822
1823void QWebPagePrivate::triggerActionForKeyEvent(QKeyEvent* event)
1824{
1825    QWebPage::WebAction action = editorActionForKeyEvent(event);
1826    q->triggerAction(action);
1827}
1828
1829void QWebPagePrivate::clearUndoStack()
1830{
1831#ifndef QT_NO_UNDOSTACK
1832    if (undoStack)
1833        undoStack->clear();
1834#endif
1835}
1836
1837bool QWebPagePrivate::canUndo() const
1838{
1839#ifndef QT_NO_UNDOSTACK
1840    if (!undoStack)
1841        return false;
1842    return undoStack->canUndo();
1843#else
1844    return false;
1845#endif
1846}
1847
1848bool QWebPagePrivate::canRedo() const
1849{
1850#ifndef QT_NO_UNDOSTACK
1851    if (!undoStack)
1852        return false;
1853    return undoStack->canRedo();
1854#else
1855    return false;
1856#endif
1857}
1858
1859void QWebPagePrivate::undo()
1860{
1861#ifndef QT_NO_UNDOSTACK
1862    if (undoStack)
1863        undoStack->undo();
1864#endif
1865}
1866
1867void QWebPagePrivate::redo()
1868{
1869#ifndef QT_NO_UNDOSTACK
1870    if (undoStack)
1871        undoStack->redo();
1872#endif
1873}
1874
1875void QWebPagePrivate::createUndoStep(QSharedPointer<UndoStepQt> step)
1876{
1877#ifndef QT_NO_UNDOSTACK
1878    // Call undoStack() getter first to ensure stack is created
1879    // if it doesn't exist yet.
1880    q->undoStack()->push(new QWebUndoCommand(step));
1881#endif
1882}
1883
1884const char *QWebPagePrivate::editorCommandForKeyEvent(QKeyEvent* event)
1885{
1886    QWebPage::WebAction action = editorActionForKeyEvent(event);
1887    return editorCommandForWebActions(action);
1888}
1889
1890QSize QWebPage::viewportSize() const
1891{
1892    if (d->mainFrame && d->mainFrame.data()->d->hasView())
1893        return d->mainFrame.data()->d->frameRect().size();
1894
1895    return d->m_viewportSize;
1896}
1897
1898/*!
1899    \property QWebPage::viewportSize
1900    \brief the size of the viewport
1901
1902    The size affects for example the visibility of scrollbars
1903    if the document is larger than the viewport.
1904
1905    By default, for a newly-created Web page, this property contains a size with
1906    zero width and height.
1907
1908    \sa QWebFrame::render(), preferredContentsSize
1909*/
1910void QWebPage::setViewportSize(const QSize &size) const
1911{
1912    d->m_viewportSize = size;
1913
1914    QWebFrameAdapter* mainFrame = d->mainFrameAdapter();
1915    if (!mainFrame->hasView())
1916        return;
1917
1918    mainFrame->setViewportSize(size);
1919}
1920
1921static int getintenv(const char* variable)
1922{
1923    bool ok;
1924    int value = qgetenv(variable).toInt(&ok);
1925    return (ok) ? value : -1;
1926}
1927
1928static QSize queryDeviceSizeForScreenContainingWidget(const QWidget* widget)
1929{
1930    QDesktopWidget* desktop = QApplication::desktop();
1931    if (!desktop)
1932        return QSize();
1933
1934    QSize size;
1935
1936    if (widget) {
1937        // Returns the available geometry of the screen which contains widget.
1938        // NOTE: this must be the the full screen size including any fixed status areas etc.
1939        size = desktop->availableGeometry(widget).size();
1940    } else
1941        size = desktop->availableGeometry().size();
1942
1943    // This must be in portrait mode, adjust if not.
1944    if (size.width() > size.height()) {
1945        int width = size.width();
1946        size.setWidth(size.height());
1947        size.setHeight(width);
1948    }
1949
1950    return size;
1951}
1952
1953/*!
1954    Computes the optimal viewport configuration given the \a availableSize, when
1955    user interface components are disregarded.
1956
1957    The configuration is also dependent on the device screen size which is obtained
1958    automatically. For testing purposes the size can be overridden by setting two
1959    environment variables QTWEBKIT_DEVICE_WIDTH and QTWEBKIT_DEVICE_HEIGHT, which
1960    both needs to be set.
1961
1962    The ViewportAttributes includes a pixel density ratio, which will also be exposed to
1963    the web author though the -webkit-pixel-ratio media feature. This is the ratio
1964    between 1 density-independent pixel (DPI) and physical pixels.
1965
1966    A density-independent pixel is equivalent to one physical pixel on a 160 DPI screen,
1967    so on our platform assumes that as the baseline density.
1968
1969    The conversion of DIP units to screen pixels is quite simple:
1970
1971    pixels = DIPs * (density / 160).
1972
1973    Thus, on a 240 DPI screen, 1 DIPs would equal 1.5 physical pixels.
1974
1975    An invalid instance will be returned in the case an empty size is passed to the
1976    method.
1977
1978    \note The density is automatically obtained from the DPI of the screen where the page
1979    is being shown, but as many X11 servers are reporting wrong DPI, it is possible to
1980    override it using QX11Info::setAppDpiY().
1981*/
1982
1983QWebPage::ViewportAttributes QWebPage::viewportAttributesForSize(const QSize& availableSize) const
1984{
1985    ViewportAttributes result;
1986
1987    if (availableSize.isEmpty())
1988        return result; // Returns an invalid instance.
1989
1990    QSize deviceSize(getintenv("QTWEBKIT_DEVICE_WIDTH"), getintenv("QTWEBKIT_DEVICE_HEIGHT"));
1991
1992    // Both environment variables need to be set - or they will be ignored.
1993    if (deviceSize.isNull())
1994        deviceSize = queryDeviceSizeForScreenContainingWidget(view());
1995    QWebPageAdapter::ViewportAttributes attr = d->viewportAttributesForSize(availableSize, deviceSize);
1996
1997    result.m_isValid = true;
1998    result.m_size = attr.size;
1999    result.m_initialScaleFactor = attr.initialScaleFactor;
2000    result.m_minimumScaleFactor = attr.minimumScaleFactor;
2001    result.m_maximumScaleFactor = attr.maximumScaleFactor;
2002    result.m_devicePixelRatio = attr.devicePixelRatio;
2003    result.m_isUserScalable = attr.isUserScalable;
2004
2005    return result;
2006}
2007
2008QSize QWebPage::preferredContentsSize() const
2009{
2010    QWebFrameAdapter* mainFrame = d->mainFrame ? d->mainFrame->d : 0;
2011    QSize customSize;
2012    if (mainFrame && mainFrame->hasView())
2013        customSize = mainFrame->customLayoutSize();
2014
2015    return customSize.isNull() ? d->fixedLayoutSize : customSize;
2016}
2017
2018/*!
2019    \property QWebPage::preferredContentsSize
2020    \since 4.6
2021    \brief a custom size used for laying out the page contents.
2022
2023    By default all pages are laid out using the viewport of the page as the base.
2024
2025    As pages mostly are designed for desktop usage, they often do not layout properly
2026    on small devices as the contents require a certain view width. For this reason
2027    it is common to use a different layout size and then scale the contents to fit
2028    within the actual view.
2029
2030    If this property is set to a valid size, this size is used for all layout needs
2031    instead of the size of the viewport.
2032
2033    Setting an invalid size, makes the page fall back to using the viewport size for layout.
2034
2035    \sa viewportSize
2036*/
2037void QWebPage::setPreferredContentsSize(const QSize& size) const
2038{
2039    // FIXME: Rename this method to setCustomLayoutSize
2040
2041    d->fixedLayoutSize = size;
2042
2043    QWebFrameAdapter* mainFrame = d->mainFrameAdapter();
2044    if (!mainFrame->hasView())
2045        return;
2046
2047    mainFrame->setCustomLayoutSize(size);
2048}
2049
2050/*
2051    This function is to be called after any (animated) scroll/pan has ended, in the case the application handles the
2052    scrolling/panning of the web contents. This is commonly used in combination with tiling where is it common for
2053    the application to pan the actual view, which then resizes itself to the size of the contents.
2054
2055    \note Calling this function makes WebKit stop trying to calculate the visibleContentRect. To turn that on
2056    again, call this method with an empty rect.
2057
2058    \sa QGraphicsWebView::resizesToContents, QWebSettings::TiledBackingStoreEnabled
2059*/
2060void QWebPage::setActualVisibleContentRect(const QRect& rect) const
2061{
2062    QWebFrameAdapter* mainFrame = d->mainFrameAdapter();
2063    if (!mainFrame->hasView())
2064        return;
2065
2066    mainFrame->setFixedVisibleContentRect(rect);
2067}
2068
2069/*!
2070    \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2071
2072    This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
2073    the specified navigation type \a type.
2074
2075    If \a frame is a null pointer then navigation to a new window is requested. If the request is
2076    accepted createWindow() will be called.
2077
2078    The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
2079    to let QWebPage handle the navigation itself.
2080
2081    \sa createWindow()
2082*/
2083bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2084{
2085    Q_UNUSED(frame);
2086    if (type == NavigationTypeLinkClicked) {
2087        switch (d->linkPolicy) {
2088        case DontDelegateLinks:
2089            return true;
2090
2091        case DelegateExternalLinks:
2092            if (QWebPageAdapter::treatSchemeAsLocal(request.url().scheme()))
2093                return true;
2094            emit linkClicked(request.url());
2095            return false;
2096
2097        case DelegateAllLinks:
2098            emit linkClicked(request.url());
2099            return false;
2100        }
2101    }
2102    return true;
2103}
2104
2105/*!
2106    \property QWebPage::hasSelection
2107    \brief whether this page contains selected content or not.
2108
2109    \sa selectionChanged()
2110*/
2111bool QWebPage::hasSelection() const
2112{
2113    d->createMainFrame();
2114    return d->hasSelection();
2115}
2116
2117/*!
2118    \property QWebPage::selectedText
2119    \brief the text currently selected
2120
2121    By default, this property contains an empty string.
2122
2123    \sa selectionChanged(), selectedHtml()
2124*/
2125QString QWebPage::selectedText() const
2126{
2127    d->createMainFrame();
2128    return d->selectedText();
2129}
2130
2131/*!
2132    \since 4.8
2133    \property QWebPage::selectedHtml
2134    \brief the HTML currently selected
2135
2136    By default, this property contains an empty string.
2137
2138    \sa selectionChanged(), selectedText()
2139*/
2140QString QWebPage::selectedHtml() const
2141{
2142    d->createMainFrame();
2143    return d->selectedHtml();
2144}
2145
2146#ifndef QT_NO_ACTION
2147/*!
2148   Returns a QAction for the specified WebAction \a action.
2149
2150   The action is owned by the QWebPage but you can customize the look by
2151   changing its properties.
2152
2153   QWebPage also takes care of implementing the action, so that upon
2154   triggering the corresponding action is performed on the page.
2155
2156   \sa triggerAction()
2157*/
2158QAction *QWebPage::action(WebAction action) const
2159{
2160    if (action == QWebPage::NoWebAction)
2161        return 0;
2162    if (d->actions[action])
2163        return d->actions[action];
2164
2165    QString text;
2166    QIcon icon;
2167    QStyle *style = d->client ? d->client->style() : qApp->style();
2168    bool checkable = false;
2169    QWebPageAdapter::MenuAction mappedAction = QWebPageAdapter::NoAction;
2170
2171    switch (action) {
2172    // to be fetched from LocalizedStringsQt via the page adapter
2173    case OpenLink:
2174    case OpenLinkInNewWindow:
2175    case OpenFrameInNewWindow:
2176    case OpenLinkInThisWindow:
2177    case DownloadLinkToDisk:
2178    case CopyLinkToClipboard:
2179    case OpenImageInNewWindow:
2180    case DownloadImageToDisk:
2181    case CopyImageToClipboard:
2182    case CopyImageUrlToClipboard:
2183    case Cut:
2184    case Copy:
2185    case Paste:
2186    case SelectAll:
2187    case SetTextDirectionDefault:
2188    case SetTextDirectionLeftToRight:
2189    case SetTextDirectionRightToLeft:
2190    case ToggleBold:
2191    case ToggleItalic:
2192    case ToggleUnderline:
2193        mappedAction = adapterMenuActionForWebAction(action);
2194        break;
2195    case InspectElement:
2196#if ENABLE(INSPECTOR)
2197        mappedAction = QWebPageAdapter::InspectElement;
2198#endif
2199        break;
2200
2201        // icon needed as well, map by hand.
2202    case Back:
2203        mappedAction = QWebPageAdapter::Back;
2204        icon = style->standardIcon(QStyle::SP_ArrowBack);
2205        break;
2206    case Forward:
2207        mappedAction = QWebPageAdapter::Forward;
2208        icon = style->standardIcon(QStyle::SP_ArrowForward);
2209        break;
2210    case Stop:
2211        mappedAction = QWebPageAdapter::Stop;
2212        icon = style->standardIcon(QStyle::SP_BrowserStop);
2213        break;
2214    case Reload:
2215        mappedAction = QWebPageAdapter::Reload;
2216        icon = style->standardIcon(QStyle::SP_BrowserReload);
2217        break;
2218
2219#ifndef QT_NO_UNDOSTACK
2220    case Undo: {
2221        QAction *a = undoStack()->createUndoAction(d->q);
2222        d->actions[action] = a;
2223        return a;
2224    }
2225    case Redo: {
2226        QAction *a = undoStack()->createRedoAction(d->q);
2227        d->actions[action] = a;
2228        return a;
2229    }
2230#endif // QT_NO_UNDOSTACK
2231        // in place l10n
2232        case MoveToNextChar:
2233            text = tr("Move the cursor to the next character");
2234            break;
2235        case MoveToPreviousChar:
2236            text = tr("Move the cursor to the previous character");
2237            break;
2238        case MoveToNextWord:
2239            text = tr("Move the cursor to the next word");
2240            break;
2241        case MoveToPreviousWord:
2242            text = tr("Move the cursor to the previous word");
2243            break;
2244        case MoveToNextLine:
2245            text = tr("Move the cursor to the next line");
2246            break;
2247        case MoveToPreviousLine:
2248            text = tr("Move the cursor to the previous line");
2249            break;
2250        case MoveToStartOfLine:
2251            text = tr("Move the cursor to the start of the line");
2252            break;
2253        case MoveToEndOfLine:
2254            text = tr("Move the cursor to the end of the line");
2255            break;
2256        case MoveToStartOfBlock:
2257            text = tr("Move the cursor to the start of the block");
2258            break;
2259        case MoveToEndOfBlock:
2260            text = tr("Move the cursor to the end of the block");
2261            break;
2262        case MoveToStartOfDocument:
2263            text = tr("Move the cursor to the start of the document");
2264            break;
2265        case MoveToEndOfDocument:
2266            text = tr("Move the cursor to the end of the document");
2267            break;
2268        case SelectNextChar:
2269            text = tr("Select to the next character");
2270            break;
2271        case SelectPreviousChar:
2272            text = tr("Select to the previous character");
2273            break;
2274        case SelectNextWord:
2275            text = tr("Select to the next word");
2276            break;
2277        case SelectPreviousWord:
2278            text = tr("Select to the previous word");
2279            break;
2280        case SelectNextLine:
2281            text = tr("Select to the next line");
2282            break;
2283        case SelectPreviousLine:
2284            text = tr("Select to the previous line");
2285            break;
2286        case SelectStartOfLine:
2287            text = tr("Select to the start of the line");
2288            break;
2289        case SelectEndOfLine:
2290            text = tr("Select to the end of the line");
2291            break;
2292        case SelectStartOfBlock:
2293            text = tr("Select to the start of the block");
2294            break;
2295        case SelectEndOfBlock:
2296            text = tr("Select to the end of the block");
2297            break;
2298        case SelectStartOfDocument:
2299            text = tr("Select to the start of the document");
2300            break;
2301        case SelectEndOfDocument:
2302            text = tr("Select to the end of the document");
2303            break;
2304        case DeleteStartOfWord:
2305            text = tr("Delete to the start of the word");
2306            break;
2307        case DeleteEndOfWord:
2308            text = tr("Delete to the end of the word");
2309            break;
2310
2311        case InsertParagraphSeparator:
2312            text = tr("Insert a new paragraph");
2313            break;
2314        case InsertLineSeparator:
2315            text = tr("Insert a new line");
2316            break;
2317
2318        case PasteAndMatchStyle:
2319            text = tr("Paste and Match Style");
2320            break;
2321        case RemoveFormat:
2322            text = tr("Remove formatting");
2323            break;
2324
2325        case ToggleStrikethrough:
2326            text = tr("Strikethrough");
2327            checkable = true;
2328            break;
2329        case ToggleSubscript:
2330            text = tr("Subscript");
2331            checkable = true;
2332            break;
2333        case ToggleSuperscript:
2334            text = tr("Superscript");
2335            checkable = true;
2336            break;
2337        case InsertUnorderedList:
2338            text = tr("Insert Bulleted List");
2339            checkable = true;
2340            break;
2341        case InsertOrderedList:
2342            text = tr("Insert Numbered List");
2343            checkable = true;
2344            break;
2345        case Indent:
2346            text = tr("Indent");
2347            break;
2348        case Outdent:
2349            text = tr("Outdent");
2350            break;
2351        case AlignCenter:
2352            text = tr("Center");
2353            break;
2354        case AlignJustified:
2355            text = tr("Justify");
2356            break;
2357        case AlignLeft:
2358            text = tr("Align Left");
2359            break;
2360        case AlignRight:
2361            text = tr("Align Right");
2362            break;
2363        case NoWebAction:
2364            return 0;
2365        default:
2366            break;
2367    }
2368    if (mappedAction != QWebPageAdapter::NoAction)
2369        text = d->contextMenuItemTagForAction(mappedAction, &checkable);
2370
2371    if (text.isEmpty())
2372        return 0;
2373
2374    QAction *a = new QAction(d->q);
2375    a->setText(text);
2376    a->setData(action);
2377    a->setCheckable(checkable);
2378    a->setIcon(icon);
2379
2380    connect(a, SIGNAL(triggered(bool)),
2381        this, SLOT(_q_webActionTriggered(bool)));
2382
2383    d->actions[action] = a;
2384    d->updateAction(action);
2385    return a;
2386}
2387#endif // QT_NO_ACTION
2388
2389/*!
2390    \property QWebPage::modified
2391    \brief whether the page contains unsubmitted form data, or the contents have been changed.
2392
2393    By default, this property is false.
2394
2395    \sa contentsChanged(), contentEditable, undoStack()
2396*/
2397bool QWebPage::isModified() const
2398{
2399#ifdef QT_NO_UNDOSTACK
2400    return false;
2401#else
2402    if (!d->undoStack)
2403        return false;
2404    return d->undoStack->canUndo();
2405#endif // QT_NO_UNDOSTACK
2406}
2407
2408#ifndef QT_NO_UNDOSTACK
2409/*!
2410    Returns a pointer to the undo stack used for editable content.
2411
2412    \sa modified
2413*/
2414QUndoStack *QWebPage::undoStack() const
2415{
2416    if (!d->undoStack)
2417        d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
2418
2419    return d->undoStack;
2420}
2421#endif // QT_NO_UNDOSTACK
2422
2423/*! \reimp
2424*/
2425bool QWebPage::event(QEvent *ev)
2426{
2427    switch (ev->type()) {
2428    case QEvent::Timer:
2429        d->timerEvent(static_cast<QTimerEvent*>(ev));
2430        break;
2431    case QEvent::MouseMove:
2432        d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
2433        break;
2434    case QEvent::MouseButtonPress:
2435        d->mousePressEvent(static_cast<QMouseEvent*>(ev));
2436        break;
2437    case QEvent::MouseButtonDblClick:
2438        d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
2439        break;
2440    case QEvent::MouseButtonRelease:
2441        d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
2442        break;
2443#if !defined(QT_NO_GRAPHICSVIEW)
2444    case QEvent::GraphicsSceneMouseMove: {
2445        QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
2446        QMouseEvent dummyEvent(QEvent::MouseMove, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
2447        d->mouseMoveEvent(&dummyEvent);
2448        ev->setAccepted(dummyEvent.isAccepted());
2449        break;
2450    }
2451    case QEvent::GraphicsSceneMouseRelease: {
2452        QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
2453        QMouseEvent dummyEvent(QEvent::MouseButtonRelease, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
2454        d->adjustPointForClicking(&dummyEvent);
2455        d->mouseReleaseEvent(&dummyEvent);
2456        ev->setAccepted(dummyEvent.isAccepted());
2457        break;
2458    }
2459    case QEvent::GraphicsSceneMousePress: {
2460        QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
2461        QMouseEvent dummyEvent(QEvent::MouseButtonPress, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
2462        d->adjustPointForClicking(&dummyEvent);
2463        d->mousePressEvent(&dummyEvent);
2464        ev->setAccepted(dummyEvent.isAccepted());
2465        break;
2466    }
2467    case QEvent::GraphicsSceneMouseDoubleClick: {
2468        QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
2469        QMouseEvent dummyEvent(QEvent::MouseButtonDblClick, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
2470        d->adjustPointForClicking(&dummyEvent);
2471        d->mouseDoubleClickEvent(&dummyEvent);
2472        ev->setAccepted(dummyEvent.isAccepted());
2473        break;
2474    }
2475#endif
2476#ifndef QT_NO_CONTEXTMENU
2477    case QEvent::ContextMenu:
2478        d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos());
2479        break;
2480#if !defined(QT_NO_GRAPHICSVIEW)
2481    case QEvent::GraphicsSceneContextMenu:
2482        d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos());
2483        break;
2484#endif
2485#endif
2486#ifndef QT_NO_WHEELEVENT
2487    case QEvent::Wheel:
2488        d->wheelEvent(static_cast<QWheelEvent*>(ev), QApplication::wheelScrollLines());
2489        break;
2490#if !defined(QT_NO_GRAPHICSVIEW)
2491    case QEvent::GraphicsSceneWheel: {
2492        QGraphicsSceneWheelEvent *gsEv = static_cast<QGraphicsSceneWheelEvent*>(ev);
2493        QWheelEvent dummyEvent(gsEv->pos(), gsEv->screenPos(), gsEv->delta(), gsEv->buttons(), gsEv->modifiers(), gsEv->orientation());
2494        d->wheelEvent(&dummyEvent, QApplication::wheelScrollLines());
2495        ev->setAccepted(dummyEvent.isAccepted());
2496        break;
2497    }
2498#endif
2499#endif
2500    case QEvent::KeyPress:
2501        d->keyPressEvent(static_cast<QKeyEvent*>(ev));
2502        break;
2503    case QEvent::KeyRelease:
2504        d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
2505        break;
2506    case QEvent::FocusIn:
2507        d->focusInEvent(static_cast<QFocusEvent*>(ev));
2508        break;
2509    case QEvent::FocusOut:
2510        d->focusOutEvent(static_cast<QFocusEvent*>(ev));
2511        break;
2512#ifndef QT_NO_DRAGANDDROP
2513    case QEvent::DragEnter:
2514        d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
2515        break;
2516    case QEvent::DragLeave:
2517        d->dragLeaveEvent();
2518        ev->accept();
2519        break;
2520    case QEvent::DragMove:
2521        d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
2522        break;
2523    case QEvent::Drop:
2524        d->dropEvent(static_cast<QDropEvent*>(ev));
2525        break;
2526#if !defined(QT_NO_GRAPHICSVIEW)
2527    case QEvent::GraphicsSceneDragEnter:
2528        d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2529        break;
2530    case QEvent::GraphicsSceneDragMove:
2531        d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2532        break;
2533    case QEvent::GraphicsSceneDragLeave:
2534        d->dragLeaveEvent();
2535        ev->accept();
2536        break;
2537    case QEvent::GraphicsSceneDrop:
2538        d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2539        break;
2540#endif
2541
2542#endif
2543    case QEvent::InputMethod:
2544        d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
2545        break;
2546    case QEvent::ShortcutOverride:
2547        d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
2548        break;
2549    case QEvent::Leave:
2550        d->leaveEvent(ev);
2551        break;
2552    case QEvent::TouchBegin:
2553    case QEvent::TouchUpdate:
2554    case QEvent::TouchEnd:
2555    case QEvent::TouchCancel:
2556        // Return whether the default action was cancelled in the JS event handler
2557        return d->touchEvent(static_cast<QTouchEvent*>(ev));
2558#ifndef QT_NO_GESTURES
2559    case QEvent::Gesture:
2560        d->gestureEvent(static_cast<QGestureEvent*>(ev));
2561        break;
2562#endif
2563#ifndef QT_NO_PROPERTIES
2564    case QEvent::DynamicPropertyChange:
2565        d->dynamicPropertyChangeEvent(this, static_cast<QDynamicPropertyChangeEvent*>(ev));
2566        break;
2567#endif
2568    default:
2569        return QObject::event(ev);
2570    }
2571
2572    return true;
2573}
2574
2575/*!
2576    Similar to QWidget::focusNextPrevChild() it focuses the next focusable web element
2577    if \a next is true; otherwise the previous element is focused.
2578
2579    Returns true if it can find a new focusable element, or false if it can't.
2580*/
2581bool QWebPage::focusNextPrevChild(bool next)
2582{
2583    QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
2584    d->keyPressEvent(&ev);
2585    return d->hasFocusedNode();
2586}
2587
2588/*!
2589    \property QWebPage::contentEditable
2590    \brief whether the content in this QWebPage is editable or not
2591    \since 4.5
2592
2593    If this property is enabled the contents of the page can be edited by the user through a visible
2594    cursor. If disabled (the default) only HTML elements in the web page with their
2595    \c{contenteditable} attribute set are editable.
2596
2597    \sa modified, contentsChanged(), WebAction
2598*/
2599void QWebPage::setContentEditable(bool editable)
2600{
2601    if (isContentEditable() != editable) {
2602        d->setContentEditable(editable);
2603        d->updateEditorActions();
2604    }
2605}
2606
2607bool QWebPage::isContentEditable() const
2608{
2609    return d->isContentEditable();
2610}
2611
2612/*!
2613    \property QWebPage::forwardUnsupportedContent
2614    \brief whether QWebPage should forward unsupported content
2615
2616    If enabled, the unsupportedContent() signal is emitted with a network reply that
2617    can be used to read the content.
2618
2619    If disabled, the download of such content is aborted immediately.
2620
2621    By default unsupported content is not forwarded.
2622*/
2623
2624void QWebPage::setForwardUnsupportedContent(bool forward)
2625{
2626    d->forwardUnsupportedContent = forward;
2627}
2628
2629bool QWebPage::forwardUnsupportedContent() const
2630{
2631    return d->forwardUnsupportedContent;
2632}
2633
2634/*!
2635    \property QWebPage::linkDelegationPolicy
2636    \brief how QWebPage should delegate the handling of links through the
2637    linkClicked() signal
2638
2639    The default is to delegate no links.
2640*/
2641
2642void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
2643{
2644    d->linkPolicy = policy;
2645}
2646
2647QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
2648{
2649    return d->linkPolicy;
2650}
2651
2652#ifndef QT_NO_CONTEXTMENU
2653
2654bool QWebPagePrivate::handleScrollbarContextMenuEvent(QContextMenuEvent* event, bool horizontal, QWebPageAdapter::ScrollDirection* direction, QWebPageAdapter::ScrollGranularity* granularity)
2655{
2656    if (!QApplication::style()->styleHint(QStyle::SH_ScrollBar_ContextMenu))
2657        return false;
2658
2659    QMenu menu;
2660    QAction* actScrollHere = menu.addAction(QCoreApplication::translate("QWebPage", "Scroll here"));
2661    menu.addSeparator();
2662
2663    QAction* actScrollTop = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Left edge") : QCoreApplication::translate("QWebPage", "Top"));
2664    QAction* actScrollBottom = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Right edge") : QCoreApplication::translate("QWebPage", "Bottom"));
2665    menu.addSeparator();
2666
2667    QAction* actPageUp = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Page left") : QCoreApplication::translate("QWebPage", "Page up"));
2668    QAction* actPageDown = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Page right") : QCoreApplication::translate("QWebPage", "Page down"));
2669    menu.addSeparator();
2670
2671    QAction* actScrollUp = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Scroll left") : QCoreApplication::translate("QWebPage", "Scroll up"));
2672    QAction* actScrollDown = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Scroll right") : QCoreApplication::translate("QWebPage", "Scroll down"));
2673
2674    QAction* actionSelected = menu.exec(event->globalPos());
2675
2676    if (actionSelected == actScrollHere)
2677        return true;
2678    if (actionSelected == actScrollTop) {
2679        *direction = horizontal ? ScrollLeft : ScrollUp;
2680        *granularity = ScrollByDocument;
2681    } else if (actionSelected == actScrollBottom) {
2682        *direction =horizontal ? ScrollRight : ScrollDown;
2683        *granularity = ScrollByDocument;
2684    } else if (actionSelected == actPageUp) {
2685        *direction = horizontal ? ScrollLeft : ScrollUp;
2686        *granularity = ScrollByPage;
2687    } else if (actionSelected == actPageDown) {
2688        *direction =horizontal ? ScrollRight : ScrollDown;
2689        *granularity = ScrollByPage;
2690    } else if (actionSelected == actScrollUp) {
2691        *direction = horizontal ? ScrollLeft : ScrollUp;
2692        *granularity = ScrollByLine;
2693    } else if (actionSelected == actScrollDown) {
2694        *direction =horizontal ? ScrollRight : ScrollDown;
2695        *granularity = ScrollByLine;
2696    }
2697    return true;
2698}
2699
2700/*!
2701    Filters the context menu event, \a event, through handlers for scrollbars and
2702    custom event handlers in the web page. Returns true if the event was handled;
2703    otherwise false.
2704
2705    A web page may swallow a context menu event through a custom event handler, allowing for context
2706    menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
2707    Maps}, for example.
2708*/
2709bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
2710{
2711    QWebFrame* webFrame = frameAt(event->pos());
2712    return d->swallowContextMenuEvent(event, webFrame ? webFrame->d : 0);
2713}
2714#endif // QT_NO_CONTEXTMENU
2715
2716/*!
2717    Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
2718    element the CopyImageToClipboard action is enabled.
2719*/
2720void QWebPage::updatePositionDependentActions(const QPoint &pos)
2721{
2722#ifndef QT_NO_ACTION
2723    // First we disable all actions, but keep track of which ones were originally enabled.
2724    QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
2725    for (int i = QWebPageAdapter::NoAction + 1; i < QWebPageAdapter::ActionCount; ++i) {
2726        QWebPage::WebAction action = webActionForAdapterMenuAction(QWebPageAdapter::MenuAction(i));
2727        if (QAction *a = this->action(action)) {
2728            originallyEnabledWebActions.setBit(action, a->isEnabled());
2729            a->setEnabled(false);
2730        }
2731    }
2732#endif // QT_NO_ACTION
2733
2734    QBitArray visitedWebActions(QWebPage::WebActionCount);
2735    d->createMainFrame();
2736    // Then we let updatePositionDependantMenuActions() enable the actions that are put into the menu
2737    QWebHitTestResultPrivate* result = d->updatePositionDependentMenuActions(pos, &visitedWebActions);
2738    if (!result)
2739        d->hitTestResult = QWebHitTestResult();
2740    else
2741        d->hitTestResult = QWebHitTestResult(result);
2742
2743#ifndef QT_NO_ACTION
2744    // Finally, we restore the original enablement for the actions that were not put into the menu.
2745    originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
2746    for (int i = 0; i < QWebPage::WebActionCount; ++i) {
2747        if (originallyEnabledWebActions.at(i)) {
2748            if (QAction *a = this->action(QWebPage::WebAction(i)))
2749                a->setEnabled(true);
2750        }
2751    }
2752#endif // QT_NO_ACTION
2753
2754    // This whole process ensures that any actions put into to the context menu has the right
2755    // enablement, while also keeping the correct enablement for actions that were left out of
2756    // the menu.
2757
2758}
2759
2760
2761
2762/*!
2763    \enum QWebPage::Extension
2764
2765    This enum describes the types of extensions that the page can support. Before using these extensions, you
2766    should verify that the extension is supported by calling supportsExtension().
2767
2768    \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection.
2769    This extension is invoked when the web content requests one or more file names, for example
2770    as a result of the user clicking on a "file upload" button in a HTML form where multiple
2771    file selection is allowed.
2772
2773    \value ErrorPageExtension Whether the web page can provide an error page when loading fails.
2774    (introduced in Qt 4.6)
2775
2776    \sa ChooseMultipleFilesExtensionOption, ChooseMultipleFilesExtensionReturn, ErrorPageExtensionOption, ErrorPageExtensionReturn
2777*/
2778
2779/*!
2780    \enum QWebPage::ErrorDomain
2781    \since 4.6
2782
2783    This enum describes the domain of an ErrorPageExtensionOption object (i.e. the layer in which the error occurred).
2784
2785    \value QtNetwork The error occurred in the QtNetwork layer; the error code is of type QNetworkReply::NetworkError.
2786    \value Http The error occurred in the HTTP layer; the error code is a HTTP status code (see QNetworkRequest::HttpStatusCodeAttribute).
2787    \value WebKit The error is an internal WebKit error.
2788*/
2789
2790/*!
2791    \class QWebPage::ExtensionOption
2792    \since 4.4
2793    \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
2794
2795    \inmodule QtWebKit
2796
2797    \sa QWebPage::extension(), QWebPage::ExtensionReturn
2798*/
2799
2800
2801/*!
2802    \class QWebPage::ExtensionReturn
2803    \since 4.4
2804    \brief The ExtensionReturn class provides an output result from a QWebPage's extension.
2805
2806    \inmodule QtWebKit
2807
2808    \sa QWebPage::extension(), QWebPage::ExtensionOption
2809*/
2810
2811/*!
2812    \class QWebPage::ErrorPageExtensionOption
2813    \since 4.6
2814    \brief The ErrorPageExtensionOption class describes the option
2815    for the error page extension.
2816
2817    \inmodule QtWebKit
2818
2819    The ErrorPageExtensionOption class holds the \a url for which an error occurred as well as
2820    the associated \a frame.
2821
2822    The error itself is reported by an error \a domain, the \a error code as well as \a errorString.
2823
2824    \sa QWebPage::extension(), QWebPage::ErrorPageExtensionReturn
2825*/
2826
2827/*!
2828    \variable QWebPage::ErrorPageExtensionOption::url
2829    \brief the url for which an error occurred
2830*/
2831
2832/*!
2833    \variable QWebPage::ErrorPageExtensionOption::frame
2834    \brief the frame associated with the error
2835*/
2836
2837/*!
2838    \variable QWebPage::ErrorPageExtensionOption::domain
2839    \brief the domain that reported the error
2840*/
2841
2842/*!
2843    \variable QWebPage::ErrorPageExtensionOption::error
2844    \brief the error code. Interpretation of the value depends on the \a domain
2845    \sa QWebPage::ErrorDomain
2846*/
2847
2848/*!
2849    \variable QWebPage::ErrorPageExtensionOption::errorString
2850    \brief a string that describes the error
2851*/
2852
2853/*!
2854    \class QWebPage::ErrorPageExtensionReturn
2855    \since 4.6
2856    \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the
2857    frame for which the error occured.
2858
2859    \inmodule QtWebKit
2860
2861    The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are
2862    optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which
2863    is assumed to be UTF-8 if not indicated otherwise.
2864
2865    The error page is stored in the \a content byte array, as HTML content. In order to convert a
2866    QString to a byte array, the QString::toUtf8() method can be used.
2867
2868    External objects such as stylesheets or images referenced in the HTML are located relative to
2869    \a baseUrl.
2870
2871    \sa QWebPage::extension(), QWebPage::ErrorPageExtensionOption, QString::toUtf8()
2872*/
2873
2874/*!
2875    \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn()
2876
2877    Constructs a new error page object.
2878*/
2879
2880
2881/*!
2882    \variable QWebPage::ErrorPageExtensionReturn::contentType
2883    \brief the error page's content type
2884*/
2885
2886/*!
2887    \variable QWebPage::ErrorPageExtensionReturn::encoding
2888    \brief the error page encoding
2889*/
2890
2891/*!
2892    \variable QWebPage::ErrorPageExtensionReturn::baseUrl
2893    \brief the base url
2894
2895    External objects such as stylesheets or images referenced in the HTML are located relative to this url.
2896*/
2897
2898/*!
2899    \variable QWebPage::ErrorPageExtensionReturn::content
2900    \brief the HTML content of the error page
2901*/
2902
2903/*!
2904    \class QWebPage::ChooseMultipleFilesExtensionOption
2905    \since 4.5
2906    \brief The ChooseMultipleFilesExtensionOption class describes the option
2907    for the multiple files selection extension.
2908
2909    \inmodule QtWebKit
2910
2911    The ChooseMultipleFilesExtensionOption class holds the frame originating the request
2912    and the suggested filenames which might be provided.
2913
2914    \sa QWebPage::extension(), QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn
2915*/
2916
2917/*!
2918    \variable QWebPage::ChooseMultipleFilesExtensionOption::parentFrame
2919    \brief The frame in which the request originated
2920*/
2921
2922/*!
2923    \variable QWebPage::ChooseMultipleFilesExtensionOption::suggestedFileNames
2924    \brief The suggested filenames
2925*/
2926
2927/*!
2928    \variable QWebPage::ChooseMultipleFilesExtensionReturn::fileNames
2929    \brief The selected filenames
2930*/
2931
2932/*!
2933    \class QWebPage::ChooseMultipleFilesExtensionReturn
2934    \since 4.5
2935    \brief The ChooseMultipleFilesExtensionReturn describes the return value
2936    for the multiple files selection extension.
2937
2938    \inmodule QtWebKit
2939
2940    The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user
2941    when the extension is invoked.
2942
2943    \sa QWebPage::extension(), QWebPage::ChooseMultipleFilesExtensionOption
2944*/
2945
2946/*!
2947    This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
2948    argument is provided as input to the extension; the output results can be stored in \a output.
2949
2950    The behavior of this function is determined by \a extension. The \a option
2951    and \a output values are typically casted to the corresponding types (for
2952    example, ChooseMultipleFilesExtensionOption and
2953    ChooseMultipleFilesExtensionReturn for ChooseMultipleFilesExtension).
2954
2955    You can call supportsExtension() to check if an extension is supported by the page.
2956
2957    Returns true if the extension was called successfully; otherwise returns false.
2958
2959    \sa supportsExtension(), Extension
2960*/
2961bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
2962{
2963#ifndef QT_NO_FILEDIALOG
2964    if (extension == ChooseMultipleFilesExtension) {
2965        // FIXME: do not ignore suggestedFiles
2966        QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames;
2967        QStringList names = QFileDialog::getOpenFileNames(view(), QString::null);
2968        static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
2969        return true;
2970    }
2971#endif
2972
2973    return false;
2974}
2975
2976/*!
2977    This virtual function returns true if the web page supports \a extension; otherwise false is returned.
2978
2979    \sa extension()
2980*/
2981bool QWebPage::supportsExtension(Extension extension) const
2982{
2983#ifndef QT_NO_FILEDIALOG
2984    return extension == ChooseMultipleFilesExtension;
2985#else
2986    Q_UNUSED(extension);
2987    return false;
2988#endif
2989}
2990
2991/*!
2992 * \internal
2993 */
2994QWebPageAdapter *QWebPage::handle() const
2995{
2996    return d;
2997}
2998
2999/*!
3000    Finds the specified string, \a subString, in the page, using the given \a options.
3001
3002    If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
3003    that exist in the page. All subsequent calls will extend the highlight, rather than
3004    replace it, with occurrences of the new string.
3005
3006    If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
3007    and all subsequent calls will replace the current occurrence with the next one.
3008
3009    To clear the selection, just pass an empty string.
3010
3011    Returns true if \a subString was found; otherwise returns false.
3012*/
3013bool QWebPage::findText(const QString &subString, FindFlags options)
3014{
3015    return d->findText(subString, static_cast<QWebPageAdapter::FindFlag>(options.operator int()));
3016}
3017
3018/*!
3019    Returns a pointer to the page's settings object.
3020
3021    \sa QWebSettings::globalSettings()
3022*/
3023QWebSettings *QWebPage::settings() const
3024{
3025    return d->settings;
3026}
3027
3028/*!
3029    This function is called when the web content requests a file name, for example
3030    as a result of the user clicking on a "file upload" button in a HTML form.
3031
3032    A suggested filename may be provided in \a suggestedFile. The frame originating the
3033    request is provided as \a parentFrame.
3034
3035    \sa ChooseMultipleFilesExtension
3036*/
3037QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
3038{
3039    Q_UNUSED(parentFrame);
3040#ifndef QT_NO_FILEDIALOG
3041    return QFileDialog::getOpenFileName(view(), QString::null, suggestedFile);
3042#else
3043    return QString::null;
3044#endif
3045}
3046
3047/*!
3048    Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
3049    QWebPage.
3050
3051    \note It is currently not supported to change the network access manager after the
3052    QWebPage has used it. The results of doing this are undefined.
3053
3054    \sa networkAccessManager()
3055*/
3056void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
3057{
3058    d->setNetworkAccessManager(manager);
3059}
3060
3061/*!
3062    Returns the QNetworkAccessManager that is responsible for serving network
3063    requests for this QWebPage.
3064
3065    \sa setNetworkAccessManager()
3066*/
3067QNetworkAccessManager *QWebPage::networkAccessManager() const
3068{
3069    return d->networkAccessManager();
3070}
3071
3072/*!
3073    Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
3074    QWebPage.
3075
3076    Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
3077
3078    \sa pluginFactory()
3079*/
3080void QWebPage::setPluginFactory(QWebPluginFactory *factory)
3081{
3082    d->pluginFactory = factory;
3083}
3084
3085/*!
3086    Returns the QWebPluginFactory that is responsible for creating plugins embedded into
3087    this QWebPage. If no plugin factory is installed a null pointer is returned.
3088
3089    \sa setPluginFactory()
3090*/
3091QWebPluginFactory *QWebPage::pluginFactory() const
3092{
3093    return d->pluginFactory;
3094}
3095
3096/*!
3097    This function is called when a user agent for HTTP requests is needed. You can reimplement this
3098    function to dynamically return different user agents for different URLs, based on the \a url parameter.
3099
3100    The default implementation returns the following value:
3101
3102    "Mozilla/5.0 (%Platform%%Security%%Subplatform%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%"
3103
3104    In this string the following values are replaced at run-time:
3105    \list
3106    \li %Platform% expands to the windowing system followed by "; " if it is not Windows (e.g. "X11; ").
3107    \li %Security% expands to "N; " if SSL is disabled.
3108    \li %Subplatform% expands to the operating system version (e.g. "Windows NT 6.1" or "Intel Mac OS X 10.5").
3109    \li %WebKitVersion% is the version of WebKit the application was compiled against.
3110    \li %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
3111    \endlist
3112*/
3113QString QWebPage::userAgentForUrl(const QUrl&) const
3114{
3115    return QWebPageAdapter::defaultUserAgentString();
3116}
3117
3118
3119/*!
3120    Returns the total number of bytes that were received from the network to render the current page,
3121    including extra content such as embedded images.
3122
3123    \sa bytesReceived()
3124*/
3125quint64 QWebPage::totalBytes() const
3126{
3127    return d->m_totalBytes;
3128}
3129
3130
3131/*!
3132    Returns the number of bytes that were received from the network to render the current page.
3133
3134    \sa totalBytes(), loadProgress()
3135*/
3136quint64 QWebPage::bytesReceived() const
3137{
3138    return d->m_bytesReceived;
3139}
3140
3141/*!
3142    \since 4.8
3143    \fn void QWebPage::viewportChangeRequested()
3144
3145    Page authors can provide the supplied values by using the viewport meta tag. More information
3146    about this can be found at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
3147
3148    \sa QWebPage::ViewportAttributes, setPreferredContentsSize(), QGraphicsWebView::setScale()
3149*/
3150
3151/*!
3152    \fn void QWebPage::loadStarted()
3153
3154    This signal is emitted when a page starts loading content.
3155
3156    \sa loadFinished()
3157*/
3158
3159/*!
3160    \fn void QWebPage::loadProgress(int progress)
3161
3162    This signal is emitted when the global progress status changes.
3163    The current value is provided by \a progress and scales from 0 to 100,
3164    which is the default range of QProgressBar.
3165    It accumulates changes from all the child frames.
3166
3167    \sa bytesReceived()
3168*/
3169
3170/*!
3171    \fn void QWebPage::loadFinished(bool ok)
3172
3173    This signal is emitted when the page finishes loading content. This signal
3174    is independant of script execution or page rendering.
3175    \a ok will indicate whether the load was successful or any error occurred.
3176
3177    \sa loadStarted(), ErrorPageExtension
3178*/
3179
3180/*!
3181    \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
3182
3183    This signal is emitted when the mouse hovers over a link.
3184
3185    \a link contains the link url.
3186    \a title is the link element's title, if it is specified in the markup.
3187    \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
3188
3189    When the mouse leaves the link element the signal is emitted with empty parameters.
3190
3191    \sa linkClicked()
3192*/
3193
3194/*!
3195    \fn void QWebPage::statusBarMessage(const QString& text)
3196
3197    This signal is emitted when the statusbar \a text is changed by the page.
3198*/
3199
3200/*!
3201    \fn void QWebPage::frameCreated(QWebFrame *frame)
3202
3203    This signal is emitted whenever the page creates a new \a frame.
3204
3205    \sa currentFrame()
3206*/
3207
3208/*!
3209    \fn void QWebPage::selectionChanged()
3210
3211    This signal is emitted whenever the selection changes, either interactively
3212    or programmatically (e.g. by calling triggerAction() with a selection action).
3213
3214    \sa selectedText()
3215*/
3216
3217/*!
3218    \fn void QWebPage::contentsChanged()
3219    \since 4.5
3220
3221    This signal is emitted whenever the text in form elements changes
3222    as well as other editable content.
3223
3224    \sa contentEditable, modified, QWebFrame::toHtml(), QWebFrame::toPlainText()
3225*/
3226
3227/*!
3228    \fn void QWebPage::geometryChangeRequested(const QRect& geom)
3229
3230    This signal is emitted whenever the document wants to change the position and size of the
3231    page to \a geom. This can happen for example through JavaScript.
3232*/
3233
3234/*!
3235    \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
3236
3237    This signal is emitted whenever this QWebPage should be updated. It's useful
3238    when rendering a QWebPage without a QWebView or QGraphicsWebView.
3239    \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
3240    the mainFrame() and call the render(QPainter*, const QRegion&) method with the
3241    \a dirtyRect as the second parameter.
3242
3243    \sa mainFrame()
3244    \sa view()
3245*/
3246
3247/*!
3248    \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
3249
3250    This signal is emitted whenever the content given by \a rectToScroll needs
3251    to be scrolled \a dx and \a dy downwards and no view was set.
3252
3253    \sa view()
3254*/
3255
3256/*!
3257    \fn void QWebPage::windowCloseRequested()
3258
3259    This signal is emitted whenever the page requests the web browser window to be closed,
3260    for example through the JavaScript \c{window.close()} call.
3261*/
3262
3263/*!
3264    \fn void QWebPage::printRequested(QWebFrame *frame)
3265
3266    This signal is emitted whenever the page requests the web browser to print \a frame,
3267    for example through the JavaScript \c{window.print()} call.
3268
3269    \sa QWebFrame::print(), QPrintPreviewDialog
3270*/
3271
3272/*!
3273    \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
3274
3275    This signal is emitted when WebKit cannot handle a link the user navigated to or a
3276    web server's response includes a "Content-Disposition" header with the 'attachment'
3277    directive. If "Content-Disposition" is present in \a reply, the web server is indicating
3278    that the client should prompt the user to save the content regardless of content-type.
3279    See RFC 2616 sections 19.5.1 for details about Content-Disposition.
3280
3281    At signal emission time the meta-data of the QNetworkReply \a reply is available.
3282
3283    \note The receiving slot is responsible for deleting the QNetworkReply \a reply.
3284
3285    \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
3286
3287    \sa downloadRequested()
3288*/
3289
3290/*!
3291    \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
3292
3293    This signal is emitted when the user decides to download a link. The url of
3294    the link as well as additional meta-information is contained in \a request.
3295
3296    \sa unsupportedContent()
3297*/
3298
3299/*!
3300    \fn void QWebPage::microFocusChanged()
3301
3302    This signal is emitted when for example the position of the cursor in an editable form
3303    element changes. It is used to inform input methods about the new on-screen position where
3304    the user is able to enter text. This signal is usually connected to the
3305    QWidget::updateMicroFocus() slot.
3306*/
3307
3308/*!
3309    \fn void QWebPage::linkClicked(const QUrl &url)
3310
3311    This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
3312    property is set to delegate the link handling for the specified \a url.
3313
3314    By default no links are delegated and are handled by QWebPage instead.
3315
3316    \note This signal possibly won't be emitted for clicked links which use
3317    JavaScript to trigger navigation.
3318
3319    \sa linkHovered()
3320*/
3321
3322/*!
3323    \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
3324
3325    This signal is emitted whenever the visibility of the toolbar in a web browser
3326    window that hosts QWebPage should be changed to \a visible.
3327*/
3328
3329/*!
3330    \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
3331
3332    This signal is emitted whenever the visibility of the statusbar in a web browser
3333    window that hosts QWebPage should be changed to \a visible.
3334*/
3335
3336/*!
3337    \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
3338
3339    This signal is emitted whenever the visibility of the menubar in a web browser
3340    window that hosts QWebPage should be changed to \a visible.
3341*/
3342
3343/*!
3344    \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
3345    \since 4.5
3346
3347    This signal is emitted whenever the web site shown in \a frame is asking to store data
3348    to the database \a databaseName and the quota allocated to that web site is exceeded.
3349
3350    \sa QWebDatabase
3351*/
3352/*!
3353    \fn void QWebPage::applicationCacheQuotaExceeded(QWebSecurityOrigin* origin, quint64 defaultOriginQuota, quint64 totalSpaceNeeded);
3354
3355    This signal is emitted whenever the web site is asking to store data to the application cache
3356    database databaseName and the quota allocated to that web site is exceeded.
3357
3358*/
3359
3360/*!
3361  \since 4.5
3362  \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
3363
3364  This signal is emitted shortly before the history of navigated pages
3365  in \a frame is changed, for example when navigating back in the history.
3366
3367  The provided QWebHistoryItem, \a item, holds the history entry of the frame before
3368  the change.
3369
3370  A potential use-case for this signal is to store custom data in
3371  the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
3372*/
3373
3374/*!
3375  \since 4.5
3376  \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
3377
3378  This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
3379*/
3380
3381/*!
3382  \fn QWebPagePrivate* QWebPage::handle() const
3383  \internal
3384*/
3385
3386#include "moc_qwebpage.cpp"
3387