2008-08-15 HÃ¥vard Wall <hwall@trolltech.com>
[WebKit-https.git] / WebKit / qt / Api / qwebpage.cpp
1 /*
2     Copyright (C) 2007 Trolltech ASA
3     Copyright (C) 2007 Staikos Computing Services Inc.
4     Copyright (C) 2007 Apple Inc.
5
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Library General Public
8     License as published by the Free Software Foundation; either
9     version 2 of the License, or (at your option) any later version.
10
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Library General Public License for more details.
15
16     You should have received a copy of the GNU Library General Public License
17     along with this library; see the file COPYING.LIB.  If not, write to
18     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19     Boston, MA 02110-1301, USA.
20 */
21
22 #include "config.h"
23 #include "qwebpage.h"
24 #include "qwebview.h"
25 #include "qwebframe.h"
26 #include "qwebpage_p.h"
27 #include "qwebframe_p.h"
28 #include "qwebhistory.h"
29 #include "qwebhistory_p.h"
30 #include "qwebsettings.h"
31
32 #include "Frame.h"
33 #include "FrameTree.h"
34 #include "FrameLoaderClientQt.h"
35 #include "FrameView.h"
36 #include "ChromeClientQt.h"
37 #include "ContextMenu.h"
38 #include "ContextMenuClientQt.h"
39 #include "DocumentLoader.h"
40 #include "DragClientQt.h"
41 #include "DragController.h"
42 #include "DragData.h"
43 #include "EditorClientQt.h"
44 #include "Settings.h"
45 #include "Page.h"
46 #include "Pasteboard.h"
47 #include "FrameLoader.h"
48 #include "FrameLoadRequest.h"
49 #include "KURL.h"
50 #include "Logging.h"
51 #include "Image.h"
52 #include "InspectorClientQt.h"
53 #include "InspectorController.h"
54 #include "FocusController.h"
55 #include "Editor.h"
56 #include "PlatformScrollBar.h"
57 #include "PlatformKeyboardEvent.h"
58 #include "PlatformWheelEvent.h"
59 #include "ProgressTracker.h"
60 #include "RefPtr.h"
61 #include "HashMap.h"
62 #include "HitTestResult.h"
63 #include "WindowFeatures.h"
64 #include "LocalizedStrings.h"
65
66 #include <QApplication>
67 #include <QBasicTimer>
68 #include <QBitArray>
69 #include <QDebug>
70 #include <QDragEnterEvent>
71 #include <QDragLeaveEvent>
72 #include <QDragMoveEvent>
73 #include <QDropEvent>
74 #include <QFileDialog>
75 #include <QHttpRequestHeader>
76 #include <QInputDialog>
77 #include <QMessageBox>
78 #include <QNetworkProxy>
79 #include <QUndoStack>
80 #include <QUrl>
81 #include <QPainter>
82 #include <QClipboard>
83 #include <QSslSocket>
84 #include <QSysInfo>
85 #if QT_VERSION >= 0x040400
86 #include <QNetworkAccessManager>
87 #include <QNetworkRequest>
88 #else
89 #include "qwebnetworkinterface.h"
90 #endif
91
92 using namespace WebCore;
93
94 // Lookup table mapping QWebPage::WebActions to the associated Editor commands
95 static const char* editorCommandWebActions[] = 
96 {
97     0, // OpenLink,
98
99     0, // OpenLinkInNewWindow,
100     0, // OpenFrameInNewWindow,
101     
102     0, // DownloadLinkToDisk,
103     0, // CopyLinkToClipboard,
104     
105     0, // OpenImageInNewWindow,
106     0, // DownloadImageToDisk,
107     0, // CopyImageToClipboard,
108     
109     0, // Back,
110     0, // Forward,
111     0, // Stop,
112     0, // Reload,
113     
114     "Cut", // Cut,
115     "Copy", // Copy,
116     "Paste", // Paste,
117     
118     "Undo", // Undo,
119     "Redo", // Redo,
120     "MoveForward", // MoveToNextChar,
121     "MoveBackward", // MoveToPreviousChar,
122     "MoveWordForward", // MoveToNextWord,
123     "MoveWordBackward", // MoveToPreviousWord,
124     "MoveDown", // MoveToNextLine,
125     "MoveUp", // MoveToPreviousLine,
126     "MoveToBeginningOfLine", // MoveToStartOfLine,
127     "MoveToEndOfLine", // MoveToEndOfLine,
128     "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
129     "MoveToEndOfParagraph", // MoveToEndOfBlock,
130     "MoveToBeginningOfDocument", // MoveToStartOfDocument,
131     "MoveToEndOfDocument", // MoveToEndOfDocument,
132     "MoveForwardAndModifySelection", // SelectNextChar,
133     "MoveBackwardAndModifySelection", // SelectPreviousChar,
134     "MoveWordForwardAndModifySelection", // SelectNextWord,
135     "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
136     "MoveDownAndModifySelection", // SelectNextLine,
137     "MoveUpAndModifySelection", // SelectPreviousLine,
138     "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
139     "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
140     "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
141     "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
142     "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
143     "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
144     "DeleteWordBackward", // DeleteStartOfWord,
145     "DeleteWordForward", // DeleteEndOfWord,
146     
147     0, // SetTextDirectionDefault,
148     0, // SetTextDirectionLeftToRight,
149     0, // SetTextDirectionRightToLeft,
150     
151     "ToggleBold", // ToggleBold,
152     "ToggleItalic", // ToggleItalic,
153     "ToggleUnderline", // ToggleUnderline,
154     
155     0, // InspectElement,
156
157     "InsertNewline", // InsertParagraphSeparator
158     "InsertLineBreak", // InsertLineSeparator
159
160     0 // WebActionCount
161 };
162
163 // Lookup the appropriate editor command to use for WebAction \a action
164 static const char* editorCommandForWebActions(QWebPage::WebAction action)
165 {
166     if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
167         return editorCommandWebActions[action];
168     
169     return 0;
170 }
171
172 #ifndef QT_NO_CURSOR
173 SetCursorEvent::SetCursorEvent(const QCursor& cursor)
174     : QEvent(static_cast<QEvent::Type>(EventType))
175     , m_cursor(cursor)
176 {}
177
178 QCursor SetCursorEvent::cursor() const
179 {
180     return m_cursor;
181 }
182 #endif
183
184 // If you change this make sure to also adjust the docs for QWebPage::userAgentForUrl
185 #define WEBKIT_VERSION "527+"
186
187 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
188 {
189     unsigned result = 0;
190     if (actions & Qt::CopyAction)
191         result |= DragOperationCopy;
192     if (actions & Qt::MoveAction)
193         result |= DragOperationMove;
194     if (actions & Qt::LinkAction)
195         result |= DragOperationLink;
196     return (DragOperation)result;
197 }
198
199 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
200 {
201     Qt::DropAction result = Qt::IgnoreAction;
202     if (actions & DragOperationCopy)
203         result = Qt::CopyAction;
204     else if (actions & DragOperationMove)
205         result = Qt::MoveAction;
206     else if (actions & DragOperationLink)
207         result = Qt::LinkAction;
208     return result;
209 }
210
211 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
212     : q(qq)
213     , view(0)
214     , viewportSize(QSize(0,0))
215 {
216     WebCore::InitializeLoggingChannelsIfNecessary();
217
218     chromeClient = new ChromeClientQt(q);
219     contextMenuClient = new ContextMenuClientQt();
220     editorClient = new EditorClientQt(q);
221     page = new Page(chromeClient, contextMenuClient, editorClient,
222                     new DragClientQt(q), new InspectorClientQt(q));
223
224     // ### should be configurable
225     page->settings()->setDefaultTextEncodingName("iso-8859-1");
226
227     settings = new QWebSettings(page->settings());
228
229 #ifndef QT_NO_UNDOSTACK
230     undoStack = 0;
231 #endif
232     mainFrame = 0;
233 #if QT_VERSION < 0x040400
234     networkInterface = 0;
235 #else
236     networkManager = 0;
237 #endif
238     pluginFactory = 0;
239     insideOpenCall = false;
240     forwardUnsupportedContent = false;
241     editable = false;
242     linkPolicy = QWebPage::DontDelegateLinks;
243 #ifndef QT_NO_CONTEXTMENU
244     currentContextMenu = 0;
245 #endif
246
247     history.d = new QWebHistoryPrivate(page->backForwardList());
248     memset(actions, 0, sizeof(actions));
249 }
250
251 QWebPagePrivate::~QWebPagePrivate()
252 {
253 #ifndef QT_NO_CONTEXTMENU
254     delete currentContextMenu;
255 #endif
256 #ifndef QT_NO_UNDOSTACK
257     delete undoStack;
258 #endif
259     delete settings;
260     delete page;
261 }
262
263 #if QT_VERSION < 0x040400
264 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
265 {
266     if (insideOpenCall
267         && frame == mainFrame)
268         return true;
269     return q->acceptNavigationRequest(frame, request, type);
270 }
271 #else
272 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
273 {
274     if (insideOpenCall
275         && frame == mainFrame)
276         return true;
277     return q->acceptNavigationRequest(frame, request, type);
278 }
279 #endif
280
281 void QWebPagePrivate::createMainFrame()
282 {
283     if (!mainFrame) {
284         QWebFrameData frameData;
285         frameData.ownerElement = 0;
286         frameData.allowsScrolling = true;
287         frameData.marginWidth = 0;
288         frameData.marginHeight = 0;
289         mainFrame = new QWebFrame(q, &frameData);
290
291         emit q->frameCreated(mainFrame);
292     }
293 }
294
295 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
296 {
297     switch (action) {
298         case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
299         case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
300         case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
301         case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
302         case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
303         case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
304         case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
305         case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
306         case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
307         case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
308         case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
309         case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
310         case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
311         case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
312         case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
313         case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
314         case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
315         case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
316         case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
317         case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
318         case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
319         case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
320         default: break;
321     }
322     return QWebPage::NoWebAction;
323 }
324
325 #ifndef QT_NO_CONTEXTMENU
326 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
327         const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
328 {
329     QMenu* menu = new QMenu(view);
330     for (int i = 0; i < items->count(); ++i) {
331         const ContextMenuItem &item = items->at(i);
332         switch (item.type()) {
333             case WebCore::CheckableActionType: /* fall through */
334             case WebCore::ActionType: {
335                 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
336                 QAction *a = q->action(action);
337                 if (a) {
338                     ContextMenuItem it(item);
339                     webcoreMenu->checkOrEnableIfNeeded(it);
340                     PlatformMenuItemDescription desc = it.releasePlatformDescription();
341                     a->setEnabled(desc.enabled);
342                     a->setChecked(desc.checked);
343                     a->setCheckable(item.type() == WebCore::CheckableActionType);
344
345                     menu->addAction(a);
346                     visitedWebActions->setBit(action);
347                 }
348                 break;
349             }
350             case WebCore::SeparatorType:
351                 menu->addSeparator();
352                 break;
353             case WebCore::SubmenuType: {
354                 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
355
356                 bool anyEnabledAction = false;
357
358                 QList<QAction *> actions = subMenu->actions();
359                 for (int i = 0; i < actions.count(); ++i) {
360                     if (actions.at(i)->isVisible())
361                         anyEnabledAction |= actions.at(i)->isEnabled();
362                 }
363
364                 // don't show sub-menus with just disabled actions
365                 if (anyEnabledAction) {
366                     subMenu->setTitle(item.title());
367                     menu->addAction(subMenu->menuAction());
368                 } else {
369                     delete subMenu;
370                 }
371                 break;
372             }
373         }
374     }
375     return menu;
376 }
377 #endif // QT_NO_CONTEXTMENU
378
379 QWebFrame *QWebPagePrivate::frameAt(const QPoint &pos) const
380 {
381     QWebFrame *frame = mainFrame;
382
383 redo:
384     QList<QWebFrame*> children = frame->childFrames();
385     for (int i = 0; i < children.size(); ++i) {
386         if (children.at(i)->geometry().contains(pos)) {
387             frame = children.at(i);
388             goto redo;
389         }
390     }
391     if (frame->geometry().contains(pos))
392         return frame;
393     return 0;
394 }
395
396 void QWebPagePrivate::_q_webActionTriggered(bool checked)
397 {
398     QAction *a = qobject_cast<QAction *>(q->sender());
399     if (!a)
400         return;
401     QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
402     q->triggerAction(action, checked);
403 }
404
405 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
406 {
407     QAction *a = actions[action];
408     if (!a || !mainFrame)
409         return;
410
411     WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
412     WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
413
414     bool enabled = a->isEnabled();
415     bool checked = a->isChecked();
416
417     switch (action) {
418         case QWebPage::Back:
419             enabled = loader->canGoBackOrForward(-1);
420             break;
421         case QWebPage::Forward:
422             enabled = loader->canGoBackOrForward(1);
423             break;
424         case QWebPage::Stop:
425             enabled = loader->isLoading();
426             break;
427         case QWebPage::Reload:
428             enabled = !loader->isLoading();
429             break;
430         case QWebPage::Cut:
431             enabled = editor->canCut();
432             break;
433         case QWebPage::Copy:
434             enabled = editor->canCopy();
435             break;
436         case QWebPage::Paste:
437             enabled = editor->canPaste();
438             break;
439 #ifndef QT_NO_UNDOSTACK
440         case QWebPage::Undo:
441         case QWebPage::Redo:
442             // those two are handled by QUndoStack
443             break;
444 #endif // QT_NO_UNDOSTACK
445         case QWebPage::ToggleBold:
446         case QWebPage::ToggleItalic:
447         case QWebPage::ToggleUnderline:
448             enabled = editor->canEditRichly();
449             if (enabled)
450                 checked = editor->command(editorCommandForWebActions(action)).state() != FalseTriState;
451             else
452                 checked = false;
453             break;
454         default: break;
455     }
456
457     a->setEnabled(enabled);
458
459     if (a->isCheckable())
460         a->setChecked(checked);
461 }
462
463 void QWebPagePrivate::updateNavigationActions()
464 {
465     updateAction(QWebPage::Back);
466     updateAction(QWebPage::Forward);
467     updateAction(QWebPage::Stop);
468     updateAction(QWebPage::Reload);
469 }
470
471 void QWebPagePrivate::updateEditorActions()
472 {
473     updateAction(QWebPage::Cut);
474     updateAction(QWebPage::Copy);
475     updateAction(QWebPage::Paste);
476     updateAction(QWebPage::ToggleBold);
477     updateAction(QWebPage::ToggleItalic);
478     updateAction(QWebPage::ToggleUnderline);
479 }
480
481 void QWebPagePrivate::timerEvent(QTimerEvent *ev)
482 {
483     int timerId = ev->timerId();
484     if (timerId == tripleClickTimer.timerId())
485         tripleClickTimer.stop();
486     else
487         q->QObject::timerEvent(ev);
488 }
489
490 void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev)
491 {
492     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
493     if (!frame->view())
494         return;
495
496     bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
497     ev->setAccepted(accepted);
498 }
499
500 void QWebPagePrivate::mousePressEvent(QMouseEvent *ev)
501 {
502     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
503     if (!frame->view())
504         return;
505
506     if (tripleClickTimer.isActive()
507             && (ev->pos() - tripleClick).manhattanLength()
508                 < QApplication::startDragDistance()) {
509         mouseTripleClickEvent(ev);
510         return;
511     }
512
513     bool accepted = frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 1));
514     ev->setAccepted(accepted);
515 }
516
517 void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev)
518 {
519     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
520     if (!frame->view())
521         return;
522
523     bool accepted = frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 2));
524     ev->setAccepted(accepted);
525
526     tripleClickTimer.start(QApplication::doubleClickInterval(), q);
527     tripleClick = ev->pos();
528 }
529
530 void QWebPagePrivate::mouseTripleClickEvent(QMouseEvent *ev)
531 {
532     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
533     if (!frame->view())
534         return;
535
536     bool accepted = frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 3));
537     ev->setAccepted(accepted);
538 }
539
540 void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev)
541 {
542     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
543     if (!frame->view())
544         return;
545
546     bool accepted = frame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(ev, 0));
547     ev->setAccepted(accepted);
548
549 #ifndef QT_NO_CLIPBOARD
550     if (QApplication::clipboard()->supportsSelection()) {
551         bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
552         Pasteboard::generalPasteboard()->setSelectionMode(true);
553         WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
554         if (ev->button() == Qt::LeftButton) {
555             if(focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
556                 focusFrame->editor()->copy();
557                 ev->setAccepted(true);
558             }
559         } else if (ev->button() == Qt::MidButton) {
560             if(focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
561                 focusFrame->editor()->paste();
562                 ev->setAccepted(true);
563             }
564         }
565         Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
566     }
567 #endif
568 }
569
570 #ifndef QT_NO_CONTEXTMENU
571 void QWebPagePrivate::contextMenuEvent(QContextMenuEvent *ev)
572 {
573     QMenu *menu = q->createStandardContextMenu();
574     if (menu) {
575         menu->exec(ev->globalPos());
576         delete menu;
577     }
578 }
579 #endif // QT_NO_CONTEXTMENU
580
581 /*!
582     \since 4.5
583     This function creates the standard context menu which is shown when
584     the user clicks on the web page with the right mouse button. It is
585     called from the default contextMenuEvent() handler. The popup menu's
586     ownership is transferred to the caller.
587  */
588 QMenu *QWebPage::createStandardContextMenu()
589 {
590     QMenu *menu = d->currentContextMenu;
591     d->currentContextMenu = 0;
592     return menu;
593 }
594
595 #ifndef QT_NO_WHEELEVENT
596 void QWebPagePrivate::wheelEvent(QWheelEvent *ev)
597 {
598     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
599     if (!frame->view())
600         return;
601
602     WebCore::PlatformWheelEvent pev(ev);
603     bool accepted = frame->eventHandler()->handleWheelEvent(pev);
604     ev->setAccepted(accepted);
605 }
606 #endif // QT_NO_WHEELEVENT
607
608 #ifndef QT_NO_SHORTCUT
609 static QWebPage::WebAction editorActionForKeyEvent(QKeyEvent* event)
610 {
611     static struct {
612         QKeySequence::StandardKey standardKey;
613         QWebPage::WebAction action;
614     } editorActions[] = {
615         { QKeySequence::Cut, QWebPage::Cut },
616         { QKeySequence::Copy, QWebPage::Copy },
617         { QKeySequence::Paste, QWebPage::Paste },
618         { QKeySequence::Undo, QWebPage::Undo },
619         { QKeySequence::Redo, QWebPage::Redo },
620         { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
621         { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
622         { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
623         { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
624         { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
625         { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
626         { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
627         { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
628         { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
629         { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
630         { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
631         { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
632         { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
633         { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
634         { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
635         { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
636         { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
637         { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
638         { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
639         { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
640         { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
641         { QKeySequence::SelectEndOfBlock,  QWebPage::SelectEndOfBlock },
642         { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
643         { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
644         { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
645         { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
646 #if QT_VERSION >= 0x040500
647         { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
648         { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
649 #endif
650         { QKeySequence::UnknownKey, QWebPage::NoWebAction }
651     };
652
653     for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
654         if (event == editorActions[i].standardKey)
655             return editorActions[i].action;
656
657     return QWebPage::NoWebAction;
658 }
659 #endif // QT_NO_SHORTCUT
660
661 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
662 {
663     bool handled = false;
664     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
665     WebCore::Editor* editor = frame->editor();
666 #ifndef QT_NO_SHORTCUT
667     if (editor->canEdit()) {
668         QWebPage::WebAction action = editorActionForKeyEvent(ev);
669         if (action != QWebPage::NoWebAction) {
670             q->triggerAction(action);
671             handled = true;
672         }
673     } else {
674         if (ev == QKeySequence::Copy) {
675             q->triggerAction(QWebPage::Copy);
676             handled = true;
677         }
678     }
679 #endif // QT_NO_SHORTCUT
680     if (!handled)
681         handled = frame->eventHandler()->keyEvent(ev);
682     if (!handled) {
683         handled = true;
684         QFont defaultFont;
685         if (view)
686             defaultFont = view->font();
687         QFontMetrics fm(defaultFont);
688         int fontHeight = fm.height();
689         if (!handleScrolling(ev)) {
690             switch (ev->key()) {
691             case Qt::Key_Backspace:
692                 if (ev->modifiers() == Qt::ShiftModifier)
693                     q->triggerAction(QWebPage::Forward);
694                 else
695                     q->triggerAction(QWebPage::Back);
696             default:
697                 handled = false;
698                 break;
699             }
700         }
701     }
702
703     ev->setAccepted(handled);
704 }
705
706 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
707 {
708     if (ev->isAutoRepeat()) {
709         ev->setAccepted(true);
710         return;
711     }
712
713     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
714     bool handled = frame->eventHandler()->keyEvent(ev);
715     ev->setAccepted(handled);
716 }
717
718 void QWebPagePrivate::focusInEvent(QFocusEvent *ev)
719 {
720     if (ev->reason() == Qt::PopupFocusReason)
721         return;
722
723     FocusController *focusController = page->focusController();
724     Frame *frame = focusController->focusedFrame();
725     focusController->setActive(true);
726     if (frame) {
727         frame->selection()->setFocused(true);
728     } else {
729         focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame));
730     }
731 }
732
733 void QWebPagePrivate::focusOutEvent(QFocusEvent *ev)
734 {
735     if (ev->reason() == Qt::PopupFocusReason)
736         return;
737
738     // only set the focused frame inactive so that we stop painting the caret
739     // and the focus frame. But don't tell the focus controller so that upon
740     // focusInEvent() we can re-activate the frame.
741     FocusController *focusController = page->focusController();
742     focusController->setActive(false);
743     Frame *frame = focusController->focusedFrame();
744     if (frame) {
745         frame->selection()->setFocused(false);
746     }
747 }
748
749 void QWebPagePrivate::dragEnterEvent(QDragEnterEvent *ev)
750 {
751 #ifndef QT_NO_DRAGANDDROP
752     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
753                       dropActionToDragOp(ev->possibleActions()));
754     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
755     ev->setDropAction(action);
756     if (action != Qt::IgnoreAction)
757         ev->accept();
758 #endif
759 }
760
761 void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent *ev)
762 {
763 #ifndef QT_NO_DRAGANDDROP
764     DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
765     page->dragController()->dragExited(&dragData);
766     ev->accept();
767 #endif
768 }
769
770 void QWebPagePrivate::dragMoveEvent(QDragMoveEvent *ev)
771 {
772 #ifndef QT_NO_DRAGANDDROP
773     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
774                       dropActionToDragOp(ev->possibleActions()));
775     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
776     ev->setDropAction(action);
777     if (action != Qt::IgnoreAction)
778         ev->accept();
779 #endif
780 }
781
782 void QWebPagePrivate::dropEvent(QDropEvent *ev)
783 {
784 #ifndef QT_NO_DRAGANDDROP
785     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
786                       dropActionToDragOp(ev->possibleActions()));
787     Qt::DropAction action = dragOpToDropAction(page->dragController()->performDrag(&dragData));
788     if (action != Qt::IgnoreAction)
789         ev->accept();
790 #endif
791 }
792
793 void QWebPagePrivate::leaveEvent(QEvent *ev)
794 {
795     // Fake a mouse move event just outside of the widget, since all
796     // the interesting mouse-out behavior like invalidating scrollbars
797     // is handled by the WebKit event handler's mouseMoved function.
798     QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
799     mouseMoveEvent(&fakeEvent);
800 }
801
802 /*!
803     \property QWebPage::palette
804     \brief the page's palette
805
806     The background brush of the palette is used to draw the background of the main frame.
807
808     By default, this property contains the application's default palette.
809 */
810 void QWebPage::setPalette(const QPalette &pal)
811 {
812     d->palette = pal;
813     if (d->mainFrame)
814         d->mainFrame->d->updateBackground();
815 }
816
817 QPalette QWebPage::palette() const
818 {
819     return d->palette;
820 }
821
822 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
823 {
824     WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
825     WebCore::Editor *editor = frame->editor();
826
827     if (!editor->canEdit()) {
828         ev->ignore();
829         return;
830     }
831
832     if (!ev->preeditString().isEmpty()) {
833         QString preedit = ev->preeditString();
834         // ### FIXME: use the provided QTextCharFormat (use color at least)
835         Vector<CompositionUnderline> underlines;
836         underlines.append(CompositionUnderline(0, preedit.length(), Color(0,0,0), false));
837         editor->setComposition(preedit, underlines, preedit.length(), 0);
838     } else if (!ev->commitString().isEmpty()) {
839         editor->confirmComposition(ev->commitString());
840     }
841     ev->accept();
842 }
843
844 void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
845 {
846     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
847     WebCore::Editor* editor = frame->editor();
848     if (editor->canEdit()) {
849         if (event->modifiers() == Qt::NoModifier
850             || event->modifiers() == Qt::ShiftModifier
851             || event->modifiers() == Qt::KeypadModifier) {
852                 if (event->key() < Qt::Key_Escape) {
853                     event->accept();
854                 } else {
855                     switch (event->key()) {
856                     case Qt::Key_Return:
857                     case Qt::Key_Enter:
858                     case Qt::Key_Delete:
859                     case Qt::Key_Home:
860                     case Qt::Key_End:
861                     case Qt::Key_Backspace:
862                     case Qt::Key_Left:
863                     case Qt::Key_Right:
864                     case Qt::Key_Up:
865                     case Qt::Key_Down:
866                     case Qt::Key_Tab:
867                         event->accept();
868                     default:
869                         break;
870                     }
871                 }
872         }
873 #ifndef QT_NO_SHORTCUT
874         else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction) {
875             event->accept();
876         }
877 #endif
878     }
879 }
880
881 bool QWebPagePrivate::handleScrolling(QKeyEvent *ev)
882 {
883     ScrollDirection direction;
884     ScrollGranularity granularity;
885
886 #ifndef QT_NO_SHORTCUT
887     if (ev == QKeySequence::MoveToNextPage
888         || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
889         granularity = ScrollByPage;
890         direction = ScrollDown;
891     } else if (ev == QKeySequence::MoveToPreviousPage
892                || (ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier)) {
893         granularity = ScrollByPage;
894         direction = ScrollUp;
895     } else
896 #endif // QT_NO_SHORTCUT
897     if (ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier
898                || ev->key() == Qt::Key_Home) {
899         granularity = ScrollByDocument;
900         direction = ScrollUp;
901     } else if (ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier
902                || ev->key() == Qt::Key_End) {
903         granularity = ScrollByDocument;
904         direction = ScrollDown;
905     } else {
906         switch (ev->key()) {
907             case Qt::Key_Up:
908                 granularity = ScrollByLine;
909                 direction = ScrollUp;
910                 break;
911             case Qt::Key_Down:
912                 granularity = ScrollByLine;
913                 direction = ScrollDown;
914                 break;
915             case Qt::Key_Left:
916                 granularity = ScrollByLine;
917                 direction = ScrollLeft;
918                 break;
919             case Qt::Key_Right:
920                 granularity = ScrollByLine;
921                 direction = ScrollRight;
922                 break;
923             default:
924                 return false;
925         }
926     }
927
928     if (!mainFrame->d->frame->eventHandler()->scrollOverflow(direction, granularity))
929         mainFrame->d->frame->view()->scroll(direction, granularity);
930
931     return true;
932 }
933
934 /*!
935   This method is used by the input method to query a set of properties of the page
936   to be able to support complex input method operations as support for surrounding
937   text and reconversions.
938
939   \a property specifies which property is queried.
940
941   \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
942 */
943 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
944 {
945     switch(property) {
946     case Qt::ImMicroFocus: {
947         Frame *frame = d->page->focusController()->focusedFrame();
948         if (frame) {
949             return QVariant(frame->selection()->caretRect());
950         }
951         return QVariant();
952     }
953     case Qt::ImFont: {
954         QWebView *webView = qobject_cast<QWebView *>(d->view);
955         if (webView)
956             return QVariant(webView->font());
957         return QVariant();
958     }
959     case Qt::ImCursorPosition: {
960         Frame *frame = d->page->focusController()->focusedFrame();
961         if (frame) {
962             Selection selection = frame->selection()->selection();
963             if (selection.isCaret()) {
964                 return QVariant(selection.start().offset());
965             }
966         }
967         return QVariant();
968     }
969     case Qt::ImSurroundingText: {
970         Frame *frame = d->page->focusController()->focusedFrame();
971         if (frame) {
972             Document *document = frame->document();
973             if (document->focusedNode()) {
974                 return QVariant(document->focusedNode()->nodeValue());
975             }
976         }
977         return QVariant();
978     }
979     case Qt::ImCurrentSelection:
980         return QVariant(selectedText());
981     default:
982         return QVariant();
983     }
984 }
985
986 /*!
987    \enum QWebPage::FindFlag
988
989    This enum describes the options available to QWebPage's findText() function. The options
990    can be OR-ed together from the following list:
991
992    \value FindBackward Searches backwards instead of forwards.
993    \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
994    changes the behaviour to a case sensitive find operation.
995    \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
996    was reached and the text was not found.
997 */
998
999 /*!
1000     \enum QWebPage::LinkDelegationPolicy
1001
1002     This enum defines the delegation policies a webpage can have when activating links and emitting
1003     the linkClicked() signal.
1004
1005     \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1006     \value DelegateExternalLinks When activating links that point to documents not stored on the
1007     local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1008     \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1009 */
1010
1011 /*!
1012     \enum QWebPage::NavigationType
1013
1014     This enum describes the types of navigation available when browsing through hyperlinked
1015     documents.
1016
1017     \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1018     \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1019     \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1020     \value NavigationTypeReload The user activated the reload action.
1021     \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1022     \value NavigationTypeOther A navigation to another document using a method not listed above.
1023 */
1024
1025 /*!
1026     \enum QWebPage::WebAction
1027
1028     \value NoWebAction No action is triggered.
1029     \value OpenLink Open the current link.
1030     \value OpenLinkInNewWindow Open the current link in a new window.
1031     \value OpenFrameInNewWindow Replicate the current frame in a new window.
1032     \value DownloadLinkToDisk Download the current link to the disk.
1033     \value CopyLinkToClipboard Copy the current link to the clipboard.
1034     \value OpenImageInNewWindow Open the highlighted image in a new window.
1035     \value DownloadImageToDisk Download the highlighted image to the disk.
1036     \value CopyImageToClipboard Copy the highlighted image to the clipboard.
1037     \value Back Navigate back in the history of navigated links.
1038     \value Forward Navigate forward in the history of navigated links.
1039     \value Stop Stop loading the current page.
1040     \value Reload Reload the current page.
1041     \value Cut Cut the content currently selected into the clipboard.
1042     \value Copy Copy the content currently selected into the clipboard.
1043     \value Paste Paste content from the clipboard.
1044     \value Undo Undo the last editing action.
1045     \value Redo Redo the last editing action.
1046     \value MoveToNextChar Move the cursor to the next character.
1047     \value MoveToPreviousChar Move the cursor to the previous character.
1048     \value MoveToNextWord Move the cursor to the next word.
1049     \value MoveToPreviousWord Move the cursor to the previous word.
1050     \value MoveToNextLine Move the cursor to the next line.
1051     \value MoveToPreviousLine Move the cursor to the previous line.
1052     \value MoveToStartOfLine Move the cursor to the start of the line.
1053     \value MoveToEndOfLine Move the cursor to the end of the line.
1054     \value MoveToStartOfBlock Move the cursor to the start of the block.
1055     \value MoveToEndOfBlock Move the cursor to the end of the block.
1056     \value MoveToStartOfDocument Move the cursor to the start of the document.
1057     \value MoveToEndOfDocument Move the cursor to the end of the document.
1058     \value SelectNextChar Select to the next character.
1059     \value SelectPreviousChar Select to the previous character.
1060     \value SelectNextWord Select to the next word.
1061     \value SelectPreviousWord Select to the previous word.
1062     \value SelectNextLine Select to the next line.
1063     \value SelectPreviousLine Select to the previous line.
1064     \value SelectStartOfLine Select to the start of the line.
1065     \value SelectEndOfLine Select to the end of the line.
1066     \value SelectStartOfBlock Select to the start of the block.
1067     \value SelectEndOfBlock Select to the end of the block.
1068     \value SelectStartOfDocument Select to the start of the document.
1069     \value SelectEndOfDocument Select to the end of the document.
1070     \value DeleteStartOfWord Delete to the start of the word.
1071     \value DeleteEndOfWord Delete to the end of the word.
1072     \value SetTextDirectionDefault Set the text direction to the default direction.
1073     \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1074     \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1075     \value ToggleBold Toggle the formatting between bold and normal weight.
1076     \value ToggleItalic Toggle the formatting between italic and normal style.
1077     \value ToggleUnderline Toggle underlining.
1078     \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1079     \value InsertParagraphSeparator Insert a new paragraph.
1080     \value InsertLineSeparator Insert a new line.
1081     \omitvalue WebActionCount
1082
1083 */
1084
1085 /*!
1086     \enum QWebPage::WebWindowType
1087
1088     \value WebBrowserWindow The window is a regular web browser window.
1089     \value WebModalDialog The window acts as modal dialog.
1090 */
1091
1092 /*!
1093     \class QWebPage
1094     \since 4.4
1095     \brief The QWebPage class provides an object to view and edit web documents.
1096
1097     QWebPage holds a main frame responsible for web content, settings, the history
1098     of navigated links and actions. This class can be used, together with QWebFrame,
1099     to provide functionality like QWebView in a widget-less environment.
1100
1101     QWebPage's API is very similar to QWebView, as you are still provided with
1102     common functions like action() (known as \l{QWebView::}{pageAction()} in
1103     QWebView), triggerAction(), findText() and settings(). More QWebView-like
1104     functions can be found in the main frame of QWebPage, obtained via
1105     QWebPage::mainFrame(). For example, the load(), setUrl() and setHtml()
1106     unctions for QWebPage can be accessed using QWebFrame.
1107
1108     The loadStarted() signal is emitted when the page begins to load.The
1109     loadProgress() signal, on the other hand, is emitted whenever an element
1110     of the web page completes loading, such as an embedded image, a script,
1111     etc. Finally, the loadFinished() signal is emitted when the page has
1112     loaded completely. Its argument, either true or false, indicates whether
1113     or not the load operation succeeded.
1114
1115     \section1 Using QWebPage in a Widget-less Environment
1116
1117     Before you begin painting a QWebPage object, you need to set the size of
1118     the viewport by calling setViewportSize(). Then, you invoke the main
1119     frame's render function (QWebFrame::render()). An example of this
1120     is shown in the code snippet below.
1121
1122     Suppose we have a \c Thumbnail class as follows:
1123
1124     \snippet doc/src/snippets/webkit/webpage/main.cpp 0
1125
1126     The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1127     object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1128     \c render().
1129
1130     \snippet doc/src/snippets/webkit/webpage/main.cpp 1
1131
1132     The \c render() function shows how we can paint a thumbnail using a
1133     QWebPage object.
1134
1135     \snippet doc/src/snippets/webkit/webpage/main.cpp 2
1136
1137     We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1138     then we instantiate a QImage object, \c image, with the same size as our
1139     \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1140     as a parameter to \c painter. Next, we render the contents of the main
1141     frame and its subframes into \c painter. Finally, we save the scaled image.
1142
1143     \sa QWebFrame
1144 */
1145
1146 /*!
1147     Constructs an empty QWebView with parent \a parent.
1148 */
1149 QWebPage::QWebPage(QObject *parent)
1150     : QObject(parent)
1151     , d(new QWebPagePrivate(this))
1152 {
1153     setView(qobject_cast<QWidget *>(parent));
1154
1155     connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1156 }
1157
1158 /*!
1159     Destroys the web page.
1160 */
1161 QWebPage::~QWebPage()
1162 {
1163     FrameLoader *loader = d->mainFrame->d->frame->loader();
1164     if (loader)
1165         loader->detachFromParent();
1166     delete d;
1167 }
1168
1169 /*!
1170     Returns the main frame of the page.
1171
1172     The main frame provides access to the hierarchy of sub-frames and is also needed if you
1173     want to explicitly render a web page into a given painter.
1174
1175     \sa currentFrame()
1176 */
1177 QWebFrame *QWebPage::mainFrame() const
1178 {
1179     d->createMainFrame();
1180     return d->mainFrame;
1181 }
1182
1183 /*!
1184     Returns the frame currently active.
1185
1186     \sa mainFrame(), frameCreated()
1187 */
1188 QWebFrame *QWebPage::currentFrame() const
1189 {
1190     return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame();
1191 }
1192
1193 /*!
1194     Returns a pointer to the view's history of navigated web pages.
1195 */
1196 QWebHistory *QWebPage::history() const
1197 {
1198     return &d->history;
1199 }
1200
1201 /*!
1202     Sets the \a view that is associated with the web page.
1203
1204     \sa view()
1205 */
1206 void QWebPage::setView(QWidget *view)
1207 {
1208     d->view = view;
1209     setViewportSize(view ? view->size() : QSize(0, 0));
1210 }
1211
1212 /*!
1213     Returns the view widget that is associated with the web page.
1214
1215     \sa setView()
1216 */
1217 QWidget *QWebPage::view() const
1218 {
1219     return d->view;
1220 }
1221
1222 /*!
1223     This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
1224
1225     For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
1226
1227     The default implementation prints nothing.
1228 */
1229 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
1230 {
1231     Q_UNUSED(message)
1232     Q_UNUSED(lineNumber)
1233     Q_UNUSED(sourceID)
1234 }
1235
1236 /*!
1237     This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
1238     the message \a msg.
1239
1240     The default implementation shows the message, \a msg, with QMessageBox::information.
1241 */
1242 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
1243 {
1244     QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Ok);
1245 }
1246
1247 /*!
1248     This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
1249     with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
1250
1251     The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1252 */
1253 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
1254 {
1255     return QMessageBox::Yes == QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Yes, QMessageBox::No);
1256 }
1257
1258 /*!
1259     This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
1260     The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
1261
1262     If the prompt was cancelled by the user the implementation should return false; otherwise the
1263     result should be written to \a result and true should be returned.
1264
1265     The default implementation uses QInputDialog::getText.
1266 */
1267 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
1268 {
1269     bool ok = false;
1270 #ifndef QT_NO_INPUTDIALOG
1271     QString x = QInputDialog::getText(d->view, mainFrame()->title(), msg, QLineEdit::Normal, defaultValue, &ok);
1272     if (ok && result) {
1273         *result = x;
1274     }
1275 #endif
1276     return ok;
1277 }
1278
1279 /*!
1280     This function is called whenever WebKit wants to create a new window of the given \a type, for
1281     example when a JavaScript program requests to open a document in a new window.
1282
1283     If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
1284
1285     If the view associated with the web page is a QWebView object, then the default implementation forwards
1286     the request to QWebView's createWindow() function; otherwise it returns a null pointer.
1287
1288     \sa acceptNavigationRequest()
1289 */
1290 QWebPage *QWebPage::createWindow(WebWindowType type)
1291 {
1292     QWebView *webView = qobject_cast<QWebView *>(d->view);
1293     if (webView) {
1294         QWebView *newView = webView->createWindow(type);
1295         if (newView)
1296             return newView->page();
1297     }
1298     return 0;
1299 }
1300
1301 /*!
1302     This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin".
1303     The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and
1304     child elements to configure the embeddable object.
1305 */
1306 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
1307 {
1308     Q_UNUSED(classid)
1309     Q_UNUSED(url)
1310     Q_UNUSED(paramNames)
1311     Q_UNUSED(paramValues)
1312     return 0;
1313 }
1314
1315 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
1316 {
1317     WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer());
1318     return WebCore::FrameLoadRequest(rr);
1319 }
1320
1321 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
1322 {
1323     if (Page* oldPage = frame->page()) {
1324         WindowFeatures features;
1325         if (Page* newPage = oldPage->chrome()->createWindow(frame,
1326                 frameLoadRequest(url, frame), features))
1327             newPage->chrome()->show();
1328     }
1329 }
1330
1331 /*!
1332     This function can be called to trigger the specified \a action.
1333     It is also called by QtWebKit if the user triggers the action, for example
1334     through a context menu item.
1335
1336     If \a action is a checkable action then \a checked specified whether the action
1337     is toggled or not.
1338
1339     \sa action()
1340 */
1341 void QWebPage::triggerAction(WebAction action, bool checked)
1342 {
1343     WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
1344     if (!frame)
1345         return;
1346     WebCore::Editor *editor = frame->editor();
1347     const char *command = 0;
1348
1349     switch (action) {
1350         case OpenLink:
1351             if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
1352                 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
1353                 targetFrame->d->frame->loader()->loadFrameRequestWithFormAndValues(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
1354                                                                                    /*lockHistory*/ false, /*event*/ 0,
1355                                                                                    /*HTMLFormElement*/ 0, /*formValues*/
1356                                                                                    WTF::HashMap<String, String>());
1357                 break;
1358             }
1359             // fall through
1360         case OpenLinkInNewWindow:
1361             openNewWindow(d->hitTestResult.linkUrl(), frame);
1362             break;
1363         case OpenFrameInNewWindow: {
1364             KURL url = frame->loader()->documentLoader()->unreachableURL();
1365             if (url.isEmpty())
1366                 url = frame->loader()->documentLoader()->url();
1367             openNewWindow(url, frame);
1368             break;
1369         }
1370         case CopyLinkToClipboard:
1371             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
1372             break;
1373         case OpenImageInNewWindow:
1374             openNewWindow(d->hitTestResult.imageUrl(), frame);
1375             break;
1376         case DownloadImageToDisk:
1377             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
1378             break;
1379         case DownloadLinkToDisk:
1380             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
1381             break;
1382 #ifndef QT_NO_CLIPBOARD
1383         case CopyImageToClipboard:
1384             QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
1385             break;
1386 #endif
1387         case Back:
1388             d->page->goBack();
1389             break;
1390         case Forward:
1391             d->page->goForward();
1392             break;
1393         case Stop:
1394             mainFrame()->d->frame->loader()->stopForUserCancel();
1395             break;
1396         case Reload:
1397             mainFrame()->d->frame->loader()->reload();
1398             break;
1399         case SetTextDirectionDefault:
1400             editor->setBaseWritingDirection(NaturalWritingDirection);
1401             break;
1402         case SetTextDirectionLeftToRight:
1403             editor->setBaseWritingDirection(LeftToRightWritingDirection);
1404             break;
1405         case SetTextDirectionRightToLeft:
1406             editor->setBaseWritingDirection(RightToLeftWritingDirection);
1407             break;
1408         case InspectElement:
1409             d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
1410             break;
1411         default:
1412             command = editorCommandForWebActions(action);
1413             break;
1414     }
1415
1416     if (command)
1417         editor->command(command).execute();
1418 }
1419
1420 QSize QWebPage::viewportSize() const
1421 {
1422     if (d->mainFrame && d->mainFrame->d->frame->view())
1423         return d->mainFrame->d->frame->view()->frameGeometry().size();
1424
1425     return d->viewportSize;
1426 }
1427
1428 /*!
1429     \property QWebPage::viewportSize
1430     \brief the size of the viewport
1431
1432     The size affects for example the visibility of scrollbars
1433     if the document is larger than the viewport.
1434
1435     By default, for a newly-created Web page, this property contains a size with
1436     zero width and height.
1437 */
1438 void QWebPage::setViewportSize(const QSize &size) const
1439 {
1440     d->viewportSize = size;
1441
1442     QWebFrame *frame = mainFrame();
1443     if (frame->d->frame && frame->d->frame->view()) {
1444         WebCore::FrameView* view = frame->d->frame->view();
1445         view->setFrameGeometry(QRect(QPoint(0, 0), size));
1446         frame->d->frame->forceLayout();
1447         view->adjustViewSize();
1448     }
1449 }
1450
1451
1452 /*!
1453     \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
1454
1455     This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
1456     the specified navigation type \a type.
1457
1458     If \a frame is a null pointer then navigation to a new window is requested. If the request is
1459     accepted createWindow() will be called.
1460
1461     The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
1462     to let QWebPage handle the navigation itself.
1463
1464     \sa createWindow()
1465 */
1466 #if QT_VERSION >= 0x040400
1467 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
1468 #else
1469 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
1470 #endif
1471 {
1472     if (type == NavigationTypeLinkClicked) {
1473         switch (d->linkPolicy) {
1474             case DontDelegateLinks:
1475                 return true;
1476
1477             case DelegateExternalLinks:
1478                 if (WebCore::FrameLoader::shouldTreatSchemeAsLocal(request.url().scheme()))
1479                     return true;
1480                 emit linkClicked(request.url());
1481                 return false;
1482
1483             case DelegateAllLinks:
1484                 emit linkClicked(request.url());
1485                 return false;
1486         }
1487     }
1488     return true;
1489 }
1490
1491 /*!
1492     \property QWebPage::selectedText
1493     \brief the text currently selected
1494
1495     By default, this property contains an empty string.
1496
1497     \sa selectionChanged()
1498 */
1499 QString QWebPage::selectedText() const
1500 {
1501     return d->page->focusController()->focusedOrMainFrame()->selectedText();
1502 }
1503
1504 /*!
1505    Returns a QAction for the specified WebAction \a action.
1506
1507    The action is owned by the QWebPage but you can customize the look by
1508    changing its properties.
1509
1510    QWebPage also takes care of implementing the action, so that upon
1511    triggering the corresponding action is performed on the page.
1512
1513    \sa triggerAction()
1514 */
1515 QAction *QWebPage::action(WebAction action) const
1516 {
1517     if (action == QWebPage::NoWebAction) return 0;
1518     if (d->actions[action])
1519         return d->actions[action];
1520
1521     QString text;
1522     QIcon icon;
1523     QStyle *style = view() ? view()->style() : qApp->style();
1524     bool checkable = false;
1525
1526     switch (action) {
1527         case OpenLink:
1528             text = contextMenuItemTagOpenLink();
1529             break;
1530         case OpenLinkInNewWindow:
1531             text = contextMenuItemTagOpenLinkInNewWindow();
1532             break;
1533         case OpenFrameInNewWindow:
1534             text = contextMenuItemTagOpenFrameInNewWindow();
1535             break;
1536
1537         case DownloadLinkToDisk:
1538             text = contextMenuItemTagDownloadLinkToDisk();
1539             break;
1540         case CopyLinkToClipboard:
1541             text = contextMenuItemTagCopyLinkToClipboard();
1542             break;
1543
1544         case OpenImageInNewWindow:
1545             text = contextMenuItemTagOpenImageInNewWindow();
1546             break;
1547         case DownloadImageToDisk:
1548             text = contextMenuItemTagDownloadImageToDisk();
1549             break;
1550         case CopyImageToClipboard:
1551             text = contextMenuItemTagCopyImageToClipboard();
1552             break;
1553
1554         case Back:
1555             text = contextMenuItemTagGoBack();
1556 #if QT_VERSION >= 0x040400
1557             icon = style->standardIcon(QStyle::SP_ArrowBack);
1558 #endif
1559             break;
1560         case Forward:
1561             text = contextMenuItemTagGoForward();
1562 #if QT_VERSION >= 0x040400
1563             icon = style->standardIcon(QStyle::SP_ArrowForward);
1564 #endif
1565             break;
1566         case Stop:
1567             text = contextMenuItemTagStop();
1568 #if QT_VERSION >= 0x040400
1569             icon = style->standardIcon(QStyle::SP_BrowserStop);
1570 #endif
1571             break;
1572         case Reload:
1573             text = contextMenuItemTagReload();
1574 #if QT_VERSION >= 0x040400
1575             icon = style->standardIcon(QStyle::SP_BrowserReload);
1576 #endif
1577             break;
1578
1579         case Cut:
1580             text = contextMenuItemTagCut();
1581             break;
1582         case Copy:
1583             text = contextMenuItemTagCopy();
1584             break;
1585         case Paste:
1586             text = contextMenuItemTagPaste();
1587             break;
1588 #ifndef QT_NO_UNDOSTACK
1589         case Undo: {
1590             QAction *a = undoStack()->createUndoAction(d->q);
1591             d->actions[action] = a;
1592             return a;
1593         }
1594         case Redo: {
1595             QAction *a = undoStack()->createRedoAction(d->q);
1596             d->actions[action] = a;
1597             return a;
1598         }
1599 #endif // QT_NO_UNDOSTACK
1600         case MoveToNextChar:
1601         case MoveToPreviousChar:
1602         case MoveToNextWord:
1603         case MoveToPreviousWord:
1604         case MoveToNextLine:
1605         case MoveToPreviousLine:
1606         case MoveToStartOfLine:
1607         case MoveToEndOfLine:
1608         case MoveToStartOfBlock:
1609         case MoveToEndOfBlock:
1610         case MoveToStartOfDocument:
1611         case MoveToEndOfDocument:
1612         case SelectNextChar:
1613         case SelectPreviousChar:
1614         case SelectNextWord:
1615         case SelectPreviousWord:
1616         case SelectNextLine:
1617         case SelectPreviousLine:
1618         case SelectStartOfLine:
1619         case SelectEndOfLine:
1620         case SelectStartOfBlock:
1621         case SelectEndOfBlock:
1622         case SelectStartOfDocument:
1623         case SelectEndOfDocument:
1624         case DeleteStartOfWord:
1625         case DeleteEndOfWord:
1626             break; // ####
1627
1628         case SetTextDirectionDefault:
1629             text = contextMenuItemTagDefaultDirection();
1630             break;
1631         case SetTextDirectionLeftToRight:
1632             text = contextMenuItemTagLeftToRight();
1633             checkable = true;
1634             break;
1635         case SetTextDirectionRightToLeft:
1636             text = contextMenuItemTagRightToLeft();
1637             checkable = true;
1638             break;
1639
1640         case ToggleBold:
1641             text = contextMenuItemTagBold();
1642             checkable = true;
1643             break;
1644         case ToggleItalic:
1645             text = contextMenuItemTagItalic();
1646             checkable = true;
1647             break;
1648         case ToggleUnderline:
1649             text = contextMenuItemTagUnderline();
1650             checkable = true;
1651             break;
1652
1653         case InspectElement:
1654             text = contextMenuItemTagInspectElement();
1655             break;
1656
1657         case NoWebAction:
1658             return 0;
1659     }
1660
1661     if (text.isEmpty())
1662         return 0;
1663
1664     QAction *a = new QAction(d->q);
1665     a->setText(text);
1666     a->setData(action);
1667     a->setCheckable(checkable);
1668     a->setIcon(icon);
1669
1670     connect(a, SIGNAL(triggered(bool)),
1671             this, SLOT(_q_webActionTriggered(bool)));
1672
1673     d->actions[action] = a;
1674     d->updateAction(action);
1675     return a;
1676 }
1677
1678 /*!
1679     \property QWebPage::modified
1680     \brief whether the page contains unsubmitted form data
1681
1682     By default, this property is false.
1683 */
1684 bool QWebPage::isModified() const
1685 {
1686 #ifdef QT_NO_UNDOSTACK
1687     return false;
1688 #else
1689     if (!d->undoStack)
1690         return false;
1691     return d->undoStack->canUndo();
1692 #endif // QT_NO_UNDOSTACK
1693 }
1694
1695 #ifndef QT_NO_UNDOSTACK
1696 /*!
1697     Returns a pointer to the undo stack used for editable content.
1698 */
1699 QUndoStack *QWebPage::undoStack() const
1700 {
1701     if (!d->undoStack)
1702         d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
1703
1704     return d->undoStack;
1705 }
1706 #endif // QT_NO_UNDOSTACK
1707
1708 /*! \reimp
1709 */
1710 bool QWebPage::event(QEvent *ev)
1711 {
1712     switch (ev->type()) {
1713     case QEvent::Timer:
1714         d->timerEvent(static_cast<QTimerEvent*>(ev));
1715         break;
1716     case QEvent::MouseMove:
1717         d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
1718         break;
1719     case QEvent::MouseButtonPress:
1720         d->mousePressEvent(static_cast<QMouseEvent*>(ev));
1721         break;
1722     case QEvent::MouseButtonDblClick:
1723         d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
1724         break;
1725     case QEvent::MouseButtonRelease:
1726         d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
1727         break;
1728 #ifndef QT_NO_CONTEXTMENU
1729     case QEvent::ContextMenu:
1730         d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev));
1731         break;
1732 #endif
1733 #ifndef QT_NO_WHEELEVENT
1734     case QEvent::Wheel:
1735         d->wheelEvent(static_cast<QWheelEvent*>(ev));
1736         break;
1737 #endif
1738     case QEvent::KeyPress:
1739         d->keyPressEvent(static_cast<QKeyEvent*>(ev));
1740         break;
1741     case QEvent::KeyRelease:
1742         d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
1743         break;
1744     case QEvent::FocusIn:
1745         d->focusInEvent(static_cast<QFocusEvent*>(ev));
1746         break;
1747     case QEvent::FocusOut:
1748         d->focusOutEvent(static_cast<QFocusEvent*>(ev));
1749         break;
1750 #ifndef QT_NO_DRAGANDDROP
1751     case QEvent::DragEnter:
1752         d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
1753         break;
1754     case QEvent::DragLeave:
1755         d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
1756         break;
1757     case QEvent::DragMove:
1758         d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
1759         break;
1760     case QEvent::Drop:
1761         d->dropEvent(static_cast<QDropEvent*>(ev));
1762         break;
1763 #endif
1764     case QEvent::InputMethod:
1765         d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
1766     case QEvent::ShortcutOverride:
1767         d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
1768         break;
1769     case QEvent::Leave:
1770         d->leaveEvent(ev);
1771         break;
1772     default:
1773         return QObject::event(ev);
1774     }
1775
1776     return true;
1777 }
1778
1779 /*!
1780     Similar to QWidget::focusNextPrevChild it focuses the next focusable web element
1781     if \a next is true; otherwise the previous element is focused.
1782
1783     Returns true if it can find a new focusable element, or false if it can't.
1784 */
1785 bool QWebPage::focusNextPrevChild(bool next)
1786 {
1787     QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
1788     d->keyPressEvent(&ev);
1789     bool hasFocusedNode = false;
1790     Frame *frame = d->page->focusController()->focusedFrame();
1791     if (frame) {
1792         Document *document = frame->document();
1793         hasFocusedNode = document && document->focusedNode();
1794     }
1795     //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
1796     return hasFocusedNode;
1797 }
1798
1799 /*!
1800     \property QWebPage::editable
1801     \brief whether the content in this QWebPage is editable or not
1802     \since 4.5
1803
1804     If this property is enabled the contents of the page can be edited by the user through a visible
1805     cursor. If disabled (the default) only HTML elements in the web page with their
1806     \c{contenteditable} attribute set are editable.
1807 */
1808 void QWebPage::setEditable(bool editable)
1809 {
1810     if (d->editable != editable) {
1811         d->editable = editable;
1812         d->page->setTabKeyCyclesThroughElements(!editable);
1813         if (d->mainFrame) {
1814             WebCore::Frame* frame = d->mainFrame->d->frame;
1815             if (editable) {
1816                 frame->applyEditingStyleToBodyElement();
1817                 // FIXME: mac port calls this if there is no selectedDOMRange
1818                 //frame->setSelectionFromNone();
1819             } else {
1820                 frame->removeEditingStyleFromBodyElement();
1821             }
1822         }
1823
1824         d->updateEditorActions();
1825     }
1826 }
1827
1828 bool QWebPage::isEditable() const
1829 {
1830     return d->editable;
1831 }
1832
1833 /*!
1834     \property QWebPage::forwardUnsupportedContent
1835     \brief whether QWebPage should forward unsupported content through the
1836     unsupportedContent signal
1837
1838     If disabled the download of such content is aborted immediately.
1839
1840     By default unsupported content is not forwarded.
1841 */
1842
1843 void QWebPage::setForwardUnsupportedContent(bool forward)
1844 {
1845     d->forwardUnsupportedContent = forward;
1846 }
1847
1848 bool QWebPage::forwardUnsupportedContent() const
1849 {
1850     return d->forwardUnsupportedContent;
1851 }
1852
1853 /*!
1854     \property QWebPage::linkDelegationPolicy
1855     \brief how QWebPage should delegate the handling of links through the
1856     linkClicked() signal
1857
1858     The default is to delegate no links.
1859 */
1860
1861 void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
1862 {
1863     d->linkPolicy = policy;
1864 }
1865
1866 QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
1867 {
1868     return d->linkPolicy;
1869 }
1870
1871 #ifndef QT_NO_CONTEXTMENU
1872 /*!
1873     Filters the context menu event, \a event, through handlers for scrollbars and
1874     custom event handlers in the web page. Returns true if the event was handled;
1875     otherwise false.
1876
1877     A web page may swallow a context menu event through a custom event handler, allowing for context
1878     menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
1879     Maps}, for example.
1880 */
1881 bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
1882 {
1883     d->page->contextMenuController()->clearContextMenu();
1884
1885     if (QWebFrame* webFrame = d->frameAt(event->pos())) {
1886         Frame* frame = QWebFramePrivate::core(webFrame);
1887         if (PlatformScrollbar* scrollbar = frame->view()->scrollbarUnderMouse(PlatformMouseEvent(event, 1))) {
1888             return scrollbar->handleContextMenuEvent(PlatformMouseEvent(event, 1));
1889         }
1890     }
1891
1892     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
1893     focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
1894     ContextMenu *menu = d->page->contextMenuController()->contextMenu();
1895     // If the website defines its own handler then sendContextMenuEvent takes care of
1896     // calling/showing it and the context menu pointer will be zero. This is the case
1897     // on maps.google.com for example.
1898
1899     return !menu;
1900 }
1901 #endif // QT_NO_CONTEXTMENU
1902
1903 /*!
1904     Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
1905     element the CopyImageToClipboard action is enabled.
1906 */
1907 void QWebPage::updatePositionDependentActions(const QPoint &pos)
1908 {
1909     // First we disable all actions, but keep track of which ones were originally enabled.
1910     QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
1911     for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
1912         QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
1913         if (QAction *a = this->action(action)) {
1914             originallyEnabledWebActions.setBit(action, a->isEnabled());
1915             a->setEnabled(false);
1916         }
1917     }
1918
1919     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
1920     HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
1921
1922     d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
1923     WebCore::ContextMenu menu(result);
1924     menu.populate();
1925     if (d->page->inspectorController()->enabled())
1926         menu.addInspectElementItem();
1927
1928     QBitArray visitedWebActions(QWebPage::WebActionCount);
1929
1930 #ifndef QT_NO_CONTEXTMENU
1931     delete d->currentContextMenu;
1932
1933     // Then we let createContextMenu() enable the actions that are put into the menu
1934     d->currentContextMenu = d->createContextMenu(&menu, menu.platformDescription(), &visitedWebActions);
1935 #endif // QT_NO_CONTEXTMENU
1936
1937     // Finally, we restore the original enablement for the actions that were not put into the menu.
1938     originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
1939     for (int i = 0; i < QWebPage::WebActionCount; ++i) {
1940         if (originallyEnabledWebActions.at(i)) {
1941             if (QAction *a = this->action(QWebPage::WebAction(i))) {
1942                 a->setEnabled(true);
1943             }
1944         }
1945     }
1946
1947     // This whole process ensures that any actions put into to the context menu has the right
1948     // enablement, while also keeping the correct enablement for actions that were left out of
1949     // the menu.
1950
1951 }
1952
1953
1954
1955 /*!
1956     \enum QWebPage::Extension
1957
1958     This enum describes the types of extensions that the page can support. Before using these extensions, you
1959     should verify that the extension is supported by calling supportsExtension().
1960
1961     Currently there are no extensions.
1962 */
1963
1964 /*!
1965     \class QWebPage::ExtensionOption
1966     \since 4.4
1967     \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
1968
1969     \sa QWebPage::extension()
1970 */
1971
1972 /*!
1973     \class QWebPage::ExtensionReturn
1974     \since 4.4
1975     \brief The ExtensionOption class provides an extended output argument to QWebPage's extension support.
1976
1977     \sa QWebPage::extension()
1978 */
1979
1980 /*!
1981     This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
1982     argument is provided as input to the extension; the output results can be stored in \a output.
1983
1984     The behavior of this function is determined by \a extension.
1985
1986     You can call supportsExtension() to check if an extension is supported by the page.
1987
1988     By default, no extensions are supported, and this function returns false.
1989
1990     \sa supportsExtension(), Extension
1991 */
1992 bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
1993 {
1994     Q_UNUSED(extension)
1995     Q_UNUSED(option)
1996     Q_UNUSED(output)
1997     return false;
1998 }
1999
2000 /*!
2001     This virtual function returns true if the web page supports \a extension; otherwise false is returned.
2002
2003     \sa extension()
2004 */
2005 bool QWebPage::supportsExtension(Extension extension) const
2006 {
2007     Q_UNUSED(extension)
2008     return false;
2009 }
2010
2011 /*!
2012     Finds the next occurrence of the string, \a subString, in the page, using the given \a options.
2013     Returns true of \a subString was found and selects the match visually; otherwise returns false.
2014 */
2015 bool QWebPage::findText(const QString &subString, FindFlags options)
2016 {
2017     ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
2018     if (options & FindCaseSensitively)
2019         caseSensitivity = ::TextCaseSensitive;
2020
2021     ::FindDirection direction = ::FindDirectionForward;
2022     if (options & FindBackward)
2023         direction = ::FindDirectionBackward;
2024
2025     const bool shouldWrap = options & FindWrapsAroundDocument;
2026
2027     return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
2028 }
2029
2030 /*!
2031     Returns a pointer to the page's settings object.
2032
2033     \sa QWebSettings::globalSettings()
2034 */
2035 QWebSettings *QWebPage::settings() const
2036 {
2037     return d->settings;
2038 }
2039
2040 /*!
2041     This function is called when the web content requests a file name, for example
2042     as a result of the user clicking on a "file upload" button in a HTML form.
2043
2044     A suggested filename may be provided in \a suggestedFile. The frame originating the
2045     request is provided as \a parentFrame.
2046 */
2047 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
2048 {
2049 #ifndef QT_NO_FILEDIALOG
2050     return QFileDialog::getOpenFileName(d->view, QString::null, suggestedFile);
2051 #else
2052     return QString::null;
2053 #endif
2054 }
2055
2056 #if QT_VERSION < 0x040400 && !defined qdoc
2057
2058 void QWebPage::setNetworkInterface(QWebNetworkInterface *interface)
2059 {
2060     d->networkInterface = interface;
2061 }
2062
2063 QWebNetworkInterface *QWebPage::networkInterface() const
2064 {
2065     if (d->networkInterface)
2066         return d->networkInterface;
2067     else
2068         return QWebNetworkInterface::defaultInterface();
2069 }
2070
2071 #ifndef QT_NO_NETWORKPROXY
2072 void QWebPage::setNetworkProxy(const QNetworkProxy& proxy)
2073 {
2074     d->networkProxy = proxy;
2075 }
2076
2077 QNetworkProxy QWebPage::networkProxy() const
2078 {
2079     return d->networkProxy;
2080 }
2081 #endif
2082
2083 #else
2084
2085 /*!
2086     Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
2087     QWebPage.
2088
2089     \sa networkAccessManager()
2090 */
2091 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
2092 {
2093     if (manager == d->networkManager)
2094         return;
2095     if (d->networkManager && d->networkManager->parent() == this)
2096         delete d->networkManager;
2097     d->networkManager = manager;
2098 }
2099
2100 /*!
2101     Returns the QNetworkAccessManager that is responsible for serving network
2102     requests for this QWebPage.
2103
2104     \sa setNetworkAccessManager()
2105 */
2106 QNetworkAccessManager *QWebPage::networkAccessManager() const
2107 {
2108     if (!d->networkManager) {
2109         QWebPage *that = const_cast<QWebPage *>(this);
2110         that->d->networkManager = new QNetworkAccessManager(that);
2111     }
2112     return d->networkManager;
2113 }
2114
2115 #endif
2116
2117 /*!
2118     Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
2119     QWebPage.
2120
2121     Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
2122
2123     \sa pluginFactory()
2124 */
2125 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
2126 {
2127     d->pluginFactory = factory;
2128 }
2129
2130 /*!
2131     Returns the QWebPluginFactory that is responsible for creating plugins embedded into
2132     this QWebPage. If no plugin factory is installed a null pointer is returned.
2133
2134     \sa setPluginFactory()
2135 */
2136 QWebPluginFactory *QWebPage::pluginFactory() const
2137 {
2138     return d->pluginFactory;
2139 }
2140
2141 /*!
2142     This function is called when a user agent for HTTP requests is needed. You can re-implement this
2143     function to dynamically return different user agent's for different urls, based on the \a url parameter.
2144
2145     The default implementation returns the following value:
2146
2147     "Mozilla/5.0 (%Platform%; %Security%; %Subplatform%; %Locale%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko, Safari/419.3) %AppVersion"
2148
2149     In this string the following values are replaced at run-time:
2150     \list
2151     \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system.
2152     \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true.
2153     \o %Locale% is replaced with QLocale::name().
2154     \o %WebKitVersion% currently expands to 527+
2155     \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
2156     \endlist
2157 */
2158 QString QWebPage::userAgentForUrl(const QUrl& url) const
2159 {
2160     Q_UNUSED(url)
2161     QString ua = QLatin1String("Mozilla/5.0 ("
2162
2163     // Plastform
2164 #ifdef Q_WS_MAC
2165     "Macintosh"
2166 #elif defined Q_WS_QWS
2167     "QtEmbedded"
2168 #elif defined Q_WS_WIN
2169     "Windows"
2170 #elif defined Q_WS_X11
2171     "X11"
2172 #else
2173     "Unknown"
2174 #endif
2175     "; "
2176
2177     // Placeholder for security strength (N or U)
2178     "%1; "
2179
2180     // Subplatform"
2181 #ifdef Q_OS_AIX
2182     "AIX"
2183 #elif defined Q_OS_WIN32
2184     "%2"
2185 #elif defined Q_OS_DARWIN
2186 #ifdef __i386__ || __x86_64__
2187     "Intel Mac OS X"
2188 #else
2189     "PPC Mac OS X"
2190 #endif
2191
2192 #elif defined Q_OS_BSDI
2193     "BSD"
2194 #elif defined Q_OS_BSD4
2195     "BSD Four"
2196 #elif defined Q_OS_CYGWIN
2197     "Cygwin"
2198 #elif defined Q_OS_DGUX
2199     "DG/UX"
2200 #elif defined Q_OS_DYNIX
2201     "DYNIX/ptx"
2202 #elif defined Q_OS_FREEBSD
2203     "FreeBSD"
2204 #elif defined Q_OS_HPUX
2205     "HP-UX"
2206 #elif defined Q_OS_HURD
2207     "GNU Hurd"
2208 #elif defined Q_OS_IRIX
2209     "SGI Irix"
2210 #elif defined Q_OS_LINUX
2211     "Linux"
2212 #elif defined Q_OS_LYNX
2213     "LynxOS"
2214 #elif defined Q_OS_NETBSD
2215     "NetBSD"
2216 #elif defined Q_OS_OS2
2217     "OS/2"
2218 #elif defined Q_OS_OPENBSD
2219     "OpenBSD"
2220 #elif defined Q_OS_OS2EMX
2221     "OS/2"
2222 #elif defined Q_OS_OSF
2223     "HP Tru64 UNIX"
2224 #elif defined Q_OS_QNX6
2225     "QNX RTP Six"
2226 #elif defined Q_OS_QNX
2227     "QNX"
2228 #elif defined Q_OS_RELIANT
2229     "Reliant UNIX"
2230 #elif defined Q_OS_SCO
2231     "SCO OpenServer"
2232 #elif defined Q_OS_SOLARIS
2233     "Sun Solaris"
2234 #elif defined Q_OS_ULTRIX
2235     "DEC Ultrix"
2236 #elif defined Q_OS_UNIX
2237     "UNIX BSD/SYSV system"
2238 #elif defined Q_OS_UNIXWARE
2239     "UnixWare Seven, Open UNIX Eight"
2240 #else
2241     "Unknown"
2242 #endif
2243     "; ");
2244
2245     QChar securityStrength(QLatin1Char('N'));
2246 #if !defined(QT_NO_OPENSSL)
2247     if (QSslSocket::supportsSsl())
2248         securityStrength = QLatin1Char('U');
2249 #endif
2250     ua = ua.arg(securityStrength);
2251
2252 #if defined Q_OS_WIN32
2253     QString ver;
2254     switch(QSysInfo::WindowsVersion) {
2255         case QSysInfo::WV_32s:
2256             ver = "Windows 3.1";
2257             break;
2258         case QSysInfo::WV_95:
2259             ver = "Windows 95";
2260             break;
2261         case QSysInfo::WV_98:
2262             ver = "Windows 98";
2263             break;
2264         case QSysInfo::WV_Me:
2265             ver = "Windows 98; Win 9x 4.90";
2266             break;
2267         case QSysInfo::WV_NT:
2268             ver = "WinNT4.0";
2269             break;
2270         case QSysInfo::WV_2000:
2271             ver = "Windows NT 5.0";
2272             break;
2273         case QSysInfo::WV_XP:
2274             ver = "Windows NT 5.1";
2275             break;
2276         case QSysInfo::WV_2003:
2277             ver = "Windows NT 5.2";
2278             break;
2279         case QSysInfo::WV_VISTA:
2280             ver = "Windows NT 6.0";
2281             break;
2282         case QSysInfo::WV_CE:
2283             ver = "Windows CE";
2284             break;
2285         case QSysInfo::WV_CENET:
2286             ver = "Windows CE .NET";
2287             break;
2288         case QSysInfo::WV_CE_5:
2289             ver = "Windows CE 5.x";
2290             break;
2291         case QSysInfo::WV_CE_6:
2292             ver = "Windows CE 6.x";
2293             break;
2294     }
2295     ua = QString(ua).arg(ver);
2296 #endif
2297
2298     // Language
2299     QLocale locale;
2300     if (d->view)
2301         locale = d->view->locale();
2302     QString name = locale.name();
2303     name[2] = QLatin1Char('-');
2304     ua.append(name);
2305     ua.append(QLatin1String(") "));
2306
2307     // webkit/qt version
2308     ua.append(QLatin1String("AppleWebKit/" WEBKIT_VERSION " (KHTML, like Gecko, Safari/419.3) "));
2309
2310     // Application name/version
2311     QString appName = QCoreApplication::applicationName();
2312     if (!appName.isEmpty()) {
2313         ua.append(QLatin1Char(' ') + appName);
2314 #if QT_VERSION >= 0x040400
2315         QString appVer = QCoreApplication::applicationVersion();
2316         if (!appVer.isEmpty())
2317             ua.append(QLatin1Char('/') + appVer);
2318 #endif
2319     } else {
2320         // Qt version
2321         ua.append(QLatin1String("Qt/"));
2322         ua.append(QLatin1String(qVersion()));
2323     }
2324     return ua;
2325 }
2326
2327
2328 void QWebPagePrivate::_q_onLoadProgressChanged(int) {
2329     m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
2330     m_bytesReceived = page->progress()->totalBytesReceived();
2331 }
2332
2333
2334 /*!
2335     Returns the total number of bytes that were received from the network to render the current page,
2336     including extra content such as embedded images.
2337
2338     \sa bytesReceived()
2339 */
2340 quint64 QWebPage::totalBytes() const {
2341     return d->m_bytesReceived;
2342 }
2343
2344
2345 /*!
2346     Returns the number of bytes that were received from the network to render the current page.
2347
2348     \sa totalBytes()
2349 */
2350 quint64 QWebPage::bytesReceived() const {
2351     return d->m_totalBytes;
2352 }
2353
2354 /*!
2355     \fn void QWebPage::loadStarted()
2356
2357     This signal is emitted when a new load of the page is started.
2358
2359     \sa loadFinished()
2360 */
2361
2362 /*!
2363     \fn void QWebPage::loadProgress(int progress)
2364
2365     This signal is emitted when the global progress status changes.
2366     The current value is provided by \a progress and scales from 0 to 100,
2367     which is the default range of QProgressBar.
2368     It accumulates changes from all the child frames.
2369
2370     \sa bytesReceived()
2371 */
2372
2373 /*!
2374     \fn void QWebPage::loadFinished(bool ok)
2375
2376     This signal is emitted when a load of the page is finished.
2377     \a ok will indicate whether the load was successful or any error occurred.
2378
2379     \sa loadStarted()
2380 */
2381
2382 /*!
2383     \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
2384
2385     This signal is emitted when the mouse is hovering over a link.
2386     The first parameter is the \a link url, the second is the link \a title
2387     if any, and third \a textContent is the text content. Method is emitter with both
2388     empty parameters when the mouse isn't hovering over any link element.
2389
2390     \sa linkClicked()
2391 */
2392
2393 /*!
2394     \fn void QWebPage::statusBarMessage(const QString& text)
2395
2396     This signal is emitted when the statusbar \a text is changed by the page.
2397 */
2398
2399 /*!
2400     \fn void QWebPage::frameCreated(QWebFrame *frame)
2401
2402     This signal is emitted whenever the page creates a new \a frame.
2403 */
2404
2405 /*!
2406     \fn void QWebPage::selectionChanged()
2407
2408     This signal is emitted whenever the selection changes.
2409
2410     \sa selectedText()
2411 */
2412
2413 /*!
2414     \fn void QWebPage::geometryChangeRequested(const QRect& geom)
2415
2416     This signal is emitted whenever the document wants to change the position and size of the
2417     page to \a geom. This can happen for example through JavaScript.
2418 */
2419
2420 /*!
2421     \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
2422
2423     This signal is emitted whenever this QWebPage should be updated and no view was set.
2424     \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
2425     the mainFrame() and call the render(QPainter*, const QRegion&) method with the
2426     \a dirtyRect as the second parameter.
2427
2428     \sa mainFrame()
2429     \sa view()
2430 */
2431
2432 /*!
2433     \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
2434
2435     This signal is emitted whenever the content given by \a rectToScroll needs
2436     to be scrolled \a dx and \a dy downwards and no view was set.
2437
2438     \sa view()
2439 */
2440
2441 /*!
2442     \fn void QWebPage::windowCloseRequested()
2443
2444     This signal is emitted whenever the page requests the web browser window to be closed,
2445     for example through the JavaScript \c{window.close()} call.
2446 */
2447
2448 /*!
2449     \fn void QWebPage::printRequested(QWebFrame *frame)
2450
2451     This signal is emitted whenever the page requests the web browser to print \a frame,
2452     for example through the JavaScript \c{window.print()} call.
2453
2454     \sa QWebFrame::print(), QPrintPreviewDialog
2455 */
2456
2457 /*!
2458     \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
2459
2460     This signals is emitted when webkit cannot handle a link the user navigated to.
2461
2462     At signal emissions time the meta data of the QNetworkReply \a reply is available.
2463
2464     \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
2465
2466     \sa downloadRequested()
2467 */
2468
2469 /*!
2470     \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
2471
2472     This signal is emitted when the user decides to download a link. The url of
2473     the link as well as additional meta-information is contained in \a request.
2474
2475     \sa unsupportedContent()
2476 */
2477
2478 /*!
2479     \fn void QWebPage::microFocusChanged()
2480
2481     This signal is emitted when for example the position of the cursor in an editable form
2482     element changes. It is used inform input methods about the new on-screen position where
2483     the user is able to enter text. This signal is usually connected to QWidget's updateMicroFocus()
2484     slot.
2485 */
2486
2487 /*!
2488     \fn void QWebPage::linkClicked(const QUrl &url)
2489
2490     This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
2491     property is set to delegate the link handling for the specified \a url.
2492
2493     By default no links are delegated and are handled by QWebPage instead.
2494
2495     \sa linkHovered()
2496 */
2497
2498 /*!
2499     \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
2500
2501     This signal is emitted whenever the visibility of the toolbar in a web browser
2502     window that hosts QWebPage should be changed to \a visible.
2503 */
2504
2505 /*!
2506     \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
2507
2508     This signal is emitted whenever the visibility of the statusbar in a web browser
2509     window that hosts QWebPage should be changed to \a visible.
2510 */
2511
2512 /*!
2513     \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
2514
2515     This signal is emitted whenever the visibility of the menubar in a web browser
2516     window that hosts QWebPage should be changed to \a visible.
2517 */
2518
2519 #include "moc_qwebpage.cpp"