OSDN Git Service

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