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