1/*
2    Copyright (C) 2008, 2009 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#include "qwebview.h"
25#include "qwebframe.h"
26#include "qwebpage_p.h"
27#include "qwebframe_p.h"
28#include "qwebhistory.h"
29#include "qwebhistory_p.h"
30#include "qwebinspector.h"
31#include "qwebinspector_p.h"
32#include "qwebsettings.h"
33#include "qwebkitversion.h"
34
35#include "Chrome.h"
36#include "ContextMenuController.h"
37#include "Frame.h"
38#include "FrameTree.h"
39#include "FrameLoader.h"
40#include "FrameLoaderClientQt.h"
41#include "FrameView.h"
42#include "FormState.h"
43#include "ApplicationCacheStorage.h"
44#include "ChromeClientQt.h"
45#include "ContextMenu.h"
46#include "ContextMenuClientQt.h"
47#include "DocumentLoader.h"
48#include "DragClientQt.h"
49#include "DragController.h"
50#include "DragData.h"
51#include "EditorClientQt.h"
52#include "SecurityOrigin.h"
53#include "Settings.h"
54#include "Page.h"
55#include "Pasteboard.h"
56#include "FrameLoader.h"
57#include "FrameLoadRequest.h"
58#include "KURL.h"
59#include "Logging.h"
60#include "Image.h"
61#include "InspectorClientQt.h"
62#include "InspectorController.h"
63#include "FocusController.h"
64#include "Editor.h"
65#include "Scrollbar.h"
66#include "PlatformKeyboardEvent.h"
67#include "PlatformWheelEvent.h"
68#include "PluginDatabase.h"
69#include "ProgressTracker.h"
70#include "RefPtr.h"
71#include "RenderTextControl.h"
72#include "TextIterator.h"
73#include "HashMap.h"
74#include "HTMLFormElement.h"
75#include "HTMLInputElement.h"
76#include "HTMLNames.h"
77#include "HitTestResult.h"
78#include "WindowFeatures.h"
79#include "LocalizedStrings.h"
80#include "Cache.h"
81#include "runtime/InitializeThreading.h"
82#include "PageGroup.h"
83#include "QWebPageClient.h"
84#include "WorkerThread.h"
85
86#include <QApplication>
87#include <QBasicTimer>
88#include <QBitArray>
89#include <QDebug>
90#include <QDragEnterEvent>
91#include <QDragLeaveEvent>
92#include <QDragMoveEvent>
93#include <QDropEvent>
94#include <QFileDialog>
95#include <QHttpRequestHeader>
96#include <QInputDialog>
97#include <QLocale>
98#include <QMessageBox>
99#include <QNetworkProxy>
100#include <QUndoStack>
101#include <QUrl>
102#include <QPainter>
103#include <QClipboard>
104#include <QSslSocket>
105#include <QStyle>
106#include <QSysInfo>
107#include <QTextCharFormat>
108#include <QTextDocument>
109#include <QNetworkAccessManager>
110#include <QNetworkRequest>
111#if defined(Q_WS_X11)
112#include <QX11Info>
113#endif
114
115#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
116#include <QTouchEvent>
117#include "PlatformTouchEvent.h"
118#endif
119
120using namespace WebCore;
121
122void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories()
123{
124    PluginDatabase* db = PluginDatabase::installedPlugins(/* populate */ false);
125
126    Vector<String> paths;
127    String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").data());
128    qtPath.split(UChar(':'), /* allowEmptyEntries */ false, paths);
129
130    db->setPluginDirectories(paths);
131    db->refresh();
132}
133
134int QWEBKIT_EXPORT qt_drt_workerThreadCount()
135{
136#if ENABLE(WORKERS)
137    return WebCore::WorkerThread::workerThreadCount();
138#else
139    return 0;
140#endif
141}
142
143bool QWebPagePrivate::drtRun = false;
144void QWEBKIT_EXPORT qt_drt_run(bool b)
145{
146    QWebPagePrivate::drtRun = b;
147}
148
149void QWEBKIT_EXPORT qt_drt_setFrameSetFlatteningEnabled(QWebPage* page, bool enabled)
150{
151    QWebPagePrivate::core(page)->settings()->setFrameSetFlatteningEnabled(enabled);
152}
153
154void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName)
155{
156    page->handle()->page->setGroupName(groupName);
157}
158
159QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page)
160{
161    return page->handle()->page->groupName();
162}
163
164class QWebPageWidgetClient : public QWebPageClient {
165public:
166    QWebPageWidgetClient(QWidget* view)
167        : view(view)
168    {
169        Q_ASSERT(view);
170    }
171
172    virtual void scroll(int dx, int dy, const QRect&);
173    virtual void update(const QRect& dirtyRect);
174    virtual void setInputMethodEnabled(bool enable);
175    virtual bool inputMethodEnabled() const;
176#if QT_VERSION >= 0x040600
177    virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable);
178#endif
179
180#ifndef QT_NO_CURSOR
181    virtual QCursor cursor() const;
182    virtual void updateCursor(const QCursor& cursor);
183#endif
184
185    virtual QPalette palette() const;
186    virtual int screenNumber() const;
187    virtual QWidget* ownerWidget() const;
188
189    virtual QObject* pluginParent() const;
190
191    virtual QStyle* style() const;
192
193    QWidget* view;
194};
195
196void QWebPageWidgetClient::scroll(int dx, int dy, const QRect& rectToScroll)
197{
198    view->scroll(qreal(dx), qreal(dy), rectToScroll);
199}
200
201void QWebPageWidgetClient::update(const QRect & dirtyRect)
202{
203    view->update(dirtyRect);
204}
205
206void QWebPageWidgetClient::setInputMethodEnabled(bool enable)
207{
208    view->setAttribute(Qt::WA_InputMethodEnabled, enable);
209}
210
211bool QWebPageWidgetClient::inputMethodEnabled() const
212{
213    return view->testAttribute(Qt::WA_InputMethodEnabled);
214}
215
216#if QT_VERSION >= 0x040600
217void QWebPageWidgetClient::setInputMethodHint(Qt::InputMethodHint hint, bool enable)
218{
219    if (enable)
220        view->setInputMethodHints(view->inputMethodHints() | hint);
221    else
222        view->setInputMethodHints(view->inputMethodHints() & ~hint);
223}
224#endif
225#ifndef QT_NO_CURSOR
226QCursor QWebPageWidgetClient::cursor() const
227{
228    return view->cursor();
229}
230
231void QWebPageWidgetClient::updateCursor(const QCursor& cursor)
232{
233    view->setCursor(cursor);
234}
235#endif
236
237QPalette QWebPageWidgetClient::palette() const
238{
239    return view->palette();
240}
241
242int QWebPageWidgetClient::screenNumber() const
243{
244#if defined(Q_WS_X11)
245    if (view)
246        return view->x11Info().screen();
247#endif
248
249    return 0;
250}
251
252QWidget* QWebPageWidgetClient::ownerWidget() const
253{
254    return view;
255}
256
257QObject* QWebPageWidgetClient::pluginParent() const
258{
259    return view;
260}
261
262QStyle* QWebPageWidgetClient::style() const
263{
264    return view->style();
265}
266
267// Lookup table mapping QWebPage::WebActions to the associated Editor commands
268static const char* editorCommandWebActions[] =
269{
270    0, // OpenLink,
271
272    0, // OpenLinkInNewWindow,
273    0, // OpenFrameInNewWindow,
274
275    0, // DownloadLinkToDisk,
276    0, // CopyLinkToClipboard,
277
278    0, // OpenImageInNewWindow,
279    0, // DownloadImageToDisk,
280    0, // CopyImageToClipboard,
281
282    0, // Back,
283    0, // Forward,
284    0, // Stop,
285    0, // Reload,
286
287    "Cut", // Cut,
288    "Copy", // Copy,
289    "Paste", // Paste,
290
291    "Undo", // Undo,
292    "Redo", // Redo,
293    "MoveForward", // MoveToNextChar,
294    "MoveBackward", // MoveToPreviousChar,
295    "MoveWordForward", // MoveToNextWord,
296    "MoveWordBackward", // MoveToPreviousWord,
297    "MoveDown", // MoveToNextLine,
298    "MoveUp", // MoveToPreviousLine,
299    "MoveToBeginningOfLine", // MoveToStartOfLine,
300    "MoveToEndOfLine", // MoveToEndOfLine,
301    "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
302    "MoveToEndOfParagraph", // MoveToEndOfBlock,
303    "MoveToBeginningOfDocument", // MoveToStartOfDocument,
304    "MoveToEndOfDocument", // MoveToEndOfDocument,
305    "MoveForwardAndModifySelection", // SelectNextChar,
306    "MoveBackwardAndModifySelection", // SelectPreviousChar,
307    "MoveWordForwardAndModifySelection", // SelectNextWord,
308    "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
309    "MoveDownAndModifySelection", // SelectNextLine,
310    "MoveUpAndModifySelection", // SelectPreviousLine,
311    "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
312    "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
313    "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
314    "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
315    "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
316    "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
317    "DeleteWordBackward", // DeleteStartOfWord,
318    "DeleteWordForward", // DeleteEndOfWord,
319
320    0, // SetTextDirectionDefault,
321    0, // SetTextDirectionLeftToRight,
322    0, // SetTextDirectionRightToLeft,
323
324    "ToggleBold", // ToggleBold,
325    "ToggleItalic", // ToggleItalic,
326    "ToggleUnderline", // ToggleUnderline,
327
328    0, // InspectElement,
329
330    "InsertNewline", // InsertParagraphSeparator
331    "InsertLineBreak", // InsertLineSeparator
332
333    "SelectAll", // SelectAll
334    0, // ReloadAndBypassCache,
335
336    "PasteAndMatchStyle", // PasteAndMatchStyle
337    "RemoveFormat", // RemoveFormat
338    "Strikethrough", // ToggleStrikethrough,
339    "Subscript", // ToggleSubscript
340    "Superscript", // ToggleSuperscript
341    "InsertUnorderedList", // InsertUnorderedList
342    "InsertOrderedList", // InsertOrderedList
343    "Indent", // Indent
344    "Outdent", // Outdent,
345
346    "AlignCenter", // AlignCenter,
347    "AlignJustified", // AlignJustified,
348    "AlignLeft", // AlignLeft,
349    "AlignRight", // AlignRight,
350
351    0 // WebActionCount
352};
353
354// Lookup the appropriate editor command to use for WebAction \a action
355const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
356{
357    if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
358        return editorCommandWebActions[action];
359    return 0;
360}
361
362// If you change this make sure to also adjust the docs for QWebPage::userAgentForUrl
363#define WEBKIT_VERSION "527+"
364
365static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
366{
367    unsigned result = 0;
368    if (actions & Qt::CopyAction)
369        result |= DragOperationCopy;
370    // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
371    // hence it should be considered as "move"
372    if (actions & Qt::MoveAction)
373        result |= (DragOperationMove | DragOperationGeneric);
374    if (actions & Qt::LinkAction)
375        result |= DragOperationLink;
376    return (DragOperation)result;
377}
378
379static inline Qt::DropAction dragOpToDropAction(unsigned actions)
380{
381    Qt::DropAction result = Qt::IgnoreAction;
382    if (actions & DragOperationCopy)
383        result = Qt::CopyAction;
384    else if (actions & DragOperationMove)
385        result = Qt::MoveAction;
386    // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
387    // hence it should be considered as "move"
388    else if (actions & DragOperationGeneric)
389        result = Qt::MoveAction;
390    else if (actions & DragOperationLink)
391        result = Qt::LinkAction;
392    return result;
393}
394
395QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
396    : q(qq)
397    , client(0)
398#if QT_VERSION < 0x040600
399    , view(0)
400#endif
401    , clickCausedFocus(false)
402    , viewportSize(QSize(0, 0))
403    , inspectorFrontend(0)
404    , inspector(0)
405    , inspectorIsInternalOnly(false)
406{
407    WebCore::InitializeLoggingChannelsIfNecessary();
408    JSC::initializeThreading();
409    WebCore::SecurityOrigin::setLocalLoadPolicy(WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
410
411    chromeClient = new ChromeClientQt(q);
412    contextMenuClient = new ContextMenuClientQt();
413    editorClient = new EditorClientQt(q);
414    page = new Page(chromeClient, contextMenuClient, editorClient,
415                    new DragClientQt(q), new InspectorClientQt(q), 0, 0);
416
417    settings = new QWebSettings(page->settings());
418
419#ifndef QT_NO_UNDOSTACK
420    undoStack = 0;
421#endif
422    mainFrame = 0;
423    networkManager = 0;
424    pluginFactory = 0;
425    insideOpenCall = false;
426    forwardUnsupportedContent = false;
427    editable = false;
428    useFixedLayout = false;
429    linkPolicy = QWebPage::DontDelegateLinks;
430#ifndef QT_NO_CONTEXTMENU
431    currentContextMenu = 0;
432#endif
433
434    history.d = new QWebHistoryPrivate(page->backForwardList());
435    memset(actions, 0, sizeof(actions));
436
437    PageGroup::setShouldTrackVisitedLinks(true);
438}
439
440QWebPagePrivate::~QWebPagePrivate()
441{
442#ifndef QT_NO_CONTEXTMENU
443    delete currentContextMenu;
444#endif
445#ifndef QT_NO_UNDOSTACK
446    delete undoStack;
447#endif
448    delete settings;
449    delete page;
450}
451
452WebCore::Page* QWebPagePrivate::core(QWebPage* page)
453{
454    return page->d->page;
455}
456
457bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
458{
459    if (insideOpenCall
460        && frame == mainFrame)
461        return true;
462    return q->acceptNavigationRequest(frame, request, type);
463}
464
465void QWebPagePrivate::createMainFrame()
466{
467    if (!mainFrame) {
468        QWebFrameData frameData(page);
469        mainFrame = new QWebFrame(q, &frameData);
470
471        emit q->frameCreated(mainFrame);
472    }
473}
474
475static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
476{
477    switch (action) {
478        case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
479        case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
480        case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
481        case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
482        case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
483        case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
484        case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
485        case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
486        case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
487        case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
488        case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
489        case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
490        case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
491        case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
492        case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
493        case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
494        case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
495        case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
496        case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
497        case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
498        case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
499#if ENABLE(INSPECTOR)
500        case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
501#endif
502        default: break;
503    }
504    return QWebPage::NoWebAction;
505}
506
507#ifndef QT_NO_CONTEXTMENU
508QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
509        const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
510{
511    QMenu* menu = new QMenu(q->view());
512    for (int i = 0; i < items->count(); ++i) {
513        const ContextMenuItem &item = items->at(i);
514        switch (item.type()) {
515            case WebCore::CheckableActionType: /* fall through */
516            case WebCore::ActionType: {
517                QWebPage::WebAction action = webActionForContextMenuAction(item.action());
518                QAction *a = q->action(action);
519                if (a) {
520                    ContextMenuItem it(item);
521                    webcoreMenu->checkOrEnableIfNeeded(it);
522                    PlatformMenuItemDescription desc = it.releasePlatformDescription();
523                    a->setEnabled(desc.enabled);
524                    a->setChecked(desc.checked);
525                    a->setCheckable(item.type() == WebCore::CheckableActionType);
526
527                    menu->addAction(a);
528                    visitedWebActions->setBit(action);
529                }
530                break;
531            }
532            case WebCore::SeparatorType:
533                menu->addSeparator();
534                break;
535            case WebCore::SubmenuType: {
536                QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
537
538                bool anyEnabledAction = false;
539
540                QList<QAction *> actions = subMenu->actions();
541                for (int i = 0; i < actions.count(); ++i) {
542                    if (actions.at(i)->isVisible())
543                        anyEnabledAction |= actions.at(i)->isEnabled();
544                }
545
546                // don't show sub-menus with just disabled actions
547                if (anyEnabledAction) {
548                    subMenu->setTitle(item.title());
549                    menu->addAction(subMenu->menuAction());
550                } else
551                    delete subMenu;
552                break;
553            }
554        }
555    }
556    return menu;
557}
558#endif // QT_NO_CONTEXTMENU
559
560void QWebPagePrivate::_q_webActionTriggered(bool checked)
561{
562    QAction *a = qobject_cast<QAction *>(q->sender());
563    if (!a)
564        return;
565    QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
566    q->triggerAction(action, checked);
567}
568
569void QWebPagePrivate::_q_cleanupLeakMessages()
570{
571#ifndef NDEBUG
572    // Need this to make leak messages accurate.
573    cache()->setCapacities(0, 0, 0);
574#endif
575}
576
577void QWebPagePrivate::updateAction(QWebPage::WebAction action)
578{
579    QAction *a = actions[action];
580    if (!a || !mainFrame)
581        return;
582
583    WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
584    WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
585
586    bool enabled = a->isEnabled();
587    bool checked = a->isChecked();
588
589    switch (action) {
590        case QWebPage::Back:
591            enabled = page->canGoBackOrForward(-1);
592            break;
593        case QWebPage::Forward:
594            enabled = page->canGoBackOrForward(1);
595            break;
596        case QWebPage::Stop:
597            enabled = loader->isLoading();
598            break;
599        case QWebPage::Reload:
600        case QWebPage::ReloadAndBypassCache:
601            enabled = !loader->isLoading();
602            break;
603#ifndef QT_NO_UNDOSTACK
604        case QWebPage::Undo:
605        case QWebPage::Redo:
606            // those two are handled by QUndoStack
607            break;
608#endif // QT_NO_UNDOSTACK
609        case QWebPage::SelectAll: // editor command is always enabled
610            break;
611        case QWebPage::SetTextDirectionDefault:
612        case QWebPage::SetTextDirectionLeftToRight:
613        case QWebPage::SetTextDirectionRightToLeft:
614            enabled = editor->canEdit();
615            checked = false;
616            break;
617        default: {
618            // see if it's an editor command
619            const char* commandName = editorCommandForWebActions(action);
620
621            // if it's an editor command, let it's logic determine state
622            if (commandName) {
623                Editor::Command command = editor->command(commandName);
624                enabled = command.isEnabled();
625                if (enabled)
626                    checked = command.state() != FalseTriState;
627                else
628                    checked = false;
629            }
630            break;
631        }
632    }
633
634    a->setEnabled(enabled);
635
636    if (a->isCheckable())
637        a->setChecked(checked);
638}
639
640void QWebPagePrivate::updateNavigationActions()
641{
642    updateAction(QWebPage::Back);
643    updateAction(QWebPage::Forward);
644    updateAction(QWebPage::Stop);
645    updateAction(QWebPage::Reload);
646    updateAction(QWebPage::ReloadAndBypassCache);
647}
648
649void QWebPagePrivate::updateEditorActions()
650{
651    updateAction(QWebPage::Cut);
652    updateAction(QWebPage::Copy);
653    updateAction(QWebPage::Paste);
654    updateAction(QWebPage::MoveToNextChar);
655    updateAction(QWebPage::MoveToPreviousChar);
656    updateAction(QWebPage::MoveToNextWord);
657    updateAction(QWebPage::MoveToPreviousWord);
658    updateAction(QWebPage::MoveToNextLine);
659    updateAction(QWebPage::MoveToPreviousLine);
660    updateAction(QWebPage::MoveToStartOfLine);
661    updateAction(QWebPage::MoveToEndOfLine);
662    updateAction(QWebPage::MoveToStartOfBlock);
663    updateAction(QWebPage::MoveToEndOfBlock);
664    updateAction(QWebPage::MoveToStartOfDocument);
665    updateAction(QWebPage::MoveToEndOfDocument);
666    updateAction(QWebPage::SelectNextChar);
667    updateAction(QWebPage::SelectPreviousChar);
668    updateAction(QWebPage::SelectNextWord);
669    updateAction(QWebPage::SelectPreviousWord);
670    updateAction(QWebPage::SelectNextLine);
671    updateAction(QWebPage::SelectPreviousLine);
672    updateAction(QWebPage::SelectStartOfLine);
673    updateAction(QWebPage::SelectEndOfLine);
674    updateAction(QWebPage::SelectStartOfBlock);
675    updateAction(QWebPage::SelectEndOfBlock);
676    updateAction(QWebPage::SelectStartOfDocument);
677    updateAction(QWebPage::SelectEndOfDocument);
678    updateAction(QWebPage::DeleteStartOfWord);
679    updateAction(QWebPage::DeleteEndOfWord);
680    updateAction(QWebPage::SetTextDirectionDefault);
681    updateAction(QWebPage::SetTextDirectionLeftToRight);
682    updateAction(QWebPage::SetTextDirectionRightToLeft);
683    updateAction(QWebPage::ToggleBold);
684    updateAction(QWebPage::ToggleItalic);
685    updateAction(QWebPage::ToggleUnderline);
686    updateAction(QWebPage::InsertParagraphSeparator);
687    updateAction(QWebPage::InsertLineSeparator);
688    updateAction(QWebPage::PasteAndMatchStyle);
689    updateAction(QWebPage::RemoveFormat);
690    updateAction(QWebPage::ToggleStrikethrough);
691    updateAction(QWebPage::ToggleSubscript);
692    updateAction(QWebPage::ToggleSuperscript);
693    updateAction(QWebPage::InsertUnorderedList);
694    updateAction(QWebPage::InsertOrderedList);
695    updateAction(QWebPage::Indent);
696    updateAction(QWebPage::Outdent);
697    updateAction(QWebPage::AlignCenter);
698    updateAction(QWebPage::AlignJustified);
699    updateAction(QWebPage::AlignLeft);
700    updateAction(QWebPage::AlignRight);
701}
702
703void QWebPagePrivate::timerEvent(QTimerEvent *ev)
704{
705    int timerId = ev->timerId();
706    if (timerId == tripleClickTimer.timerId())
707        tripleClickTimer.stop();
708    else
709        q->QObject::timerEvent(ev);
710}
711
712void QWebPagePrivate::mouseMoveEvent(QGraphicsSceneMouseEvent* ev)
713{
714    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
715    if (!frame->view())
716        return;
717
718    bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
719    ev->setAccepted(accepted);
720}
721
722void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev)
723{
724    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
725    if (!frame->view())
726        return;
727
728    bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
729    ev->setAccepted(accepted);
730}
731
732void QWebPagePrivate::mousePressEvent(QGraphicsSceneMouseEvent* ev)
733{
734    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
735    if (!frame->view())
736        return;
737
738    if (tripleClickTimer.isActive()
739            && (ev->pos().toPoint() - tripleClick).manhattanLength()
740                < QApplication::startDragDistance()) {
741        mouseTripleClickEvent(ev);
742        return;
743    }
744
745    bool accepted = false;
746    PlatformMouseEvent mev(ev, 1);
747    // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
748    if (mev.button() != NoButton)
749        accepted = frame->eventHandler()->handleMousePressEvent(mev);
750    ev->setAccepted(accepted);
751}
752
753void QWebPagePrivate::mousePressEvent(QMouseEvent *ev)
754{
755    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
756    if (!frame->view())
757        return;
758
759    RefPtr<WebCore::Node> oldNode;
760    if (page->focusController()->focusedFrame()
761        && page->focusController()->focusedFrame()->document())
762        oldNode = page->focusController()->focusedFrame()->document()->focusedNode();
763
764    if (tripleClickTimer.isActive()
765            && (ev->pos() - tripleClick).manhattanLength()
766                < QApplication::startDragDistance()) {
767        mouseTripleClickEvent(ev);
768        return;
769    }
770
771    bool accepted = false;
772    PlatformMouseEvent mev(ev, 1);
773    // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
774    if (mev.button() != NoButton)
775        accepted = frame->eventHandler()->handleMousePressEvent(mev);
776    ev->setAccepted(accepted);
777
778    RefPtr<WebCore::Node> newNode;
779    if (page->focusController()->focusedFrame()
780        && page->focusController()->focusedFrame()->document())
781        newNode = page->focusController()->focusedFrame()->document()->focusedNode();
782
783    if (newNode && oldNode != newNode)
784        clickCausedFocus = true;
785}
786
787void QWebPagePrivate::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *ev)
788{
789    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
790    if (!frame->view())
791        return;
792
793    bool accepted = false;
794    PlatformMouseEvent mev(ev, 2);
795    // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
796    if (mev.button() != NoButton)
797        accepted = frame->eventHandler()->handleMousePressEvent(mev);
798    ev->setAccepted(accepted);
799
800    tripleClickTimer.start(QApplication::doubleClickInterval(), q);
801    tripleClick = ev->pos().toPoint();
802}
803
804void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev)
805{
806    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
807    if (!frame->view())
808        return;
809
810    bool accepted = false;
811    PlatformMouseEvent mev(ev, 2);
812    // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
813    if (mev.button() != NoButton)
814        accepted = frame->eventHandler()->handleMousePressEvent(mev);
815    ev->setAccepted(accepted);
816
817    tripleClickTimer.start(QApplication::doubleClickInterval(), q);
818    tripleClick = ev->pos();
819}
820
821void QWebPagePrivate::mouseTripleClickEvent(QGraphicsSceneMouseEvent *ev)
822{
823    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
824    if (!frame->view())
825        return;
826
827    bool accepted = false;
828    PlatformMouseEvent mev(ev, 3);
829    // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
830    if (mev.button() != NoButton)
831        accepted = frame->eventHandler()->handleMousePressEvent(mev);
832    ev->setAccepted(accepted);
833}
834
835void QWebPagePrivate::mouseTripleClickEvent(QMouseEvent *ev)
836{
837    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
838    if (!frame->view())
839        return;
840
841    bool accepted = false;
842    PlatformMouseEvent mev(ev, 3);
843    // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
844    if (mev.button() != NoButton)
845        accepted = frame->eventHandler()->handleMousePressEvent(mev);
846    ev->setAccepted(accepted);
847}
848
849void QWebPagePrivate::handleClipboard(QEvent* ev, Qt::MouseButton button)
850{
851#ifndef QT_NO_CLIPBOARD
852    if (QApplication::clipboard()->supportsSelection()) {
853        bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
854        Pasteboard::generalPasteboard()->setSelectionMode(true);
855        WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
856        if (button == Qt::LeftButton) {
857            if (focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
858                focusFrame->editor()->copy();
859                ev->setAccepted(true);
860            }
861        } else if (button == Qt::MidButton) {
862            if (focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
863                focusFrame->editor()->paste();
864                ev->setAccepted(true);
865            }
866        }
867        Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
868    }
869#endif
870}
871
872void QWebPagePrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev)
873{
874    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
875    if (!frame->view())
876        return;
877
878    bool accepted = false;
879    PlatformMouseEvent mev(ev, 0);
880    // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
881    if (mev.button() != NoButton)
882        accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
883    ev->setAccepted(accepted);
884
885    handleClipboard(ev, ev->button());
886    handleSoftwareInputPanel(ev->button());
887}
888
889void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button)
890{
891#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
892    Frame* frame = page->focusController()->focusedFrame();
893    if (!frame)
894        return;
895
896    if (client && client->inputMethodEnabled()
897        && frame->document()->focusedNode()
898        && button == Qt::LeftButton && qApp->autoSipEnabled()) {
899        QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
900            client->ownerWidget()->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
901        if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
902            QEvent event(QEvent::RequestSoftwareInputPanel);
903            QApplication::sendEvent(client->ownerWidget(), &event);
904        }
905    }
906
907    clickCausedFocus = false;
908#endif
909}
910
911void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev)
912{
913    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
914    if (!frame->view())
915        return;
916
917    bool accepted = false;
918    PlatformMouseEvent mev(ev, 0);
919    // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
920    if (mev.button() != NoButton)
921        accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
922    ev->setAccepted(accepted);
923
924    handleClipboard(ev, ev->button());
925    handleSoftwareInputPanel(ev->button());
926}
927
928#ifndef QT_NO_CONTEXTMENU
929void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
930{
931    QMenu *menu = q->createStandardContextMenu();
932    if (menu) {
933        menu->exec(globalPos);
934        delete menu;
935    }
936}
937#endif // QT_NO_CONTEXTMENU
938
939/*!
940    \since 4.5
941    This function creates the standard context menu which is shown when
942    the user clicks on the web page with the right mouse button. It is
943    called from the default contextMenuEvent() handler. The popup menu's
944    ownership is transferred to the caller.
945 */
946QMenu *QWebPage::createStandardContextMenu()
947{
948#ifndef QT_NO_CONTEXTMENU
949    QMenu *menu = d->currentContextMenu;
950    d->currentContextMenu = 0;
951    return menu;
952#else
953    return 0;
954#endif
955}
956
957#ifndef QT_NO_WHEELEVENT
958void QWebPagePrivate::wheelEvent(QGraphicsSceneWheelEvent* ev)
959{
960    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
961    if (!frame->view())
962        return;
963
964    WebCore::PlatformWheelEvent pev(ev);
965    bool accepted = frame->eventHandler()->handleWheelEvent(pev);
966    ev->setAccepted(accepted);
967}
968
969void QWebPagePrivate::wheelEvent(QWheelEvent *ev)
970{
971    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
972    if (!frame->view())
973        return;
974
975    WebCore::PlatformWheelEvent pev(ev);
976    bool accepted = frame->eventHandler()->handleWheelEvent(pev);
977    ev->setAccepted(accepted);
978}
979#endif // QT_NO_WHEELEVENT
980
981#ifndef QT_NO_SHORTCUT
982QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
983{
984    static struct {
985        QKeySequence::StandardKey standardKey;
986        QWebPage::WebAction action;
987    } editorActions[] = {
988        { QKeySequence::Cut, QWebPage::Cut },
989        { QKeySequence::Copy, QWebPage::Copy },
990        { QKeySequence::Paste, QWebPage::Paste },
991        { QKeySequence::Undo, QWebPage::Undo },
992        { QKeySequence::Redo, QWebPage::Redo },
993        { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
994        { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
995        { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
996        { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
997        { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
998        { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
999        { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
1000        { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
1001        { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
1002        { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
1003        { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
1004        { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
1005        { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
1006        { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
1007        { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
1008        { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
1009        { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
1010        { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
1011        { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
1012        { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
1013        { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
1014        { QKeySequence::SelectEndOfBlock,  QWebPage::SelectEndOfBlock },
1015        { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
1016        { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
1017        { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
1018        { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
1019#if QT_VERSION >= 0x040500
1020        { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
1021        { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
1022#endif
1023        { QKeySequence::SelectAll, QWebPage::SelectAll },
1024        { QKeySequence::UnknownKey, QWebPage::NoWebAction }
1025    };
1026
1027    for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
1028        if (event == editorActions[i].standardKey)
1029            return editorActions[i].action;
1030
1031    return QWebPage::NoWebAction;
1032}
1033#endif // QT_NO_SHORTCUT
1034
1035void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
1036{
1037    bool handled = false;
1038    WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1039    // we forward the key event to WebCore first to handle potential DOM
1040    // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
1041    // to trigger editor commands via triggerAction().
1042    if (!handled)
1043        handled = frame->eventHandler()->keyEvent(ev);
1044    if (!handled) {
1045        handled = true;
1046        QFont defaultFont;
1047        if (q->view())
1048            defaultFont = q->view()->font();
1049        QFontMetrics fm(defaultFont);
1050        if (!handleScrolling(ev, frame)) {
1051            switch (ev->key()) {
1052            case Qt::Key_Back:
1053                q->triggerAction(QWebPage::Back);
1054                break;
1055            case Qt::Key_Forward:
1056                q->triggerAction(QWebPage::Forward);
1057                break;
1058            case Qt::Key_Stop:
1059                q->triggerAction(QWebPage::Stop);
1060                break;
1061            case Qt::Key_Refresh:
1062                q->triggerAction(QWebPage::Reload);
1063                break;
1064            case Qt::Key_Backspace:
1065                if (ev->modifiers() == Qt::ShiftModifier)
1066                    q->triggerAction(QWebPage::Forward);
1067                else
1068                    q->triggerAction(QWebPage::Back);
1069                break;
1070            default:
1071                handled = false;
1072                break;
1073            }
1074        }
1075    }
1076
1077    ev->setAccepted(handled);
1078}
1079
1080void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
1081{
1082    if (ev->isAutoRepeat()) {
1083        ev->setAccepted(true);
1084        return;
1085    }
1086
1087    WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1088    bool handled = frame->eventHandler()->keyEvent(ev);
1089    ev->setAccepted(handled);
1090}
1091
1092void QWebPagePrivate::focusInEvent(QFocusEvent*)
1093{
1094    FocusController *focusController = page->focusController();
1095    focusController->setActive(true);
1096    focusController->setFocused(true);
1097    if (!focusController->focusedFrame())
1098        focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame));
1099}
1100
1101void QWebPagePrivate::focusOutEvent(QFocusEvent*)
1102{
1103    // only set the focused frame inactive so that we stop painting the caret
1104    // and the focus frame. But don't tell the focus controller so that upon
1105    // focusInEvent() we can re-activate the frame.
1106    FocusController *focusController = page->focusController();
1107    // Call setFocused first so that window.onblur doesn't get called twice
1108    focusController->setFocused(false);
1109    focusController->setActive(false);
1110}
1111
1112void QWebPagePrivate::dragEnterEvent(QGraphicsSceneDragDropEvent* ev)
1113{
1114#ifndef QT_NO_DRAGANDDROP
1115    DragData dragData(ev->mimeData(), ev->pos().toPoint(),
1116            QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1117    Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
1118    ev->setDropAction(action);
1119    if (action != Qt::IgnoreAction)
1120        ev->accept();
1121#endif
1122}
1123
1124void QWebPagePrivate::dragEnterEvent(QDragEnterEvent* ev)
1125{
1126#ifndef QT_NO_DRAGANDDROP
1127    DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
1128                      dropActionToDragOp(ev->possibleActions()));
1129    Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
1130    ev->setDropAction(action);
1131    // We must accept this event in order to receive the drag move events that are sent
1132    // while the drag and drop action is in progress.
1133    ev->accept();
1134#endif
1135}
1136
1137void QWebPagePrivate::dragLeaveEvent(QGraphicsSceneDragDropEvent* ev)
1138{
1139#ifndef QT_NO_DRAGANDDROP
1140    DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1141    page->dragController()->dragExited(&dragData);
1142    ev->accept();
1143#endif
1144}
1145
1146void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent* ev)
1147{
1148#ifndef QT_NO_DRAGANDDROP
1149    DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1150    page->dragController()->dragExited(&dragData);
1151    ev->accept();
1152#endif
1153}
1154
1155void QWebPagePrivate::dragMoveEvent(QGraphicsSceneDragDropEvent* ev)
1156{
1157#ifndef QT_NO_DRAGANDDROP
1158    DragData dragData(ev->mimeData(), ev->pos().toPoint(),
1159            QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1160    Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
1161    ev->setDropAction(action);
1162    if (action != Qt::IgnoreAction)
1163        ev->accept();
1164#endif
1165}
1166
1167void QWebPagePrivate::dragMoveEvent(QDragMoveEvent* ev)
1168{
1169#ifndef QT_NO_DRAGANDDROP
1170    DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
1171                      dropActionToDragOp(ev->possibleActions()));
1172    Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
1173    m_lastDropAction = action;
1174    ev->setDropAction(action);
1175    // We must accept this event in order to receive the drag move events that are sent
1176    // while the drag and drop action is in progress.
1177    ev->accept();
1178#endif
1179}
1180
1181void QWebPagePrivate::dropEvent(QGraphicsSceneDragDropEvent* ev)
1182{
1183#ifndef QT_NO_DRAGANDDROP
1184    DragData dragData(ev->mimeData(), ev->pos().toPoint(),
1185            QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1186    if (page->dragController()->performDrag(&dragData))
1187        ev->accept();
1188#endif
1189}
1190
1191void QWebPagePrivate::dropEvent(QDropEvent* ev)
1192{
1193#ifndef QT_NO_DRAGANDDROP
1194    // Overwrite the defaults set by QDragManager::defaultAction()
1195    ev->setDropAction(m_lastDropAction);
1196    DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
1197                      dropActionToDragOp(Qt::DropAction(ev->dropAction())));
1198    if (page->dragController()->performDrag(&dragData))
1199        ev->accept();
1200#endif
1201}
1202
1203void QWebPagePrivate::leaveEvent(QEvent*)
1204{
1205    // Fake a mouse move event just outside of the widget, since all
1206    // the interesting mouse-out behavior like invalidating scrollbars
1207    // is handled by the WebKit event handler's mouseMoved function.
1208    QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
1209    mouseMoveEvent(&fakeEvent);
1210}
1211
1212/*!
1213    \property QWebPage::palette
1214    \brief the page's palette
1215
1216    The base brush of the palette is used to draw the background of the main frame.
1217
1218    By default, this property contains the application's default palette.
1219*/
1220void QWebPage::setPalette(const QPalette &pal)
1221{
1222    d->palette = pal;
1223    if (!d->mainFrame || !d->mainFrame->d->frame->view())
1224        return;
1225
1226    QBrush brush = pal.brush(QPalette::Base);
1227    QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
1228    QWebFramePrivate::core(d->mainFrame)->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha());
1229}
1230
1231QPalette QWebPage::palette() const
1232{
1233    return d->palette;
1234}
1235
1236void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
1237{
1238    WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
1239    WebCore::Editor *editor = frame->editor();
1240
1241    if (!editor->canEdit()) {
1242        ev->ignore();
1243        return;
1244    }
1245
1246    RenderObject* renderer = 0;
1247    RenderTextControl* renderTextControl = 0;
1248
1249    if (frame->selection()->rootEditableElement())
1250        renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1251
1252    if (renderer && renderer->isTextControl())
1253        renderTextControl = toRenderTextControl(renderer);
1254
1255    Vector<CompositionUnderline> underlines;
1256
1257    for (int i = 0; i < ev->attributes().size(); ++i) {
1258        const QInputMethodEvent::Attribute& a = ev->attributes().at(i);
1259        switch (a.type) {
1260        case QInputMethodEvent::TextFormat: {
1261            QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat();
1262            QColor qcolor = textCharFormat.underlineColor();
1263            underlines.append(CompositionUnderline(a.start, a.length, Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())), false));
1264            break;
1265        }
1266        case QInputMethodEvent::Cursor: {
1267            frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible
1268            if (a.length > 0) {
1269                RenderObject* caretRenderer = frame->selection()->caretRenderer();
1270                if (caretRenderer) {
1271                    QColor qcolor = a.value.value<QColor>();
1272                    caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())));
1273                }
1274            }
1275            break;
1276        }
1277#if QT_VERSION >= 0x040600
1278        case QInputMethodEvent::Selection: {
1279            if (renderTextControl) {
1280                renderTextControl->setSelectionStart(a.start);
1281                renderTextControl->setSelectionEnd(a.start + a.length);
1282            }
1283            break;
1284        }
1285#endif
1286        }
1287    }
1288
1289    if (!ev->commitString().isEmpty())
1290        editor->confirmComposition(ev->commitString());
1291    else if (!ev->preeditString().isEmpty()) {
1292        QString preedit = ev->preeditString();
1293        editor->setComposition(preedit, underlines, preedit.length(), 0);
1294    }
1295    ev->accept();
1296}
1297
1298void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
1299{
1300    WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1301    WebCore::Editor* editor = frame->editor();
1302    if (editor->canEdit()) {
1303        if (event->modifiers() == Qt::NoModifier
1304            || event->modifiers() == Qt::ShiftModifier
1305            || event->modifiers() == Qt::KeypadModifier) {
1306                if (event->key() < Qt::Key_Escape) {
1307                    event->accept();
1308                } else {
1309                    switch (event->key()) {
1310                    case Qt::Key_Return:
1311                    case Qt::Key_Enter:
1312                    case Qt::Key_Delete:
1313                    case Qt::Key_Home:
1314                    case Qt::Key_End:
1315                    case Qt::Key_Backspace:
1316                    case Qt::Key_Left:
1317                    case Qt::Key_Right:
1318                    case Qt::Key_Up:
1319                    case Qt::Key_Down:
1320                    case Qt::Key_Tab:
1321                        event->accept();
1322                    default:
1323                        break;
1324                    }
1325                }
1326        }
1327#ifndef QT_NO_SHORTCUT
1328        else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
1329            event->accept();
1330#endif
1331    }
1332}
1333
1334bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame)
1335{
1336    ScrollDirection direction;
1337    ScrollGranularity granularity;
1338
1339#ifndef QT_NO_SHORTCUT
1340    if (ev == QKeySequence::MoveToNextPage
1341        || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
1342        granularity = ScrollByPage;
1343        direction = ScrollDown;
1344    } else if (ev == QKeySequence::MoveToPreviousPage
1345               || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) {
1346        granularity = ScrollByPage;
1347        direction = ScrollUp;
1348    } else
1349#endif // QT_NO_SHORTCUT
1350    if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier)
1351               || ev->key() == Qt::Key_Home) {
1352        granularity = ScrollByDocument;
1353        direction = ScrollUp;
1354    } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier)
1355               || ev->key() == Qt::Key_End) {
1356        granularity = ScrollByDocument;
1357        direction = ScrollDown;
1358    } else {
1359        switch (ev->key()) {
1360            case Qt::Key_Up:
1361                granularity = ScrollByLine;
1362                direction = ScrollUp;
1363                break;
1364            case Qt::Key_Down:
1365                granularity = ScrollByLine;
1366                direction = ScrollDown;
1367                break;
1368            case Qt::Key_Left:
1369                granularity = ScrollByLine;
1370                direction = ScrollLeft;
1371                break;
1372            case Qt::Key_Right:
1373                granularity = ScrollByLine;
1374                direction = ScrollRight;
1375                break;
1376            default:
1377                return false;
1378        }
1379    }
1380
1381    return frame->eventHandler()->scrollRecursively(direction, granularity);
1382}
1383
1384#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
1385void QWebPagePrivate::touchEvent(QTouchEvent* event)
1386{
1387    WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
1388    if (!frame->view())
1389        return;
1390
1391    bool accepted = frame->eventHandler()->handleTouchEvent(PlatformTouchEvent(event));
1392    event->setAccepted(accepted);
1393}
1394#endif
1395
1396/*!
1397  This method is used by the input method to query a set of properties of the page
1398  to be able to support complex input method operations as support for surrounding
1399  text and reconversions.
1400
1401  \a property specifies which property is queried.
1402
1403  \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
1404*/
1405QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1406{
1407    Frame* frame = d->page->focusController()->focusedFrame();
1408    if (!frame)
1409        return QVariant();
1410
1411    WebCore::Editor* editor = frame->editor();
1412
1413    RenderObject* renderer = 0;
1414    RenderTextControl* renderTextControl = 0;
1415
1416    if (frame->selection()->rootEditableElement())
1417        renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1418
1419    if (renderer && renderer->isTextControl())
1420        renderTextControl = toRenderTextControl(renderer);
1421
1422    switch (property) {
1423        case Qt::ImMicroFocus: {
1424            WebCore::FrameView* view = frame->view();
1425            if (view && view->needsLayout()) {
1426                // We can't access absoluteCaretBounds() while the view needs to layout.
1427                return QVariant();
1428            }
1429            return QVariant(frame->selection()->absoluteCaretBounds());
1430        }
1431        case Qt::ImFont: {
1432            if (renderTextControl) {
1433                RenderStyle* renderStyle = renderTextControl->style();
1434                return QVariant(QFont(renderStyle->font().font()));
1435            }
1436            return QVariant(QFont());
1437        }
1438        case Qt::ImCursorPosition: {
1439            if (renderTextControl) {
1440                if (editor->hasComposition()) {
1441                    RefPtr<Range> range = editor->compositionRange();
1442                    return QVariant(renderTextControl->selectionEnd() - TextIterator::rangeLength(range.get()));
1443                }
1444                return QVariant(renderTextControl->selectionEnd());
1445            }
1446            return QVariant();
1447        }
1448        case Qt::ImSurroundingText: {
1449            if (renderTextControl) {
1450                QString text = renderTextControl->text();
1451                RefPtr<Range> range = editor->compositionRange();
1452                if (range) {
1453                    text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get()));
1454                }
1455                return QVariant(text);
1456            }
1457            return QVariant();
1458        }
1459        case Qt::ImCurrentSelection: {
1460            if (renderTextControl) {
1461                int start = renderTextControl->selectionStart();
1462                int end = renderTextControl->selectionEnd();
1463                if (end > start)
1464                    return QVariant(QString(renderTextControl->text()).mid(start,end-start));
1465            }
1466            return QVariant();
1467
1468        }
1469#if QT_VERSION >= 0x040600
1470        case Qt::ImAnchorPosition: {
1471            if (renderTextControl) {
1472                if (editor->hasComposition()) {
1473                    RefPtr<Range> range = editor->compositionRange();
1474                    return QVariant(renderTextControl->selectionStart() - TextIterator::rangeLength(range.get()));
1475                }
1476                return QVariant(renderTextControl->selectionStart());
1477            }
1478            return QVariant();
1479        }
1480        case Qt::ImMaximumTextLength: {
1481            if (frame->selection()->isContentEditable()) {
1482                if (frame->document() && frame->document()->focusedNode()) {
1483                    if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
1484                        HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
1485                        return QVariant(inputElement->maxLength());
1486                    }
1487                }
1488                return QVariant(InputElement::s_maximumLength);
1489            }
1490            return QVariant(0);
1491        }
1492#endif
1493        default:
1494            return QVariant();
1495    }
1496}
1497
1498/*!
1499    \internal
1500*/
1501void QWebPagePrivate::setInspector(QWebInspector* insp)
1502{
1503    if (inspector)
1504        inspector->d->setFrontend(0);
1505
1506    if (inspectorIsInternalOnly) {
1507        QWebInspector* inspToDelete = inspector;
1508        inspector = 0;
1509        inspectorIsInternalOnly = false;
1510        delete inspToDelete;    // Delete after to prevent infinite recursion
1511    }
1512
1513    inspector = insp;
1514
1515    // Give inspector frontend web view if previously created
1516    if (inspector && inspectorFrontend)
1517        inspector->d->setFrontend(inspectorFrontend);
1518}
1519
1520/*!
1521    \internal
1522    Returns the inspector and creates it if it wasn't created yet.
1523    The instance created here will not be available through QWebPage's API.
1524*/
1525QWebInspector* QWebPagePrivate::getOrCreateInspector()
1526{
1527#if ENABLE(INSPECTOR)
1528    if (!inspector) {
1529        QWebInspector* insp = new QWebInspector;
1530        insp->setPage(q);
1531        inspectorIsInternalOnly = true;
1532
1533        Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1534    }
1535#endif
1536    return inspector;
1537}
1538
1539/*! \internal */
1540InspectorController* QWebPagePrivate::inspectorController()
1541{
1542#if ENABLE(INSPECTOR)
1543    return page->inspectorController();
1544#else
1545    return 0;
1546#endif
1547}
1548
1549
1550/*!
1551   \enum QWebPage::FindFlag
1552
1553   This enum describes the options available to QWebPage's findText() function. The options
1554   can be OR-ed together from the following list:
1555
1556   \value FindBackward Searches backwards instead of forwards.
1557   \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1558   changes the behaviour to a case sensitive find operation.
1559   \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1560   was reached and the text was not found.
1561   \value HighlightAllOccurrences Highlights all existing occurrences of a specific string.
1562*/
1563
1564/*!
1565    \enum QWebPage::LinkDelegationPolicy
1566
1567    This enum defines the delegation policies a webpage can have when activating links and emitting
1568    the linkClicked() signal.
1569
1570    \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1571    \value DelegateExternalLinks When activating links that point to documents not stored on the
1572    local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1573    \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1574*/
1575
1576/*!
1577    \enum QWebPage::NavigationType
1578
1579    This enum describes the types of navigation available when browsing through hyperlinked
1580    documents.
1581
1582    \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1583    \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1584    \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1585    \value NavigationTypeReload The user activated the reload action.
1586    \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1587    \value NavigationTypeOther A navigation to another document using a method not listed above.
1588*/
1589
1590/*!
1591    \enum QWebPage::WebAction
1592
1593    This enum describes the types of action which can be performed on the web page.
1594
1595    Actions only have an effect when they are applicable. The availability of
1596    actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1597    action returned by \l{QWebPage::}{action()}.
1598
1599    One method of enabling the text editing, cursor movement, and text selection actions
1600    is by setting \l contentEditable to true.
1601
1602    \value NoWebAction No action is triggered.
1603    \value OpenLink Open the current link.
1604    \value OpenLinkInNewWindow Open the current link in a new window.
1605    \value OpenFrameInNewWindow Replicate the current frame in a new window.
1606    \value DownloadLinkToDisk Download the current link to the disk.
1607    \value CopyLinkToClipboard Copy the current link to the clipboard.
1608    \value OpenImageInNewWindow Open the highlighted image in a new window.
1609    \value DownloadImageToDisk Download the highlighted image to the disk.
1610    \value CopyImageToClipboard Copy the highlighted image to the clipboard.
1611    \value Back Navigate back in the history of navigated links.
1612    \value Forward Navigate forward in the history of navigated links.
1613    \value Stop Stop loading the current page.
1614    \value Reload Reload the current page.
1615    \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1616    \value Cut Cut the content currently selected into the clipboard.
1617    \value Copy Copy the content currently selected into the clipboard.
1618    \value Paste Paste content from the clipboard.
1619    \value Undo Undo the last editing action.
1620    \value Redo Redo the last editing action.
1621    \value MoveToNextChar Move the cursor to the next character.
1622    \value MoveToPreviousChar Move the cursor to the previous character.
1623    \value MoveToNextWord Move the cursor to the next word.
1624    \value MoveToPreviousWord Move the cursor to the previous word.
1625    \value MoveToNextLine Move the cursor to the next line.
1626    \value MoveToPreviousLine Move the cursor to the previous line.
1627    \value MoveToStartOfLine Move the cursor to the start of the line.
1628    \value MoveToEndOfLine Move the cursor to the end of the line.
1629    \value MoveToStartOfBlock Move the cursor to the start of the block.
1630    \value MoveToEndOfBlock Move the cursor to the end of the block.
1631    \value MoveToStartOfDocument Move the cursor to the start of the document.
1632    \value MoveToEndOfDocument Move the cursor to the end of the document.
1633    \value SelectNextChar Select to the next character.
1634    \value SelectPreviousChar Select to the previous character.
1635    \value SelectNextWord Select to the next word.
1636    \value SelectPreviousWord Select to the previous word.
1637    \value SelectNextLine Select to the next line.
1638    \value SelectPreviousLine Select to the previous line.
1639    \value SelectStartOfLine Select to the start of the line.
1640    \value SelectEndOfLine Select to the end of the line.
1641    \value SelectStartOfBlock Select to the start of the block.
1642    \value SelectEndOfBlock Select to the end of the block.
1643    \value SelectStartOfDocument Select to the start of the document.
1644    \value SelectEndOfDocument Select to the end of the document.
1645    \value DeleteStartOfWord Delete to the start of the word.
1646    \value DeleteEndOfWord Delete to the end of the word.
1647    \value SetTextDirectionDefault Set the text direction to the default direction.
1648    \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1649    \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1650    \value ToggleBold Toggle the formatting between bold and normal weight.
1651    \value ToggleItalic Toggle the formatting between italic and normal style.
1652    \value ToggleUnderline Toggle underlining.
1653    \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1654    \value InsertParagraphSeparator Insert a new paragraph.
1655    \value InsertLineSeparator Insert a new line.
1656    \value SelectAll Selects all content.
1657    \value PasteAndMatchStyle Paste content from the clipboard with current style.
1658    \value RemoveFormat Removes formatting and style.
1659    \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style.
1660    \value ToggleSubscript Toggle the formatting between subscript and baseline.
1661    \value ToggleSuperscript Toggle the formatting between supercript and baseline.
1662    \value InsertUnorderedList Toggles the selection between an ordered list and a normal block.
1663    \value InsertOrderedList Toggles the selection between an ordered list and a normal block.
1664    \value Indent Increases the indentation of the currently selected format block by one increment.
1665    \value Outdent Decreases the indentation of the currently selected format block by one increment.
1666    \value AlignCenter Applies center alignment to content.
1667    \value AlignJustified Applies full justification to content.
1668    \value AlignLeft Applies left justification to content.
1669    \value AlignRight Applies right justification to content.
1670
1671
1672    \omitvalue WebActionCount
1673
1674*/
1675
1676/*!
1677    \enum QWebPage::WebWindowType
1678
1679    \value WebBrowserWindow The window is a regular web browser window.
1680    \value WebModalDialog The window acts as modal dialog.
1681*/
1682
1683/*!
1684    \class QWebPage
1685    \since 4.4
1686    \brief The QWebPage class provides an object to view and edit web documents.
1687
1688    \inmodule QtWebKit
1689
1690    QWebPage holds a main frame responsible for web content, settings, the history
1691    of navigated links and actions. This class can be used, together with QWebFrame,
1692    to provide functionality like QWebView in a widget-less environment.
1693
1694    QWebPage's API is very similar to QWebView, as you are still provided with
1695    common functions like action() (known as \l{QWebView::}{pageAction()} in
1696    QWebView), triggerAction(), findText() and settings(). More QWebView-like
1697    functions can be found in the main frame of QWebPage, obtained via
1698    QWebPage::mainFrame(). For example, the load(), setUrl() and setHtml()
1699    unctions for QWebPage can be accessed using QWebFrame.
1700
1701    The loadStarted() signal is emitted when the page begins to load.The
1702    loadProgress() signal, on the other hand, is emitted whenever an element
1703    of the web page completes loading, such as an embedded image, a script,
1704    etc. Finally, the loadFinished() signal is emitted when the page has
1705    loaded completely. Its argument, either true or false, indicates whether
1706    or not the load operation succeeded.
1707
1708    \section1 Using QWebPage in a Widget-less Environment
1709
1710    Before you begin painting a QWebPage object, you need to set the size of
1711    the viewport by calling setViewportSize(). Then, you invoke the main
1712    frame's render function (QWebFrame::render()). An example of this
1713    is shown in the code snippet below.
1714
1715    Suppose we have a \c Thumbnail class as follows:
1716
1717    \snippet webkitsnippets/webpage/main.cpp 0
1718
1719    The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1720    object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1721    \c render().
1722
1723    \snippet webkitsnippets/webpage/main.cpp 1
1724
1725    The \c render() function shows how we can paint a thumbnail using a
1726    QWebPage object.
1727
1728    \snippet webkitsnippets/webpage/main.cpp 2
1729
1730    We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1731    then we instantiate a QImage object, \c image, with the same size as our
1732    \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1733    as a parameter to \c painter. Next, we render the contents of the main
1734    frame and its subframes into \c painter. Finally, we save the scaled image.
1735
1736    \sa QWebFrame
1737*/
1738
1739/*!
1740    Constructs an empty QWebPage with parent \a parent.
1741*/
1742QWebPage::QWebPage(QObject *parent)
1743    : QObject(parent)
1744    , d(new QWebPagePrivate(this))
1745{
1746    setView(qobject_cast<QWidget *>(parent));
1747
1748    connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1749#ifndef NDEBUG
1750    connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1751#endif
1752}
1753
1754/*!
1755    Destroys the web page.
1756*/
1757QWebPage::~QWebPage()
1758{
1759    d->createMainFrame();
1760    FrameLoader *loader = d->mainFrame->d->frame->loader();
1761    if (loader)
1762        loader->detachFromParent();
1763    if (d->inspector) {
1764        // Since we have to delete an internal inspector,
1765        // call setInspector(0) directly to prevent potential crashes
1766        if (d->inspectorIsInternalOnly)
1767            d->setInspector(0);
1768        else
1769            d->inspector->setPage(0);
1770    }
1771    delete d;
1772}
1773
1774/*!
1775    Returns the main frame of the page.
1776
1777    The main frame provides access to the hierarchy of sub-frames and is also needed if you
1778    want to explicitly render a web page into a given painter.
1779
1780    \sa currentFrame()
1781*/
1782QWebFrame *QWebPage::mainFrame() const
1783{
1784    d->createMainFrame();
1785    return d->mainFrame;
1786}
1787
1788/*!
1789    Returns the frame currently active.
1790
1791    \sa mainFrame(), frameCreated()
1792*/
1793QWebFrame *QWebPage::currentFrame() const
1794{
1795    d->createMainFrame();
1796    return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame();
1797}
1798
1799
1800/*!
1801    \since 4.6
1802
1803    Returns the frame at the given point \a pos.
1804
1805    \sa mainFrame(), currentFrame()
1806*/
1807QWebFrame* QWebPage::frameAt(const QPoint& pos) const
1808{
1809    QWebFrame* webFrame = mainFrame();
1810    if (!webFrame->geometry().contains(pos))
1811        return 0;
1812    QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
1813    return hitTestResult.frame();
1814}
1815
1816/*!
1817    Returns a pointer to the view's history of navigated web pages.
1818*/
1819QWebHistory *QWebPage::history() const
1820{
1821    d->createMainFrame();
1822    return &d->history;
1823}
1824
1825/*!
1826    Sets the \a view that is associated with the web page.
1827
1828    \sa view()
1829*/
1830void QWebPage::setView(QWidget *view)
1831{
1832    if (this->view() != view) {
1833        d->view = view;
1834        if (!view) {
1835            delete d->client;
1836            d->client = 0;
1837        } else {
1838            if (!d->client)
1839                d->client = new QWebPageWidgetClient(view);
1840            else
1841                static_cast<QWebPageWidgetClient*>(d->client)->view = view;
1842        }
1843        setViewportSize(view ? view->size() : QSize(0, 0));
1844    }
1845}
1846
1847/*!
1848    Returns the view widget that is associated with the web page.
1849
1850    \sa setView()
1851*/
1852QWidget *QWebPage::view() const
1853{
1854#if QT_VERSION < 0x040600
1855    return d->view;
1856#else
1857    return d->view.data();
1858#endif
1859}
1860
1861/*!
1862    This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
1863
1864    For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
1865
1866    The default implementation prints nothing.
1867*/
1868void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
1869{
1870    Q_UNUSED(message)
1871    Q_UNUSED(lineNumber)
1872    Q_UNUSED(sourceID)
1873}
1874
1875/*!
1876    This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
1877    the message \a msg.
1878
1879    The default implementation shows the message, \a msg, with QMessageBox::information.
1880*/
1881void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
1882{
1883    Q_UNUSED(frame)
1884#ifndef QT_NO_MESSAGEBOX
1885    QMessageBox::information(view(), tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Ok);
1886#endif
1887}
1888
1889/*!
1890    This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
1891    with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
1892
1893    The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1894*/
1895bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
1896{
1897    Q_UNUSED(frame)
1898#ifdef QT_NO_MESSAGEBOX
1899    return true;
1900#else
1901    return QMessageBox::Yes == QMessageBox::information(view(), tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Yes, QMessageBox::No);
1902#endif
1903}
1904
1905/*!
1906    This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
1907    The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
1908
1909    If the prompt was cancelled by the user the implementation should return false; otherwise the
1910    result should be written to \a result and true should be returned. If the prompt was not cancelled by the
1911    user, the implementation should return true and the result string must not be null.
1912
1913    The default implementation uses QInputDialog::getText.
1914*/
1915bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
1916{
1917    Q_UNUSED(frame)
1918    bool ok = false;
1919#ifndef QT_NO_INPUTDIALOG
1920    QString x = QInputDialog::getText(view(), tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QLineEdit::Normal, defaultValue, &ok);
1921    if (ok && result)
1922        *result = x;
1923#endif
1924    return ok;
1925}
1926
1927/*!
1928    \fn bool QWebPage::shouldInterruptJavaScript()
1929    \since 4.6
1930    This function is called when a JavaScript program is running for a long period of time.
1931
1932    If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
1933
1934    The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1935
1936    \warning Because of binary compatibility constraints, this function is not virtual. If you want to
1937    provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript()
1938    slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
1939*/
1940bool QWebPage::shouldInterruptJavaScript()
1941{
1942#ifdef QT_NO_MESSAGEBOX
1943    return false;
1944#else
1945    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);
1946#endif
1947}
1948
1949/*!
1950    This function is called whenever WebKit wants to create a new window of the given \a type, for
1951    example when a JavaScript program requests to open a document in a new window.
1952
1953    If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
1954
1955    If the view associated with the web page is a QWebView object, then the default implementation forwards
1956    the request to QWebView's createWindow() function; otherwise it returns a null pointer.
1957
1958    If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
1959
1960    \sa acceptNavigationRequest()
1961*/
1962QWebPage *QWebPage::createWindow(WebWindowType type)
1963{
1964    QWebView *webView = qobject_cast<QWebView *>(view());
1965    if (webView) {
1966        QWebView *newView = webView->createWindow(type);
1967        if (newView)
1968            return newView->page();
1969    }
1970    return 0;
1971}
1972
1973/*!
1974    This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin".
1975    The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and
1976    child elements to configure the embeddable object.
1977*/
1978QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
1979{
1980    Q_UNUSED(classid)
1981    Q_UNUSED(url)
1982    Q_UNUSED(paramNames)
1983    Q_UNUSED(paramValues)
1984    return 0;
1985}
1986
1987static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
1988{
1989    WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer());
1990    return WebCore::FrameLoadRequest(rr);
1991}
1992
1993static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
1994{
1995    if (Page* oldPage = frame->page()) {
1996        WindowFeatures features;
1997        if (Page* newPage = oldPage->chrome()->createWindow(frame,
1998                frameLoadRequest(url, frame), features))
1999            newPage->chrome()->show();
2000    }
2001}
2002
2003/*!
2004    This function can be called to trigger the specified \a action.
2005    It is also called by QtWebKit if the user triggers the action, for example
2006    through a context menu item.
2007
2008    If \a action is a checkable action then \a checked specified whether the action
2009    is toggled or not.
2010
2011    \sa action()
2012*/
2013void QWebPage::triggerAction(WebAction action, bool)
2014{
2015    WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2016    if (!frame)
2017        return;
2018    WebCore::Editor *editor = frame->editor();
2019    const char *command = 0;
2020
2021    switch (action) {
2022        case OpenLink:
2023            if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
2024                WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
2025                targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
2026                                                                  /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0,
2027                                                                  /*FormState*/ 0, SendReferrer);
2028                break;
2029            }
2030            // fall through
2031        case OpenLinkInNewWindow:
2032            openNewWindow(d->hitTestResult.linkUrl(), frame);
2033            break;
2034        case OpenFrameInNewWindow: {
2035            KURL url = frame->loader()->documentLoader()->unreachableURL();
2036            if (url.isEmpty())
2037                url = frame->loader()->documentLoader()->url();
2038            openNewWindow(url, frame);
2039            break;
2040        }
2041        case CopyLinkToClipboard: {
2042#if defined(Q_WS_X11)
2043            bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
2044            Pasteboard::generalPasteboard()->setSelectionMode(true);
2045            editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2046            Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
2047#endif
2048            editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2049            break;
2050        }
2051        case OpenImageInNewWindow:
2052            openNewWindow(d->hitTestResult.imageUrl(), frame);
2053            break;
2054        case DownloadImageToDisk:
2055            frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
2056            break;
2057        case DownloadLinkToDisk:
2058            frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
2059            break;
2060#ifndef QT_NO_CLIPBOARD
2061        case CopyImageToClipboard:
2062            QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
2063            break;
2064#endif
2065        case Back:
2066            d->page->goBack();
2067            break;
2068        case Forward:
2069            d->page->goForward();
2070            break;
2071        case Stop:
2072            mainFrame()->d->frame->loader()->stopForUserCancel();
2073            break;
2074        case Reload:
2075            mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false);
2076            break;
2077        case ReloadAndBypassCache:
2078            mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true);
2079            break;
2080        case SetTextDirectionDefault:
2081            editor->setBaseWritingDirection(NaturalWritingDirection);
2082            break;
2083        case SetTextDirectionLeftToRight:
2084            editor->setBaseWritingDirection(LeftToRightWritingDirection);
2085            break;
2086        case SetTextDirectionRightToLeft:
2087            editor->setBaseWritingDirection(RightToLeftWritingDirection);
2088            break;
2089        case InspectElement: {
2090#if ENABLE(INSPECTOR)
2091            if (!d->hitTestResult.isNull()) {
2092                d->getOrCreateInspector(); // Make sure the inspector is created
2093                d->inspector->show(); // The inspector is expected to be shown on inspection
2094                d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
2095            }
2096#endif
2097            break;
2098        }
2099        default:
2100            command = QWebPagePrivate::editorCommandForWebActions(action);
2101            break;
2102    }
2103
2104    if (command)
2105        editor->command(command).execute();
2106}
2107
2108QSize QWebPage::viewportSize() const
2109{
2110    if (d->mainFrame && d->mainFrame->d->frame->view())
2111        return d->mainFrame->d->frame->view()->frameRect().size();
2112
2113    return d->viewportSize;
2114}
2115
2116/*!
2117    \property QWebPage::viewportSize
2118    \brief the size of the viewport
2119
2120    The size affects for example the visibility of scrollbars
2121    if the document is larger than the viewport.
2122
2123    By default, for a newly-created Web page, this property contains a size with
2124    zero width and height.
2125*/
2126void QWebPage::setViewportSize(const QSize &size) const
2127{
2128    d->viewportSize = size;
2129
2130    QWebFrame *frame = mainFrame();
2131    if (frame->d->frame && frame->d->frame->view()) {
2132        WebCore::FrameView* view = frame->d->frame->view();
2133        view->setFrameRect(QRect(QPoint(0, 0), size));
2134        view->forceLayout();
2135        view->adjustViewSize();
2136    }
2137}
2138
2139QSize QWebPage::preferredContentsSize() const
2140{
2141    QWebFrame* frame = d->mainFrame;
2142    if (frame) {
2143        WebCore::FrameView* view = frame->d->frame->view();
2144        if (view && view->useFixedLayout())
2145            return d->mainFrame->d->frame->view()->fixedLayoutSize();
2146    }
2147
2148    return d->fixedLayoutSize;
2149}
2150
2151/*!
2152    \property QWebPage::preferredContentsSize
2153    \since 4.6
2154    \brief the size of the fixed layout
2155
2156    The size affects the layout of the page in the viewport.  If set to a fixed size of
2157    1024x768 for example then webkit will layout the page as if the viewport were that size
2158    rather than something different.
2159*/
2160void QWebPage::setPreferredContentsSize(const QSize &size) const
2161{
2162    d->fixedLayoutSize = size;
2163
2164    QWebFrame *frame = mainFrame();
2165    if (frame->d->frame && frame->d->frame->view()) {
2166        WebCore::FrameView* view = frame->d->frame->view();
2167
2168        if (size.isValid()) {
2169            view->setUseFixedLayout(true);
2170            view->setFixedLayoutSize(size);
2171            view->forceLayout();
2172        } else if (view->useFixedLayout()) {
2173            view->setUseFixedLayout(false);
2174            view->forceLayout();
2175        }
2176    }
2177}
2178
2179/*!
2180    \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2181
2182    This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
2183    the specified navigation type \a type.
2184
2185    If \a frame is a null pointer then navigation to a new window is requested. If the request is
2186    accepted createWindow() will be called.
2187
2188    The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
2189    to let QWebPage handle the navigation itself.
2190
2191    \sa createWindow()
2192*/
2193bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2194{
2195    Q_UNUSED(frame)
2196    if (type == NavigationTypeLinkClicked) {
2197        switch (d->linkPolicy) {
2198            case DontDelegateLinks:
2199                return true;
2200
2201            case DelegateExternalLinks:
2202                if (WebCore::SecurityOrigin::shouldTreatURLSchemeAsLocal(request.url().scheme()))
2203                    return true;
2204                emit linkClicked(request.url());
2205                return false;
2206
2207            case DelegateAllLinks:
2208                emit linkClicked(request.url());
2209                return false;
2210        }
2211    }
2212    return true;
2213}
2214
2215/*!
2216    \property QWebPage::selectedText
2217    \brief the text currently selected
2218
2219    By default, this property contains an empty string.
2220
2221    \sa selectionChanged()
2222*/
2223QString QWebPage::selectedText() const
2224{
2225    d->createMainFrame();
2226    return d->page->focusController()->focusedOrMainFrame()->selectedText();
2227}
2228
2229/*!
2230   Returns a QAction for the specified WebAction \a action.
2231
2232   The action is owned by the QWebPage but you can customize the look by
2233   changing its properties.
2234
2235   QWebPage also takes care of implementing the action, so that upon
2236   triggering the corresponding action is performed on the page.
2237
2238   \sa triggerAction()
2239*/
2240QAction *QWebPage::action(WebAction action) const
2241{
2242    if (action == QWebPage::NoWebAction) return 0;
2243    if (d->actions[action])
2244        return d->actions[action];
2245
2246    QString text;
2247    QIcon icon;
2248    QStyle *style = view() ? view()->style() : qApp->style();
2249    bool checkable = false;
2250
2251    switch (action) {
2252        case OpenLink:
2253            text = contextMenuItemTagOpenLink();
2254            break;
2255        case OpenLinkInNewWindow:
2256            text = contextMenuItemTagOpenLinkInNewWindow();
2257            break;
2258        case OpenFrameInNewWindow:
2259            text = contextMenuItemTagOpenFrameInNewWindow();
2260            break;
2261
2262        case DownloadLinkToDisk:
2263            text = contextMenuItemTagDownloadLinkToDisk();
2264            break;
2265        case CopyLinkToClipboard:
2266            text = contextMenuItemTagCopyLinkToClipboard();
2267            break;
2268
2269        case OpenImageInNewWindow:
2270            text = contextMenuItemTagOpenImageInNewWindow();
2271            break;
2272        case DownloadImageToDisk:
2273            text = contextMenuItemTagDownloadImageToDisk();
2274            break;
2275        case CopyImageToClipboard:
2276            text = contextMenuItemTagCopyImageToClipboard();
2277            break;
2278
2279        case Back:
2280            text = contextMenuItemTagGoBack();
2281            icon = style->standardIcon(QStyle::SP_ArrowBack);
2282            break;
2283        case Forward:
2284            text = contextMenuItemTagGoForward();
2285            icon = style->standardIcon(QStyle::SP_ArrowForward);
2286            break;
2287        case Stop:
2288            text = contextMenuItemTagStop();
2289            icon = style->standardIcon(QStyle::SP_BrowserStop);
2290            break;
2291        case Reload:
2292            text = contextMenuItemTagReload();
2293            icon = style->standardIcon(QStyle::SP_BrowserReload);
2294            break;
2295
2296        case Cut:
2297            text = contextMenuItemTagCut();
2298            break;
2299        case Copy:
2300            text = contextMenuItemTagCopy();
2301            break;
2302        case Paste:
2303            text = contextMenuItemTagPaste();
2304            break;
2305#ifndef QT_NO_UNDOSTACK
2306        case Undo: {
2307            QAction *a = undoStack()->createUndoAction(d->q);
2308            d->actions[action] = a;
2309            return a;
2310        }
2311        case Redo: {
2312            QAction *a = undoStack()->createRedoAction(d->q);
2313            d->actions[action] = a;
2314            return a;
2315        }
2316#endif // QT_NO_UNDOSTACK
2317        case MoveToNextChar:
2318            text = tr("Move the cursor to the next character");
2319            break;
2320        case MoveToPreviousChar:
2321            text = tr("Move the cursor to the previous character");
2322            break;
2323        case MoveToNextWord:
2324            text = tr("Move the cursor to the next word");
2325            break;
2326        case MoveToPreviousWord:
2327            text = tr("Move the cursor to the previous word");
2328            break;
2329        case MoveToNextLine:
2330            text = tr("Move the cursor to the next line");
2331            break;
2332        case MoveToPreviousLine:
2333            text = tr("Move the cursor to the previous line");
2334            break;
2335        case MoveToStartOfLine:
2336            text = tr("Move the cursor to the start of the line");
2337            break;
2338        case MoveToEndOfLine:
2339            text = tr("Move the cursor to the end of the line");
2340            break;
2341        case MoveToStartOfBlock:
2342            text = tr("Move the cursor to the start of the block");
2343            break;
2344        case MoveToEndOfBlock:
2345            text = tr("Move the cursor to the end of the block");
2346            break;
2347        case MoveToStartOfDocument:
2348            text = tr("Move the cursor to the start of the document");
2349            break;
2350        case MoveToEndOfDocument:
2351            text = tr("Move the cursor to the end of the document");
2352            break;
2353        case SelectAll:
2354            text = tr("Select all");
2355            break;
2356        case SelectNextChar:
2357            text = tr("Select to the next character");
2358            break;
2359        case SelectPreviousChar:
2360            text = tr("Select to the previous character");
2361            break;
2362        case SelectNextWord:
2363            text = tr("Select to the next word");
2364            break;
2365        case SelectPreviousWord:
2366            text = tr("Select to the previous word");
2367            break;
2368        case SelectNextLine:
2369            text = tr("Select to the next line");
2370            break;
2371        case SelectPreviousLine:
2372            text = tr("Select to the previous line");
2373            break;
2374        case SelectStartOfLine:
2375            text = tr("Select to the start of the line");
2376            break;
2377        case SelectEndOfLine:
2378            text = tr("Select to the end of the line");
2379            break;
2380        case SelectStartOfBlock:
2381            text = tr("Select to the start of the block");
2382            break;
2383        case SelectEndOfBlock:
2384            text = tr("Select to the end of the block");
2385            break;
2386        case SelectStartOfDocument:
2387            text = tr("Select to the start of the document");
2388            break;
2389        case SelectEndOfDocument:
2390            text = tr("Select to the end of the document");
2391            break;
2392        case DeleteStartOfWord:
2393            text = tr("Delete to the start of the word");
2394            break;
2395        case DeleteEndOfWord:
2396            text = tr("Delete to the end of the word");
2397            break;
2398
2399        case SetTextDirectionDefault:
2400            text = contextMenuItemTagDefaultDirection();
2401            break;
2402        case SetTextDirectionLeftToRight:
2403            text = contextMenuItemTagLeftToRight();
2404            checkable = true;
2405            break;
2406        case SetTextDirectionRightToLeft:
2407            text = contextMenuItemTagRightToLeft();
2408            checkable = true;
2409            break;
2410
2411        case ToggleBold:
2412            text = contextMenuItemTagBold();
2413            checkable = true;
2414            break;
2415        case ToggleItalic:
2416            text = contextMenuItemTagItalic();
2417            checkable = true;
2418            break;
2419        case ToggleUnderline:
2420            text = contextMenuItemTagUnderline();
2421            checkable = true;
2422            break;
2423
2424        case InspectElement:
2425            text = contextMenuItemTagInspectElement();
2426            break;
2427
2428        case InsertParagraphSeparator:
2429            text = tr("Insert a new paragraph");
2430            break;
2431        case InsertLineSeparator:
2432            text = tr("Insert a new line");
2433            break;
2434
2435        case PasteAndMatchStyle:
2436            text = tr("Paste and Match Style");
2437            break;
2438        case RemoveFormat:
2439            text = tr("Remove formatting");
2440            break;
2441
2442        case ToggleStrikethrough:
2443            text = tr("Strikethrough");
2444            checkable = true;
2445            break;
2446        case ToggleSubscript:
2447            text = tr("Subscript");
2448            checkable = true;
2449            break;
2450        case ToggleSuperscript:
2451            text = tr("Superscript");
2452            checkable = true;
2453            break;
2454        case InsertUnorderedList:
2455            text = tr("Insert Bulleted List");
2456            checkable = true;
2457            break;
2458        case InsertOrderedList:
2459            text = tr("Insert Numbered List");
2460            checkable = true;
2461            break;
2462        case Indent:
2463            text = tr("Indent");
2464            break;
2465        case Outdent:
2466            text = tr("Outdent");
2467            break;
2468        case AlignCenter:
2469            text = tr("Center");
2470            break;
2471        case AlignJustified:
2472            text = tr("Justify");
2473            break;
2474        case AlignLeft:
2475            text = tr("Align Left");
2476            break;
2477        case AlignRight:
2478            text = tr("Align Right");
2479            break;
2480
2481        case NoWebAction:
2482            return 0;
2483    }
2484
2485    if (text.isEmpty())
2486        return 0;
2487
2488    QAction *a = new QAction(d->q);
2489    a->setText(text);
2490    a->setData(action);
2491    a->setCheckable(checkable);
2492    a->setIcon(icon);
2493
2494    connect(a, SIGNAL(triggered(bool)),
2495            this, SLOT(_q_webActionTriggered(bool)));
2496
2497    d->actions[action] = a;
2498    d->updateAction(action);
2499    return a;
2500}
2501
2502/*!
2503    \property QWebPage::modified
2504    \brief whether the page contains unsubmitted form data
2505
2506    By default, this property is false.
2507*/
2508bool QWebPage::isModified() const
2509{
2510#ifdef QT_NO_UNDOSTACK
2511    return false;
2512#else
2513    if (!d->undoStack)
2514        return false;
2515    return d->undoStack->canUndo();
2516#endif // QT_NO_UNDOSTACK
2517}
2518
2519#ifndef QT_NO_UNDOSTACK
2520/*!
2521    Returns a pointer to the undo stack used for editable content.
2522*/
2523QUndoStack *QWebPage::undoStack() const
2524{
2525    if (!d->undoStack)
2526        d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
2527
2528    return d->undoStack;
2529}
2530#endif // QT_NO_UNDOSTACK
2531
2532/*! \reimp
2533*/
2534bool QWebPage::event(QEvent *ev)
2535{
2536    switch (ev->type()) {
2537    case QEvent::Timer:
2538        d->timerEvent(static_cast<QTimerEvent*>(ev));
2539        break;
2540    case QEvent::MouseMove:
2541        d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
2542        break;
2543    case QEvent::GraphicsSceneMouseMove:
2544        d->mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2545        break;
2546    case QEvent::MouseButtonPress:
2547        d->mousePressEvent(static_cast<QMouseEvent*>(ev));
2548        break;
2549    case QEvent::GraphicsSceneMousePress:
2550        d->mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2551        break;
2552    case QEvent::MouseButtonDblClick:
2553        d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
2554        break;
2555    case QEvent::GraphicsSceneMouseDoubleClick:
2556        d->mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2557        break;
2558    case QEvent::MouseButtonRelease:
2559        d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
2560        break;
2561    case QEvent::GraphicsSceneMouseRelease:
2562        d->mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2563        break;
2564#ifndef QT_NO_CONTEXTMENU
2565    case QEvent::ContextMenu:
2566        d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos());
2567        break;
2568    case QEvent::GraphicsSceneContextMenu:
2569        d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos());
2570        break;
2571#endif
2572#ifndef QT_NO_WHEELEVENT
2573    case QEvent::Wheel:
2574        d->wheelEvent(static_cast<QWheelEvent*>(ev));
2575        break;
2576    case QEvent::GraphicsSceneWheel:
2577        d->wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(ev));
2578        break;
2579#endif
2580    case QEvent::KeyPress:
2581        d->keyPressEvent(static_cast<QKeyEvent*>(ev));
2582        break;
2583    case QEvent::KeyRelease:
2584        d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
2585        break;
2586    case QEvent::FocusIn:
2587        d->focusInEvent(static_cast<QFocusEvent*>(ev));
2588        break;
2589    case QEvent::FocusOut:
2590        d->focusOutEvent(static_cast<QFocusEvent*>(ev));
2591        break;
2592#ifndef QT_NO_DRAGANDDROP
2593    case QEvent::DragEnter:
2594        d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
2595        break;
2596    case QEvent::GraphicsSceneDragEnter:
2597        d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2598        break;
2599    case QEvent::DragLeave:
2600        d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
2601        break;
2602    case QEvent::GraphicsSceneDragLeave:
2603        d->dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2604        break;
2605    case QEvent::DragMove:
2606        d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
2607        break;
2608    case QEvent::GraphicsSceneDragMove:
2609        d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2610        break;
2611    case QEvent::Drop:
2612        d->dropEvent(static_cast<QDropEvent*>(ev));
2613        break;
2614    case QEvent::GraphicsSceneDrop:
2615        d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2616        break;
2617#endif
2618    case QEvent::InputMethod:
2619        d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
2620    case QEvent::ShortcutOverride:
2621        d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
2622        break;
2623    case QEvent::Leave:
2624        d->leaveEvent(ev);
2625        break;
2626#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
2627    case QEvent::TouchBegin:
2628    case QEvent::TouchUpdate:
2629    case QEvent::TouchEnd:
2630        d->touchEvent(static_cast<QTouchEvent*>(ev));
2631        break;
2632#endif
2633    default:
2634        return QObject::event(ev);
2635    }
2636
2637    return true;
2638}
2639
2640/*!
2641    Similar to QWidget::focusNextPrevChild it focuses the next focusable web element
2642    if \a next is true; otherwise the previous element is focused.
2643
2644    Returns true if it can find a new focusable element, or false if it can't.
2645*/
2646bool QWebPage::focusNextPrevChild(bool next)
2647{
2648    QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
2649    d->keyPressEvent(&ev);
2650    bool hasFocusedNode = false;
2651    Frame *frame = d->page->focusController()->focusedFrame();
2652    if (frame) {
2653        Document *document = frame->document();
2654        hasFocusedNode = document && document->focusedNode();
2655    }
2656    //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
2657    return hasFocusedNode;
2658}
2659
2660/*!
2661    \property QWebPage::contentEditable
2662    \brief whether the content in this QWebPage is editable or not
2663    \since 4.5
2664
2665    If this property is enabled the contents of the page can be edited by the user through a visible
2666    cursor. If disabled (the default) only HTML elements in the web page with their
2667    \c{contenteditable} attribute set are editable.
2668*/
2669void QWebPage::setContentEditable(bool editable)
2670{
2671    if (d->editable != editable) {
2672        d->editable = editable;
2673        d->page->setTabKeyCyclesThroughElements(!editable);
2674        if (d->mainFrame) {
2675            WebCore::Frame* frame = d->mainFrame->d->frame;
2676            if (editable) {
2677                frame->applyEditingStyleToBodyElement();
2678                // FIXME: mac port calls this if there is no selectedDOMRange
2679                //frame->setSelectionFromNone();
2680            } else
2681                frame->removeEditingStyleFromBodyElement();
2682        }
2683
2684        d->updateEditorActions();
2685    }
2686}
2687
2688bool QWebPage::isContentEditable() const
2689{
2690    return d->editable;
2691}
2692
2693/*!
2694    \property QWebPage::forwardUnsupportedContent
2695    \brief whether QWebPage should forward unsupported content
2696
2697    If enabled, the unsupportedContent() signal is emitted with a network reply that
2698    can be used to read the content.
2699
2700    If disabled, the download of such content is aborted immediately.
2701
2702    By default unsupported content is not forwarded.
2703*/
2704
2705void QWebPage::setForwardUnsupportedContent(bool forward)
2706{
2707    d->forwardUnsupportedContent = forward;
2708}
2709
2710bool QWebPage::forwardUnsupportedContent() const
2711{
2712    return d->forwardUnsupportedContent;
2713}
2714
2715/*!
2716    \property QWebPage::linkDelegationPolicy
2717    \brief how QWebPage should delegate the handling of links through the
2718    linkClicked() signal
2719
2720    The default is to delegate no links.
2721*/
2722
2723void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
2724{
2725    d->linkPolicy = policy;
2726}
2727
2728QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
2729{
2730    return d->linkPolicy;
2731}
2732
2733#ifndef QT_NO_CONTEXTMENU
2734/*!
2735    Filters the context menu event, \a event, through handlers for scrollbars and
2736    custom event handlers in the web page. Returns true if the event was handled;
2737    otherwise false.
2738
2739    A web page may swallow a context menu event through a custom event handler, allowing for context
2740    menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
2741    Maps}, for example.
2742*/
2743bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
2744{
2745    d->page->contextMenuController()->clearContextMenu();
2746
2747    if (QWebFrame* webFrame = frameAt(event->pos())) {
2748        Frame* frame = QWebFramePrivate::core(webFrame);
2749        if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).pos()))
2750            return scrollbar->contextMenu(PlatformMouseEvent(event, 1));
2751    }
2752
2753    WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
2754    focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
2755    ContextMenu *menu = d->page->contextMenuController()->contextMenu();
2756    // If the website defines its own handler then sendContextMenuEvent takes care of
2757    // calling/showing it and the context menu pointer will be zero. This is the case
2758    // on maps.google.com for example.
2759
2760    return !menu;
2761}
2762#endif // QT_NO_CONTEXTMENU
2763
2764/*!
2765    Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
2766    element the CopyImageToClipboard action is enabled.
2767*/
2768void QWebPage::updatePositionDependentActions(const QPoint &pos)
2769{
2770    // First we disable all actions, but keep track of which ones were originally enabled.
2771    QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
2772    for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
2773        QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
2774        if (QAction *a = this->action(action)) {
2775            originallyEnabledWebActions.setBit(action, a->isEnabled());
2776            a->setEnabled(false);
2777        }
2778    }
2779
2780    d->createMainFrame();
2781    WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
2782    HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
2783
2784    if (result.scrollbar())
2785        d->hitTestResult = QWebHitTestResult();
2786    else
2787        d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
2788    WebCore::ContextMenu menu(result);
2789    menu.populate();
2790
2791#if ENABLE(INSPECTOR)
2792    if (d->page->inspectorController()->enabled())
2793        menu.addInspectElementItem();
2794#endif
2795
2796    QBitArray visitedWebActions(QWebPage::WebActionCount);
2797
2798#ifndef QT_NO_CONTEXTMENU
2799    delete d->currentContextMenu;
2800
2801    // Then we let createContextMenu() enable the actions that are put into the menu
2802    d->currentContextMenu = d->createContextMenu(&menu, menu.platformDescription(), &visitedWebActions);
2803#endif // QT_NO_CONTEXTMENU
2804
2805    // Finally, we restore the original enablement for the actions that were not put into the menu.
2806    originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
2807    for (int i = 0; i < QWebPage::WebActionCount; ++i) {
2808        if (originallyEnabledWebActions.at(i)) {
2809            if (QAction *a = this->action(QWebPage::WebAction(i)))
2810                a->setEnabled(true);
2811        }
2812    }
2813
2814    // This whole process ensures that any actions put into to the context menu has the right
2815    // enablement, while also keeping the correct enablement for actions that were left out of
2816    // the menu.
2817
2818}
2819
2820
2821
2822/*!
2823    \enum QWebPage::Extension
2824
2825    This enum describes the types of extensions that the page can support. Before using these extensions, you
2826    should verify that the extension is supported by calling supportsExtension().
2827
2828    \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection.
2829    This extension is invoked when the web content requests one or more file names, for example
2830    as a result of the user clicking on a "file upload" button in a HTML form where multiple
2831    file selection is allowed.
2832
2833    \omitvalue ErrorPageExtension (introduced in Qt 4.6)
2834*/
2835
2836/*!
2837    \enum QWebPage::ErrorDomain
2838    \since 4.6
2839    \internal
2840
2841    \value QtNetwork
2842    \value Http
2843    \value WebKit
2844*/
2845
2846/*!
2847    \class QWebPage::ExtensionOption
2848    \since 4.4
2849    \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
2850
2851    \inmodule QtWebKit
2852
2853    \sa QWebPage::extension()
2854*/
2855
2856/*!
2857    \class QWebPage::ErrorPageExtensionOption
2858    \since 4.6
2859    \brief The ErrorPageExtensionOption class describes the option
2860    for the error page extension.
2861
2862    \inmodule QtWebKit
2863
2864    The ErrorPageExtensionOption class holds the \a url for which an error occoured as well as
2865    the associated \a frame.
2866
2867    The error itself is reported by an error \a domain, the \a error code as well as \a errorString.
2868
2869    \sa QWebPage::ErrorPageExtensionReturn
2870*/
2871
2872/*!
2873    \class QWebPage::ErrorPageExtensionReturn
2874    \since 4.6
2875    \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the
2876    frame for which the error occured.
2877
2878    \inmodule QtWebKit
2879
2880    The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are
2881    optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which
2882    is assumed to be UTF-8 if not indicated otherwise.
2883
2884    The error page is stored in the \a content byte array, as HTML content. In order to convert a
2885    QString to a byte array, the QString::toUtf8() method can be used.
2886
2887    External objects such as stylesheets or images referenced in the HTML are located relative to
2888    \a baseUrl.
2889
2890    \sa QWebPage::ErrorPageExtensionOption, QString::toUtf8()
2891*/
2892
2893/*!
2894    \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn()
2895
2896    Constructs a new error page object.
2897*/
2898
2899/*!
2900    \class QWebPage::ChooseMultipleFilesExtensionOption
2901    \since 4.5
2902    \brief The ChooseMultipleFilesExtensionOption class describes the option
2903    for the multiple files selection extension.
2904
2905    \inmodule QtWebKit
2906
2907    The ChooseMultipleFilesExtensionOption class holds the frame originating the request
2908    and the suggested filenames which might be provided.
2909
2910    \sa QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn
2911*/
2912
2913/*!
2914    \class QWebPage::ChooseMultipleFilesExtensionReturn
2915    \since 4.5
2916    \brief The ChooseMultipleFilesExtensionReturn describes the return value
2917    for the multiple files selection extension.
2918
2919    \inmodule QtWebKit
2920
2921    The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user
2922    when the extension is invoked.
2923
2924    \sa QWebPage::ChooseMultipleFilesExtensionOption
2925*/
2926
2927/*!
2928    This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
2929    argument is provided as input to the extension; the output results can be stored in \a output.
2930
2931    The behavior of this function is determined by \a extension.
2932
2933    You can call supportsExtension() to check if an extension is supported by the page.
2934
2935    Returns true if the extension was called successfully; otherwise returns false.
2936
2937    \sa supportsExtension(), Extension
2938*/
2939bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
2940{
2941#ifndef QT_NO_FILEDIALOG
2942    if (extension == ChooseMultipleFilesExtension) {
2943        // FIXME: do not ignore suggestedFiles
2944        QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames;
2945        QStringList names = QFileDialog::getOpenFileNames(view(), QString::null);
2946        static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
2947        return true;
2948    }
2949#endif
2950
2951    return false;
2952}
2953
2954/*!
2955    This virtual function returns true if the web page supports \a extension; otherwise false is returned.
2956
2957    \sa extension()
2958*/
2959bool QWebPage::supportsExtension(Extension extension) const
2960{
2961#ifndef QT_NO_FILEDIALOG
2962    return extension == ChooseMultipleFilesExtension;
2963#else
2964    Q_UNUSED(extension);
2965    return false;
2966#endif
2967}
2968
2969/*!
2970    Finds the specified string, \a subString, in the page, using the given \a options.
2971
2972    If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
2973    that exist in the page. All subsequent calls will extend the highlight, rather than
2974    replace it, with occurrences of the new string.
2975
2976    If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
2977    and all subsequent calls will replace the current occurrence with the next one.
2978
2979    To clear the selection, just pass an empty string.
2980
2981    Returns true if \a subString was found; otherwise returns false.
2982*/
2983bool QWebPage::findText(const QString &subString, FindFlags options)
2984{
2985    ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
2986    if (options & FindCaseSensitively)
2987        caseSensitivity = ::TextCaseSensitive;
2988
2989    if (options & HighlightAllOccurrences) {
2990        if (subString.isEmpty()) {
2991            d->page->unmarkAllTextMatches();
2992            return true;
2993        } else
2994            return d->page->markAllMatchesForText(subString, caseSensitivity, true, 0);
2995    } else {
2996        ::FindDirection direction = ::FindDirectionForward;
2997        if (options & FindBackward)
2998            direction = ::FindDirectionBackward;
2999
3000        const bool shouldWrap = options & FindWrapsAroundDocument;
3001
3002        return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
3003    }
3004}
3005
3006/*!
3007    Returns a pointer to the page's settings object.
3008
3009    \sa QWebSettings::globalSettings()
3010*/
3011QWebSettings *QWebPage::settings() const
3012{
3013    return d->settings;
3014}
3015
3016/*!
3017    This function is called when the web content requests a file name, for example
3018    as a result of the user clicking on a "file upload" button in a HTML form.
3019
3020    A suggested filename may be provided in \a suggestedFile. The frame originating the
3021    request is provided as \a parentFrame.
3022*/
3023QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
3024{
3025    Q_UNUSED(parentFrame)
3026#ifndef QT_NO_FILEDIALOG
3027    return QFileDialog::getOpenFileName(view(), QString::null, suggestedFile);
3028#else
3029    return QString::null;
3030#endif
3031}
3032
3033/*!
3034    Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
3035    QWebPage.
3036
3037    \note It is currently not supported to change the network access manager after the
3038    QWebPage has used it. The results of doing this are undefined.
3039
3040    \sa networkAccessManager()
3041*/
3042void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
3043{
3044    if (manager == d->networkManager)
3045        return;
3046    if (d->networkManager && d->networkManager->parent() == this)
3047        delete d->networkManager;
3048    d->networkManager = manager;
3049}
3050
3051/*!
3052    Returns the QNetworkAccessManager that is responsible for serving network
3053    requests for this QWebPage.
3054
3055    \sa setNetworkAccessManager()
3056*/
3057QNetworkAccessManager *QWebPage::networkAccessManager() const
3058{
3059    if (!d->networkManager) {
3060        QWebPage *that = const_cast<QWebPage *>(this);
3061        that->d->networkManager = new QNetworkAccessManager(that);
3062    }
3063    return d->networkManager;
3064}
3065
3066/*!
3067    Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
3068    QWebPage.
3069
3070    Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
3071
3072    \sa pluginFactory()
3073*/
3074void QWebPage::setPluginFactory(QWebPluginFactory *factory)
3075{
3076    d->pluginFactory = factory;
3077}
3078
3079/*!
3080    Returns the QWebPluginFactory that is responsible for creating plugins embedded into
3081    this QWebPage. If no plugin factory is installed a null pointer is returned.
3082
3083    \sa setPluginFactory()
3084*/
3085QWebPluginFactory *QWebPage::pluginFactory() const
3086{
3087    return d->pluginFactory;
3088}
3089
3090/*!
3091    This function is called when a user agent for HTTP requests is needed. You can reimplement this
3092    function to dynamically return different user agents for different URLs, based on the \a url parameter.
3093
3094    The default implementation returns the following value:
3095
3096    "Mozilla/5.0 (%Platform%; %Security%; %Subplatform%; %Locale%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%"
3097
3098    In this string the following values are replaced at run-time:
3099    \list
3100    \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system.
3101    \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true.
3102    \o %Locale% is replaced with QLocale::name(). The locale is determined from the view of the QWebPage. If no view is set on the QWebPage,
3103    then a default constructed QLocale is used instead.
3104    \o %WebKitVersion% is the version of WebKit the application was compiled against.
3105    \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
3106    \endlist
3107*/
3108QString QWebPage::userAgentForUrl(const QUrl& url) const
3109{
3110    Q_UNUSED(url)
3111    QString ua = QLatin1String("Mozilla/5.0 ("
3112
3113    // Platform
3114#ifdef Q_WS_MAC
3115    "Macintosh"
3116#elif defined Q_WS_QWS
3117    "QtEmbedded"
3118#elif defined Q_WS_WIN
3119    "Windows"
3120#elif defined Q_WS_X11
3121    "X11"
3122#elif defined Q_OS_SYMBIAN
3123    "SymbianOS"
3124#else
3125    "Unknown"
3126#endif
3127    // Placeholder for Platform Version
3128    "%1; "
3129
3130    // Placeholder for security strength (N or U)
3131    "%2; "
3132
3133    // Subplatform"
3134#ifdef Q_OS_AIX
3135    "AIX"
3136#elif defined Q_OS_WIN32
3137    "%3"
3138#elif defined Q_OS_DARWIN
3139#ifdef __i386__ || __x86_64__
3140    "Intel Mac OS X"
3141#else
3142    "PPC Mac OS X"
3143#endif
3144
3145#elif defined Q_OS_BSDI
3146    "BSD"
3147#elif defined Q_OS_BSD4
3148    "BSD Four"
3149#elif defined Q_OS_CYGWIN
3150    "Cygwin"
3151#elif defined Q_OS_DGUX
3152    "DG/UX"
3153#elif defined Q_OS_DYNIX
3154    "DYNIX/ptx"
3155#elif defined Q_OS_FREEBSD
3156    "FreeBSD"
3157#elif defined Q_OS_HPUX
3158    "HP-UX"
3159#elif defined Q_OS_HURD
3160    "GNU Hurd"
3161#elif defined Q_OS_IRIX
3162    "SGI Irix"
3163#elif defined Q_OS_LINUX
3164    "Linux"
3165#elif defined Q_OS_LYNX
3166    "LynxOS"
3167#elif defined Q_OS_NETBSD
3168    "NetBSD"
3169#elif defined Q_OS_OS2
3170    "OS/2"
3171#elif defined Q_OS_OPENBSD
3172    "OpenBSD"
3173#elif defined Q_OS_OS2EMX
3174    "OS/2"
3175#elif defined Q_OS_OSF
3176    "HP Tru64 UNIX"
3177#elif defined Q_OS_QNX6
3178    "QNX RTP Six"
3179#elif defined Q_OS_QNX
3180    "QNX"
3181#elif defined Q_OS_RELIANT
3182    "Reliant UNIX"
3183#elif defined Q_OS_SCO
3184    "SCO OpenServer"
3185#elif defined Q_OS_SOLARIS
3186    "Sun Solaris"
3187#elif defined Q_OS_ULTRIX
3188    "DEC Ultrix"
3189#elif defined Q_WS_S60
3190    "Series60"
3191#elif defined Q_OS_UNIX
3192    "UNIX BSD/SYSV system"
3193#elif defined Q_OS_UNIXWARE
3194    "UnixWare Seven, Open UNIX Eight"
3195#else
3196    "Unknown"
3197#endif
3198    // Placeholder for SubPlatform Version
3199    "%4; ");
3200
3201    // Platform Version
3202    QString osVer;
3203#ifdef Q_OS_SYMBIAN
3204    QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
3205    switch (symbianVersion) {
3206    case QSysInfo::SV_9_2:
3207        osVer = "/9.2";
3208        break;
3209    case QSysInfo::SV_9_3:
3210        osVer = "/9.3";
3211        break;
3212    case QSysInfo::SV_9_4:
3213        osVer = "/9.4";
3214        break;
3215    default:
3216        osVer = "Unknown";
3217    }
3218#endif
3219    ua = ua.arg(osVer);
3220
3221    QChar securityStrength(QLatin1Char('N'));
3222#if !defined(QT_NO_OPENSSL)
3223    // we could check QSslSocket::supportsSsl() here, but this makes
3224    // OpenSSL, certificates etc being loaded in all cases were QWebPage
3225    // is used. This loading is not needed for non-https.
3226    securityStrength = QLatin1Char('U');
3227    // this may lead to a false positive: We indicate SSL since it is
3228    // compiled in even though supportsSsl() might return false
3229#endif
3230    ua = ua.arg(securityStrength);
3231
3232#if defined Q_OS_WIN32
3233    QString ver;
3234    switch (QSysInfo::WindowsVersion) {
3235        case QSysInfo::WV_32s:
3236            ver = "Windows 3.1";
3237            break;
3238        case QSysInfo::WV_95:
3239            ver = "Windows 95";
3240            break;
3241        case QSysInfo::WV_98:
3242            ver = "Windows 98";
3243            break;
3244        case QSysInfo::WV_Me:
3245            ver = "Windows 98; Win 9x 4.90";
3246            break;
3247        case QSysInfo::WV_NT:
3248            ver = "WinNT4.0";
3249            break;
3250        case QSysInfo::WV_2000:
3251            ver = "Windows NT 5.0";
3252            break;
3253        case QSysInfo::WV_XP:
3254            ver = "Windows NT 5.1";
3255            break;
3256        case QSysInfo::WV_2003:
3257            ver = "Windows NT 5.2";
3258            break;
3259        case QSysInfo::WV_VISTA:
3260            ver = "Windows NT 6.0";
3261            break;
3262#if QT_VERSION > 0x040500
3263        case QSysInfo::WV_WINDOWS7:
3264            ver = "Windows NT 6.1";
3265            break;
3266#endif
3267        case QSysInfo::WV_CE:
3268            ver = "Windows CE";
3269            break;
3270        case QSysInfo::WV_CENET:
3271            ver = "Windows CE .NET";
3272            break;
3273        case QSysInfo::WV_CE_5:
3274            ver = "Windows CE 5.x";
3275            break;
3276        case QSysInfo::WV_CE_6:
3277            ver = "Windows CE 6.x";
3278            break;
3279    }
3280    ua = QString(ua).arg(ver);
3281#endif
3282
3283    // SubPlatform Version
3284    QString subPlatformVer;
3285#ifdef Q_OS_SYMBIAN
3286    QSysInfo::S60Version s60Version = QSysInfo::s60Version();
3287    switch (s60Version) {
3288    case QSysInfo::SV_S60_3_1:
3289        subPlatformVer = "/3.1";
3290        break;
3291    case QSysInfo::SV_S60_3_2:
3292        subPlatformVer = "/3.2";
3293        break;
3294    case QSysInfo::SV_S60_5_0:
3295        subPlatformVer = "/5.0";
3296        break;
3297    default:
3298        subPlatformVer = " Unknown";
3299    }
3300#endif
3301    ua = ua.arg(subPlatformVer);
3302
3303    // Language
3304    QLocale locale;
3305    if (view())
3306        locale = view()->locale();
3307    QString name = locale.name();
3308    name[2] = QLatin1Char('-');
3309    ua.append(name);
3310    ua.append(QLatin1String(") "));
3311
3312    // webkit/qt version
3313    ua.append(QString(QLatin1String("AppleWebKit/%1 (KHTML, like Gecko) "))
3314                      .arg(QString(qWebKitVersion())));
3315
3316    // Application name/version
3317    QString appName = QCoreApplication::applicationName();
3318    if (!appName.isEmpty()) {
3319        ua.append(appName);
3320        QString appVer = QCoreApplication::applicationVersion();
3321        if (!appVer.isEmpty())
3322            ua.append(QLatin1Char('/') + appVer);
3323    } else {
3324        // Qt version
3325        ua.append(QLatin1String("Qt/"));
3326        ua.append(QLatin1String(qVersion()));
3327    }
3328
3329    ua.append(QString(QLatin1String(" Safari/%1"))
3330                      .arg(qWebKitVersion()));
3331
3332    return ua;
3333}
3334
3335
3336void QWebPagePrivate::_q_onLoadProgressChanged(int)
3337{
3338    m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
3339    m_bytesReceived = page->progress()->totalBytesReceived();
3340}
3341
3342
3343/*!
3344    Returns the total number of bytes that were received from the network to render the current page,
3345    including extra content such as embedded images.
3346
3347    \sa bytesReceived()
3348*/
3349quint64 QWebPage::totalBytes() const
3350{
3351    return d->m_totalBytes;
3352}
3353
3354
3355/*!
3356    Returns the number of bytes that were received from the network to render the current page.
3357
3358    \sa totalBytes()
3359*/
3360quint64 QWebPage::bytesReceived() const
3361{
3362    return d->m_bytesReceived;
3363}
3364
3365/*!
3366    \fn void QWebPage::loadStarted()
3367
3368    This signal is emitted when a new load of the page is started.
3369
3370    \sa loadFinished()
3371*/
3372
3373/*!
3374    \fn void QWebPage::loadProgress(int progress)
3375
3376    This signal is emitted when the global progress status changes.
3377    The current value is provided by \a progress and scales from 0 to 100,
3378    which is the default range of QProgressBar.
3379    It accumulates changes from all the child frames.
3380
3381    \sa bytesReceived()
3382*/
3383
3384/*!
3385    \fn void QWebPage::loadFinished(bool ok)
3386
3387    This signal is emitted when a load of the page is finished.
3388    \a ok will indicate whether the load was successful or any error occurred.
3389
3390    \sa loadStarted()
3391*/
3392
3393/*!
3394    \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
3395
3396    This signal is emitted when the mouse hovers over a link.
3397
3398    \a link contains the link url.
3399    \a title is the link element's title, if it is specified in the markup.
3400    \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
3401
3402    When the mouse leaves the link element the signal is emitted with empty parameters.
3403
3404    \sa linkClicked()
3405*/
3406
3407/*!
3408    \fn void QWebPage::statusBarMessage(const QString& text)
3409
3410    This signal is emitted when the statusbar \a text is changed by the page.
3411*/
3412
3413/*!
3414    \fn void QWebPage::frameCreated(QWebFrame *frame)
3415
3416    This signal is emitted whenever the page creates a new \a frame.
3417*/
3418
3419/*!
3420    \fn void QWebPage::selectionChanged()
3421
3422    This signal is emitted whenever the selection changes.
3423
3424    \sa selectedText()
3425*/
3426
3427/*!
3428    \fn void QWebPage::contentsChanged()
3429    \since 4.5
3430
3431    This signal is emitted whenever the text in form elements changes
3432    as well as other editable content.
3433
3434    \sa contentEditable, QWebFrame::toHtml(), QWebFrame::toPlainText()
3435*/
3436
3437/*!
3438    \fn void QWebPage::geometryChangeRequested(const QRect& geom)
3439
3440    This signal is emitted whenever the document wants to change the position and size of the
3441    page to \a geom. This can happen for example through JavaScript.
3442*/
3443
3444/*!
3445    \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
3446
3447    This signal is emitted whenever this QWebPage should be updated and no view was set.
3448    \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
3449    the mainFrame() and call the render(QPainter*, const QRegion&) method with the
3450    \a dirtyRect as the second parameter.
3451
3452    \sa mainFrame()
3453    \sa view()
3454*/
3455
3456/*!
3457    \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
3458
3459    This signal is emitted whenever the content given by \a rectToScroll needs
3460    to be scrolled \a dx and \a dy downwards and no view was set.
3461
3462    \sa view()
3463*/
3464
3465/*!
3466    \fn void QWebPage::windowCloseRequested()
3467
3468    This signal is emitted whenever the page requests the web browser window to be closed,
3469    for example through the JavaScript \c{window.close()} call.
3470*/
3471
3472/*!
3473    \fn void QWebPage::printRequested(QWebFrame *frame)
3474
3475    This signal is emitted whenever the page requests the web browser to print \a frame,
3476    for example through the JavaScript \c{window.print()} call.
3477
3478    \sa QWebFrame::print(), QPrintPreviewDialog
3479*/
3480
3481/*!
3482    \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
3483
3484    This signal is emitted when WebKit cannot handle a link the user navigated to.
3485
3486    At signal emission time the meta-data of the QNetworkReply \a reply is available.
3487
3488    \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
3489
3490    \sa downloadRequested()
3491*/
3492
3493/*!
3494    \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
3495
3496    This signal is emitted when the user decides to download a link. The url of
3497    the link as well as additional meta-information is contained in \a request.
3498
3499    \sa unsupportedContent()
3500*/
3501
3502/*!
3503    \fn void QWebPage::microFocusChanged()
3504
3505    This signal is emitted when for example the position of the cursor in an editable form
3506    element changes. It is used inform input methods about the new on-screen position where
3507    the user is able to enter text. This signal is usually connected to QWidget's updateMicroFocus()
3508    slot.
3509*/
3510
3511/*!
3512    \fn void QWebPage::linkClicked(const QUrl &url)
3513
3514    This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
3515    property is set to delegate the link handling for the specified \a url.
3516
3517    By default no links are delegated and are handled by QWebPage instead.
3518
3519    \sa linkHovered()
3520*/
3521
3522/*!
3523    \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
3524
3525    This signal is emitted whenever the visibility of the toolbar in a web browser
3526    window that hosts QWebPage should be changed to \a visible.
3527*/
3528
3529/*!
3530    \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
3531
3532    This signal is emitted whenever the visibility of the statusbar in a web browser
3533    window that hosts QWebPage should be changed to \a visible.
3534*/
3535
3536/*!
3537    \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
3538
3539    This signal is emitted whenever the visibility of the menubar in a web browser
3540    window that hosts QWebPage should be changed to \a visible.
3541*/
3542
3543/*!
3544    \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
3545    \since 4.5
3546
3547    This signal is emitted whenever the web site shown in \a frame is asking to store data
3548    to the database \a databaseName and the quota allocated to that web site is exceeded.
3549*/
3550
3551/*!
3552  \since 4.5
3553  \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
3554
3555  This signal is emitted shortly before the history of navigated pages
3556  in \a frame is changed, for example when navigating back in the history.
3557
3558  The provided QWebHistoryItem, \a item, holds the history entry of the frame before
3559  the change.
3560
3561  A potential use-case for this signal is to store custom data in
3562  the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
3563*/
3564
3565/*!
3566  \since 4.5
3567  \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
3568
3569  This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
3570*/
3571
3572/*!
3573  \fn QWebPagePrivate* QWebPage::handle() const
3574  \internal
3575*/
3576
3577#include "moc_qwebpage.cpp"
3578