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