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