a581b32e95c75295cc1ac665f3e1f6e99a05407c
[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& url) const
3058 {
3059     Q_UNUSED(url)
3060     QString ua = QLatin1String("Mozilla/5.0 ("
3061
3062     // Platform
3063 #ifdef Q_WS_MAC
3064     "Macintosh"
3065 #elif defined Q_WS_QWS
3066     "QtEmbedded"
3067 #elif defined Q_WS_WIN
3068     "Windows"
3069 #elif defined Q_WS_X11
3070     "X11"
3071 #elif defined Q_OS_SYMBIAN
3072     "SymbianOS"
3073 #else
3074     "Unknown"
3075 #endif
3076     // Placeholder for Platform Version
3077     "%1; "
3078
3079     // Placeholder for security strength (N or U)
3080     "%2; "
3081
3082     // Subplatform"
3083 #ifdef Q_OS_AIX
3084     "AIX"
3085 #elif defined Q_OS_WIN32
3086     "%3"
3087 #elif defined Q_OS_DARWIN
3088 #ifdef __i386__ || __x86_64__
3089     "Intel Mac OS X"
3090 #else
3091     "PPC Mac OS X"
3092 #endif
3093
3094 #elif defined Q_OS_BSDI
3095     "BSD"
3096 #elif defined Q_OS_BSD4
3097     "BSD Four"
3098 #elif defined Q_OS_CYGWIN
3099     "Cygwin"
3100 #elif defined Q_OS_DGUX
3101     "DG/UX"
3102 #elif defined Q_OS_DYNIX
3103     "DYNIX/ptx"
3104 #elif defined Q_OS_FREEBSD
3105     "FreeBSD"
3106 #elif defined Q_OS_HPUX
3107     "HP-UX"
3108 #elif defined Q_OS_HURD
3109     "GNU Hurd"
3110 #elif defined Q_OS_IRIX
3111     "SGI Irix"
3112 #elif defined Q_OS_LINUX
3113     "Linux"
3114 #elif defined Q_OS_LYNX
3115     "LynxOS"
3116 #elif defined Q_OS_NETBSD
3117     "NetBSD"
3118 #elif defined Q_OS_OS2
3119     "OS/2"
3120 #elif defined Q_OS_OPENBSD
3121     "OpenBSD"
3122 #elif defined Q_OS_OS2EMX
3123     "OS/2"
3124 #elif defined Q_OS_OSF
3125     "HP Tru64 UNIX"
3126 #elif defined Q_OS_QNX6
3127     "QNX RTP Six"
3128 #elif defined Q_OS_QNX
3129     "QNX"
3130 #elif defined Q_OS_RELIANT
3131     "Reliant UNIX"
3132 #elif defined Q_OS_SCO
3133     "SCO OpenServer"
3134 #elif defined Q_OS_SOLARIS
3135     "Sun Solaris"
3136 #elif defined Q_OS_ULTRIX
3137     "DEC Ultrix"
3138 #elif defined Q_WS_S60
3139     "Series60"
3140 #elif defined Q_OS_UNIX
3141     "UNIX BSD/SYSV system"
3142 #elif defined Q_OS_UNIXWARE
3143     "UnixWare Seven, Open UNIX Eight"
3144 #else
3145     "Unknown"
3146 #endif
3147     // Placeholder for SubPlatform Version
3148     "%4; ");
3149
3150     // Platform Version
3151     QString osVer;
3152 #ifdef Q_OS_SYMBIAN
3153     QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
3154     switch (symbianVersion) {
3155     case QSysInfo::SV_9_2:
3156         osVer = "/9.2";
3157         break;
3158     case QSysInfo::SV_9_3:
3159         osVer = "/9.3";
3160         break;
3161     case QSysInfo::SV_9_4:
3162         osVer = "/9.4";
3163         break;
3164     default: 
3165         osVer = "Unknown";
3166     }
3167 #endif
3168     ua = ua.arg(osVer);
3169
3170     QChar securityStrength(QLatin1Char('N'));
3171 #if !defined(QT_NO_OPENSSL)
3172     // we could check QSslSocket::supportsSsl() here, but this makes
3173     // OpenSSL, certificates etc being loaded in all cases were QWebPage
3174     // is used. This loading is not needed for non-https.
3175     securityStrength = QLatin1Char('U');
3176     // this may lead to a false positive: We indicate SSL since it is
3177     // compiled in even though supportsSsl() might return false
3178 #endif
3179     ua = ua.arg(securityStrength);
3180
3181 #if defined Q_OS_WIN32
3182     QString ver;
3183     switch (QSysInfo::WindowsVersion) {
3184         case QSysInfo::WV_32s:
3185             ver = "Windows 3.1";
3186             break;
3187         case QSysInfo::WV_95:
3188             ver = "Windows 95";
3189             break;
3190         case QSysInfo::WV_98:
3191             ver = "Windows 98";
3192             break;
3193         case QSysInfo::WV_Me:
3194             ver = "Windows 98; Win 9x 4.90";
3195             break;
3196         case QSysInfo::WV_NT:
3197             ver = "WinNT4.0";
3198             break;
3199         case QSysInfo::WV_2000:
3200             ver = "Windows NT 5.0";
3201             break;
3202         case QSysInfo::WV_XP:
3203             ver = "Windows NT 5.1";
3204             break;
3205         case QSysInfo::WV_2003:
3206             ver = "Windows NT 5.2";
3207             break;
3208         case QSysInfo::WV_VISTA:
3209             ver = "Windows NT 6.0";
3210             break;
3211 #if QT_VERSION > 0x040500
3212         case QSysInfo::WV_WINDOWS7:
3213             ver = "Windows NT 6.1";
3214             break;
3215 #endif
3216         case QSysInfo::WV_CE:
3217             ver = "Windows CE";
3218             break;
3219         case QSysInfo::WV_CENET:
3220             ver = "Windows CE .NET";
3221             break;
3222         case QSysInfo::WV_CE_5:
3223             ver = "Windows CE 5.x";
3224             break;
3225         case QSysInfo::WV_CE_6:
3226             ver = "Windows CE 6.x";
3227             break;
3228     }
3229     ua = QString(ua).arg(ver);
3230 #endif
3231
3232     // SubPlatform Version
3233     QString subPlatformVer;
3234 #ifdef Q_OS_SYMBIAN
3235     QSysInfo::S60Version s60Version = QSysInfo::s60Version();
3236     switch (s60Version) {
3237     case QSysInfo::SV_S60_3_1:
3238         subPlatformVer = "/3.1";
3239         break;
3240     case QSysInfo::SV_S60_3_2:
3241         subPlatformVer = "/3.2";
3242         break;
3243     case QSysInfo::SV_S60_5_0:
3244         subPlatformVer = "/5.0";
3245         break;
3246     default: 
3247         subPlatformVer = " Unknown";
3248     }
3249 #endif
3250     ua = ua.arg(subPlatformVer);
3251
3252     // Language
3253     QLocale locale;
3254     if (d->client && d->client->ownerWidget())
3255         locale = d->client->ownerWidget()->locale();
3256     QString name = locale.name();
3257     name[2] = QLatin1Char('-');
3258     ua.append(name);
3259     ua.append(QLatin1String(") "));
3260
3261     // webkit/qt version
3262     ua.append(QString(QLatin1String("AppleWebKit/%1 (KHTML, like Gecko) "))
3263                       .arg(QString(qWebKitVersion())));
3264
3265     // Application name/version
3266     QString appName = QCoreApplication::applicationName();
3267     if (!appName.isEmpty()) {
3268         ua.append(appName);
3269         QString appVer = QCoreApplication::applicationVersion();
3270         if (!appVer.isEmpty())
3271             ua.append(QLatin1Char('/') + appVer);
3272     } else {
3273         // Qt version
3274         ua.append(QLatin1String("Qt/"));
3275         ua.append(QLatin1String(qVersion()));
3276     }
3277
3278 #if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
3279     ua.append(QString(QLatin1String(" Mobile Safari/%1")).arg(qWebKitVersion()));
3280 #else
3281     ua.append(QString(QLatin1String(" Safari/%1")).arg(qWebKitVersion()));
3282 #endif
3283     return ua;
3284 }
3285
3286
3287 void QWebPagePrivate::_q_onLoadProgressChanged(int)
3288 {
3289     m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
3290     m_bytesReceived = page->progress()->totalBytesReceived();
3291 }
3292
3293
3294 /*!
3295     Returns the total number of bytes that were received from the network to render the current page,
3296     including extra content such as embedded images.
3297
3298     \sa bytesReceived()
3299 */
3300 quint64 QWebPage::totalBytes() const
3301 {
3302     return d->m_totalBytes;
3303 }
3304
3305
3306 /*!
3307     Returns the number of bytes that were received from the network to render the current page.
3308
3309     \sa totalBytes()
3310 */
3311 quint64 QWebPage::bytesReceived() const
3312 {
3313     return d->m_bytesReceived;
3314 }
3315
3316 /*!
3317     \fn void QWebPage::loadStarted()
3318
3319     This signal is emitted when a new load of the page is started.
3320
3321     \sa loadFinished()
3322 */
3323
3324 /*!
3325     \fn void QWebPage::loadProgress(int progress)
3326
3327     This signal is emitted when the global progress status changes.
3328     The current value is provided by \a progress and scales from 0 to 100,
3329     which is the default range of QProgressBar.
3330     It accumulates changes from all the child frames.
3331
3332     \sa bytesReceived()
3333 */
3334
3335 /*!
3336     \fn void QWebPage::loadFinished(bool ok)
3337
3338     This signal is emitted when a load of the page is finished.
3339     \a ok will indicate whether the load was successful or any error occurred.
3340
3341     \sa loadStarted()
3342 */
3343
3344 /*!
3345     \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
3346
3347     This signal is emitted when the mouse hovers over a link.
3348
3349     \a link contains the link url.
3350     \a title is the link element's title, if it is specified in the markup.
3351     \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
3352
3353     When the mouse leaves the link element the signal is emitted with empty parameters.
3354
3355     \sa linkClicked()
3356 */
3357
3358 /*!
3359     \fn void QWebPage::statusBarMessage(const QString& text)
3360
3361     This signal is emitted when the statusbar \a text is changed by the page.
3362 */
3363
3364 /*!
3365     \fn void QWebPage::frameCreated(QWebFrame *frame)
3366
3367     This signal is emitted whenever the page creates a new \a frame.
3368 */
3369
3370 /*!
3371     \fn void QWebPage::selectionChanged()
3372
3373     This signal is emitted whenever the selection changes.
3374
3375     \sa selectedText()
3376 */
3377
3378 /*!
3379     \fn void QWebPage::contentsChanged()
3380     \since 4.5
3381
3382     This signal is emitted whenever the text in form elements changes
3383     as well as other editable content.
3384
3385     \sa contentEditable, QWebFrame::toHtml(), QWebFrame::toPlainText()
3386 */
3387
3388 /*!
3389     \fn void QWebPage::geometryChangeRequested(const QRect& geom)
3390
3391     This signal is emitted whenever the document wants to change the position and size of the
3392     page to \a geom. This can happen for example through JavaScript.
3393 */
3394
3395 /*!
3396     \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
3397
3398     This signal is emitted whenever this QWebPage should be updated and no view was set.
3399     \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
3400     the mainFrame() and call the render(QPainter*, const QRegion&) method with the
3401     \a dirtyRect as the second parameter.
3402
3403     \sa mainFrame()
3404     \sa view()
3405 */
3406
3407 /*!
3408     \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
3409
3410     This signal is emitted whenever the content given by \a rectToScroll needs
3411     to be scrolled \a dx and \a dy downwards and no view was set.
3412
3413     \sa view()
3414 */
3415
3416 /*!
3417     \fn void QWebPage::windowCloseRequested()
3418
3419     This signal is emitted whenever the page requests the web browser window to be closed,
3420     for example through the JavaScript \c{window.close()} call.
3421 */
3422
3423 /*!
3424     \fn void QWebPage::printRequested(QWebFrame *frame)
3425
3426     This signal is emitted whenever the page requests the web browser to print \a frame,
3427     for example through the JavaScript \c{window.print()} call.
3428
3429     \sa QWebFrame::print(), QPrintPreviewDialog
3430 */
3431
3432 /*!
3433     \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
3434
3435     This signal is emitted when WebKit cannot handle a link the user navigated to or a
3436     web server's response includes a "Content-Disposition" header with the 'attachment' 
3437     directive. If "Content-Disposition" is present in \a reply, the web server is indicating
3438     that the client should prompt the user to save the content regardless of content-type. 
3439     See RFC 2616 sections 19.5.1 for details about Content-Disposition.
3440
3441     At signal emission time the meta-data of the QNetworkReply \a reply is available.
3442
3443     \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
3444
3445     \sa downloadRequested()
3446 */
3447
3448 /*!
3449     \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
3450
3451     This signal is emitted when the user decides to download a link. The url of
3452     the link as well as additional meta-information is contained in \a request.
3453
3454     \sa unsupportedContent()
3455 */
3456
3457 /*!
3458     \fn void QWebPage::microFocusChanged()
3459
3460     This signal is emitted when for example the position of the cursor in an editable form
3461     element changes. It is used inform input methods about the new on-screen position where
3462     the user is able to enter text. This signal is usually connected to QWidget's updateMicroFocus()
3463     slot.
3464 */
3465
3466 /*!
3467     \fn void QWebPage::linkClicked(const QUrl &url)
3468
3469     This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
3470     property is set to delegate the link handling for the specified \a url.
3471
3472     By default no links are delegated and are handled by QWebPage instead.
3473
3474     \sa linkHovered()
3475 */
3476
3477 /*!
3478     \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
3479
3480     This signal is emitted whenever the visibility of the toolbar in a web browser
3481     window that hosts QWebPage should be changed to \a visible.
3482 */
3483
3484 /*!
3485     \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
3486
3487     This signal is emitted whenever the visibility of the statusbar in a web browser
3488     window that hosts QWebPage should be changed to \a visible.
3489 */
3490
3491 /*!
3492     \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
3493
3494     This signal is emitted whenever the visibility of the menubar in a web browser
3495     window that hosts QWebPage should be changed to \a visible.
3496 */
3497
3498 /*!
3499     \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
3500     \since 4.5
3501
3502     This signal is emitted whenever the web site shown in \a frame is asking to store data
3503     to the database \a databaseName and the quota allocated to that web site is exceeded.
3504 */
3505
3506 /*!
3507   \since 4.5
3508   \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
3509
3510   This signal is emitted shortly before the history of navigated pages
3511   in \a frame is changed, for example when navigating back in the history.
3512
3513   The provided QWebHistoryItem, \a item, holds the history entry of the frame before
3514   the change.
3515
3516   A potential use-case for this signal is to store custom data in
3517   the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
3518 */
3519
3520 /*!
3521   \since 4.5
3522   \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
3523
3524   This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
3525 */
3526
3527 /*!
3528   \fn QWebPagePrivate* QWebPage::handle() const
3529   \internal
3530 */
3531
3532 #include "moc_qwebpage.cpp"