0fcabfeebc93e0a0264bf900ecc6f5222307c1eb
[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     This class provides all functionality needed for loading images, style sheets and html
22     pages from the web. It has a memory cache for these objects.
23 */
24 #include "config.h"
25 #include "qwebpage.h"
26 #include "qwebview.h"
27 #include "qwebframe.h"
28 #include "qwebpage_p.h"
29 #include "qwebframe_p.h"
30 #include "qwebhistory.h"
31 #include "qwebhistory_p.h"
32 #include "qwebsettings.h"
33
34 #include "Frame.h"
35 #include "FrameLoaderClientQt.h"
36 #include "FrameView.h"
37 #include "ChromeClientQt.h"
38 #include "ContextMenu.h"
39 #include "ContextMenuClientQt.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 "FrameLoader.h"
47 #include "FrameLoadRequest.h"
48 #include "KURL.h"
49 #include "Image.h"
50 #include "InspectorClientQt.h"
51 #include "InspectorController.h"
52 #include "FocusController.h"
53 #include "Editor.h"
54 #include "PlatformScrollBar.h"
55 #include "PlatformKeyboardEvent.h"
56 #include "PlatformWheelEvent.h"
57 #include "ProgressTracker.h"
58 #include "RefPtr.h"
59 #include "HashMap.h"
60 #include "HitTestResult.h"
61 #include "WindowFeatures.h"
62 #include "LocalizedStrings.h"
63
64 #include <QApplication>
65 #include <QDebug>
66 #include <QDragEnterEvent>
67 #include <QDragLeaveEvent>
68 #include <QDragMoveEvent>
69 #include <QDropEvent>
70 #include <QFileDialog>
71 #include <QHttpRequestHeader>
72 #include <QInputDialog>
73 #include <QMessageBox>
74 #include <QNetworkProxy>
75 #include <QUndoStack>
76 #include <QUrl>
77 #include <QPainter>
78 #if QT_VERSION >= 0x040400
79 #include <QNetworkAccessManager>
80 #include <QNetworkRequest>
81 #else
82 #include "qwebnetworkinterface.h"
83 #endif
84
85 using namespace WebCore;
86
87 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
88 {
89     unsigned result = 0;
90     if (actions & Qt::CopyAction)
91         result |= DragOperationCopy;
92     if (actions & Qt::MoveAction)
93         result |= DragOperationMove;
94     if (actions & Qt::LinkAction)
95         result |= DragOperationLink;
96     return (DragOperation)result;
97 }
98
99 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
100 {
101     Qt::DropAction result = Qt::IgnoreAction;
102     if (actions & DragOperationCopy)
103         result = Qt::CopyAction;
104     else if (actions & DragOperationMove)
105         result = Qt::MoveAction;
106     else if (actions & DragOperationLink)
107         result = Qt::LinkAction;
108     return result;
109 }
110
111 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
112     : q(qq)
113     , view(0)
114     , modified(false)
115     , viewportSize(QSize(0,0))
116 {
117     chromeClient = new ChromeClientQt(q);
118     contextMenuClient = new ContextMenuClientQt();
119     editorClient = new EditorClientQt(q);
120     page = new Page(chromeClient, contextMenuClient, editorClient,
121                     new DragClientQt(q), new InspectorClientQt(q));
122
123     // ### should be configurable
124     page->settings()->setDefaultTextEncodingName("iso-8859-1");
125
126     settings = new QWebSettings(page->settings());
127
128     undoStack = 0;
129     mainFrame = 0;
130 #if QT_VERSION < 0x040400
131     networkInterface = 0;
132 #else
133     networkManager = 0;
134     pluginFactory = 0;
135 #endif
136     insideOpenCall = false;
137
138     history.d = new QWebHistoryPrivate(page->backForwardList());
139     memset(actions, 0, sizeof(actions));
140 }
141
142 QWebPagePrivate::~QWebPagePrivate()
143 {
144     delete undoStack;
145     delete settings;
146     delete page;
147 #if QT_VERSION >= 0x040400
148     delete networkManager;
149 #endif
150 }
151
152 #if QT_VERSION < 0x040400
153 QWebPage::NavigationRequestResponse QWebPagePrivate::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
154 {
155     if (insideOpenCall
156         && frame == mainFrame)
157         return QWebPage::AcceptNavigationRequest;
158     return q->navigationRequested(frame, request, type);
159 }
160 #else
161 QWebPage::NavigationRequestResponse QWebPagePrivate::navigationRequested(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
162 {
163     if (insideOpenCall
164         && frame == mainFrame)
165         return QWebPage::AcceptNavigationRequest;
166     return q->navigationRequested(frame, request, type);
167 }
168 #endif
169
170 void QWebPagePrivate::createMainFrame()
171 {
172     if (!mainFrame) {
173         QWebFrameData frameData;
174         frameData.ownerElement = 0;
175         frameData.allowsScrolling = true;
176         frameData.marginWidth = 0;
177         frameData.marginHeight = 0;
178         mainFrame = new QWebFrame(q, &frameData);
179         mainFrame->d->frame->view()->setFrameGeometry(IntRect(IntPoint(0,0), q->viewportSize()));
180
181         emit q->frameCreated(mainFrame);
182     }
183 }
184
185 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
186 {
187     switch (action) {
188         case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
189         case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
190         case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
191         case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
192         case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
193         case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
194         case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
195         case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
196         case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
197         case WebCore::ContextMenuItemTagGoBack: return QWebPage::GoBack;
198         case WebCore::ContextMenuItemTagGoForward: return QWebPage::GoForward;
199         case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
200         case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
201         case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
202         case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
203         case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
204         case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
205         case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
206         case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
207         case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
208         case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
209         case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
210         default: break;
211     }
212     return QWebPage::NoWebAction;
213 }
214
215 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu, const QList<WebCore::ContextMenuItem> *items)
216 {
217     QMenu *menu = new QMenu;
218     for (int i = 0; i < items->count(); ++i) {
219         const ContextMenuItem &item = items->at(i);
220         switch (item.type()) {
221             case WebCore::CheckableActionType: /* fall through */
222             case WebCore::ActionType: {
223                 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
224                 QAction *a = q->action(action);
225                 if (a) {
226                     ContextMenuItem it(item);
227                     webcoreMenu->checkOrEnableIfNeeded(it);
228                     PlatformMenuItemDescription desc = it.releasePlatformDescription();
229                     a->setEnabled(desc.enabled);
230                     a->setChecked(desc.checked);
231                     a->setCheckable(item.type() == WebCore::CheckableActionType);
232
233                     menu->addAction(a);
234                 }
235                 break;
236             }
237             case WebCore::SeparatorType:
238                 menu->addSeparator();
239                 break;
240             case WebCore::SubmenuType: {
241                 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu());
242                 if (!subMenu->actions().isEmpty()) {
243                     subMenu->setTitle(item.title());
244                     menu->addAction(subMenu->menuAction());
245                 } else {
246                     delete subMenu;
247                 }
248                 break;
249             }
250         }
251     }
252     return menu;
253 }
254
255 QWebFrame *QWebPagePrivate::frameAt(const QPoint &pos) const
256 {
257     QWebFrame *frame = mainFrame;
258
259 redo:
260     QList<QWebFrame*> children = frame->childFrames();
261     for (int i = 0; i < children.size(); ++i) {
262         if (children.at(i)->geometry().contains(pos)) {
263             frame = children.at(i);
264             goto redo;
265         }
266     }
267     if (frame->geometry().contains(pos))
268         return frame;
269     return 0;
270 }
271
272 void QWebPagePrivate::_q_webActionTriggered(bool checked)
273 {
274     QAction *a = qobject_cast<QAction *>(q->sender());
275     if (!a)
276         return;
277     QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
278     q->triggerAction(action, checked);
279 }
280
281 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
282 {
283     QAction *a = actions[action];
284     if (!a || !mainFrame)
285         return;
286
287     WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
288     WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
289
290     bool enabled = a->isEnabled();
291
292     switch (action) {
293         case QWebPage::GoBack:
294             enabled = loader->canGoBackOrForward(-1);
295             break;
296         case QWebPage::GoForward:
297             enabled = loader->canGoBackOrForward(1);
298             break;
299         case QWebPage::Stop:
300             enabled = loader->isLoading();
301             break;
302         case QWebPage::Reload:
303             enabled = !loader->isLoading();
304             break;
305         case QWebPage::Cut:
306             enabled = editor->canCut();
307             break;
308         case QWebPage::Copy:
309             enabled = editor->canCopy();
310             break;
311         case QWebPage::Paste:
312             enabled = editor->canPaste();
313             break;
314         case QWebPage::Undo:
315         case QWebPage::Redo:
316             // those two are handled by QUndoStack
317             break;
318         default: break;
319     }
320
321     a->setEnabled(enabled);
322 }
323
324 void QWebPagePrivate::updateNavigationActions()
325 {
326     updateAction(QWebPage::GoBack);
327     updateAction(QWebPage::GoForward);
328     updateAction(QWebPage::Stop);
329     updateAction(QWebPage::Reload);
330 }
331
332 void QWebPagePrivate::updateEditorActions()
333 {
334     updateAction(QWebPage::Cut);
335     updateAction(QWebPage::Copy);
336     updateAction(QWebPage::Paste);
337 }
338
339 void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev)
340 {
341     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
342     if (!frame->view())
343         return;
344
345     frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
346 }
347
348 void QWebPagePrivate::mousePressEvent(QMouseEvent *ev)
349 {
350     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
351     if (!frame->view())
352         return;
353
354     frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 1));
355 }
356
357 void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev)
358 {
359     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
360     if (!frame->view())
361         return;
362
363     frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 2));
364 }
365
366 void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev)
367 {
368     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
369     if (!frame->view())
370         return;
371
372     frame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(ev, 0));
373 }
374
375 void QWebPagePrivate::contextMenuEvent(QContextMenuEvent *ev)
376 {
377     page->contextMenuController()->clearContextMenu();
378
379     WebCore::Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
380     focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(ev, 1));
381     ContextMenu *menu = page->contextMenuController()->contextMenu();
382     // If the website defines its own handler then sendContextMenuEvent takes care of
383     // calling/showing it and the context menu pointer will be zero. This is the case
384     // on maps.google.com for example.
385     if (!menu)
386         return;
387
388     QWebPageContext oldContext = currentContext;
389     currentContext = QWebPageContext(menu->hitTestResult());
390
391     const QList<ContextMenuItem> *items = menu->platformDescription();
392     QMenu *qmenu = createContextMenu(menu, items);
393     if (qmenu) {
394         qmenu->exec(ev->globalPos());
395         delete qmenu;
396     }
397     currentContext = oldContext;
398 }
399
400 void QWebPagePrivate::wheelEvent(QWheelEvent *ev)
401 {
402     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
403     if (!frame->view())
404         return;
405
406     WebCore::PlatformWheelEvent pev(ev);
407     bool accepted = frame->eventHandler()->handleWheelEvent(pev);
408     ev->setAccepted(accepted);
409 }
410
411 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
412 {
413     bool handled = false;
414     WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
415     WebCore::Editor *editor = frame->editor();
416     if (editor->canEdit()) {
417         if (ev == QKeySequence::Cut) {
418             q->triggerAction(QWebPage::Cut);
419             handled = true;
420         } else if (ev == QKeySequence::Copy) {
421             q->triggerAction(QWebPage::Copy);
422             handled = true;
423         } else if (ev == QKeySequence::Paste) {
424             q->triggerAction(QWebPage::Paste);
425             handled = true;
426         } else if (ev == QKeySequence::Undo) {
427             q->triggerAction(QWebPage::Undo);
428             handled = true;
429         } else if (ev == QKeySequence::Redo) {
430             q->triggerAction(QWebPage::Redo);
431             handled = true;
432         } else if(ev == QKeySequence::MoveToNextChar) {
433             q->triggerAction(QWebPage::MoveToNextChar);
434             handled = true;
435         } else if(ev == QKeySequence::MoveToPreviousChar) {
436             q->triggerAction(QWebPage::MoveToPreviousChar);
437             handled = true;
438         } else if(ev == QKeySequence::MoveToNextWord) {
439             q->triggerAction(QWebPage::MoveToNextWord);
440             handled = true;
441         } else if(ev == QKeySequence::MoveToPreviousWord) {
442             q->triggerAction(QWebPage::MoveToPreviousWord);
443             handled = true;
444         } else if(ev == QKeySequence::MoveToNextLine) {
445             q->triggerAction(QWebPage::MoveToNextLine);
446             handled = true;
447         } else if(ev == QKeySequence::MoveToPreviousLine) {
448             q->triggerAction(QWebPage::MoveToPreviousLine);
449             handled = true;
450 //             } else if(ev == QKeySequence::MoveToNextPage) {
451 //             } else if(ev == QKeySequence::MoveToPreviousPage) {
452         } else if(ev == QKeySequence::MoveToStartOfLine) {
453             q->triggerAction(QWebPage::MoveToStartOfLine);
454             handled = true;
455         } else if(ev == QKeySequence::MoveToEndOfLine) {
456             q->triggerAction(QWebPage::MoveToEndOfLine);
457             handled = true;
458         } else if(ev == QKeySequence::MoveToStartOfBlock) {
459             q->triggerAction(QWebPage::MoveToStartOfBlock);
460             handled = true;
461         } else if(ev == QKeySequence::MoveToEndOfBlock) {
462             q->triggerAction(QWebPage::MoveToEndOfBlock);
463             handled = true;
464         } else if(ev == QKeySequence::MoveToStartOfDocument) {
465             q->triggerAction(QWebPage::MoveToStartOfDocument);
466             handled = true;
467         } else if(ev == QKeySequence::MoveToEndOfDocument) {
468             q->triggerAction(QWebPage::MoveToEndOfDocument);
469             handled = true;
470         } else if(ev == QKeySequence::SelectNextChar) {
471             q->triggerAction(QWebPage::SelectNextChar);
472             handled = true;
473         } else if(ev == QKeySequence::SelectPreviousChar) {
474             q->triggerAction(QWebPage::SelectPreviousChar);
475             handled = true;
476         } else if(ev == QKeySequence::SelectNextWord) {
477             q->triggerAction(QWebPage::SelectNextWord);
478             handled = true;
479         } else if(ev == QKeySequence::SelectPreviousWord) {
480             q->triggerAction(QWebPage::SelectPreviousWord);
481             handled = true;
482         } else if(ev == QKeySequence::SelectNextLine) {
483             q->triggerAction(QWebPage::SelectNextLine);
484             handled = true;
485         } else if(ev == QKeySequence::SelectPreviousLine) {
486             q->triggerAction(QWebPage::SelectPreviousLine);
487             handled = true;
488 //             } else if(ev == QKeySequence::SelectNextPage) {
489 //             } else if(ev == QKeySequence::SelectPreviousPage) {
490         } else if(ev == QKeySequence::SelectStartOfLine) {
491             q->triggerAction(QWebPage::SelectStartOfLine);
492             handled = true;
493         } else if(ev == QKeySequence::SelectEndOfLine) {
494             q->triggerAction(QWebPage::SelectEndOfLine);
495             handled = true;
496         } else if(ev == QKeySequence::SelectStartOfBlock) {
497             q->triggerAction(QWebPage::SelectStartOfBlock);
498             handled = true;
499         } else if(ev == QKeySequence::SelectEndOfBlock) {
500             q->triggerAction(QWebPage::SelectEndOfBlock);
501             handled = true;
502         } else if(ev == QKeySequence::SelectStartOfDocument) {
503             q->triggerAction(QWebPage::SelectStartOfDocument);
504             handled = true;
505         } else if(ev == QKeySequence::SelectEndOfDocument) {
506             q->triggerAction(QWebPage::SelectEndOfDocument);
507             handled = true;
508         } else if(ev == QKeySequence::DeleteStartOfWord) {
509             q->triggerAction(QWebPage::DeleteStartOfWord);
510             handled = true;
511         } else if(ev == QKeySequence::DeleteEndOfWord) {
512             q->triggerAction(QWebPage::DeleteEndOfWord);
513             handled = true;
514 //             } else if(ev == QKeySequence::DeleteEndOfLine) {
515         }
516     }
517     if (!handled)
518         handled = frame->eventHandler()->keyEvent(ev);
519     if (!handled) {
520         handled = true;
521         PlatformScrollbar *h, *v;
522         h = mainFrame->d->horizontalScrollBar();
523         v = mainFrame->d->verticalScrollBar();
524         QFont defaultFont;
525         if (view)
526             defaultFont = view->font();
527         QFontMetrics fm(defaultFont);
528         int fontHeight = fm.height();
529         if (ev == QKeySequence::MoveToNextPage
530             || ev->key() == Qt::Key_Space) {
531             if (v)
532                 v->setValue(v->value() + q->viewportSize().height() - fontHeight);
533         } else if (ev == QKeySequence::MoveToPreviousPage) {
534             if (v)
535                 v->setValue(v->value() - q->viewportSize().height() + fontHeight);
536         } else if (ev->key() == Qt::Key_Up && ev->modifiers() == Qt::ControlModifier) {
537             if (v)
538                 v->setValue(0);
539         } else if (ev->key() == Qt::Key_Down && ev->modifiers() == Qt::ControlModifier) {
540             if (v)
541                 v->setValue(INT_MAX);
542         } else {
543             switch (ev->key()) {
544             case Qt::Key_Up:
545                 if (v)
546                     v->setValue(v->value() - fontHeight);
547                 break;
548             case Qt::Key_Down:
549                 if (v)
550                     v->setValue(v->value() + fontHeight);
551                 break;
552             case Qt::Key_Left:
553                 if (h)
554                     h->setValue(h->value() - fontHeight);
555                 break;
556             case Qt::Key_Right:
557                 if (h)
558                     h->setValue(h->value() + fontHeight);
559                 break;
560             case Qt::Key_Backspace:
561                 if (ev->modifiers() == Qt::ShiftModifier)
562                     q->triggerAction(QWebPage::GoForward);
563                 else
564                     q->triggerAction(QWebPage::GoBack);
565             default:
566                 handled = false;
567                 break;
568             }
569         }
570     }
571
572     ev->setAccepted(handled);
573 }
574
575 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
576 {
577     if (ev->isAutoRepeat()) {
578         ev->setAccepted(true);
579         return;
580     }
581
582     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
583     bool handled = frame->eventHandler()->keyEvent(ev);
584     ev->setAccepted(handled);
585 }
586
587 void QWebPagePrivate::focusInEvent(QFocusEvent *ev)
588 {
589     if (ev->reason() != Qt::PopupFocusReason)
590         page->focusController()->setFocusedFrame(QWebFramePrivate::core(mainFrame));
591 }
592
593 void QWebPagePrivate::focusOutEvent(QFocusEvent *ev)
594 {
595     if (ev->reason() != Qt::PopupFocusReason)
596         page->focusController()->setFocusedFrame(0);
597 }
598
599 void QWebPagePrivate::dragEnterEvent(QDragEnterEvent *ev)
600 {
601 #ifndef QT_NO_DRAGANDDROP
602     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
603                       dropActionToDragOp(ev->possibleActions()));
604     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
605     ev->setDropAction(action);
606     ev->accept();
607 #endif
608 }
609
610 void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent *ev)
611 {
612 #ifndef QT_NO_DRAGANDDROP
613     DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
614     page->dragController()->dragExited(&dragData);
615     ev->accept();
616 #endif
617 }
618
619 void QWebPagePrivate::dragMoveEvent(QDragMoveEvent *ev)
620 {
621 #ifndef QT_NO_DRAGANDDROP
622     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
623                       dropActionToDragOp(ev->possibleActions()));
624     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
625     ev->setDropAction(action);
626     ev->accept();
627 #endif
628 }
629
630 void QWebPagePrivate::dropEvent(QDropEvent *ev)
631 {
632 #ifndef QT_NO_DRAGANDDROP
633     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
634                       dropActionToDragOp(ev->possibleActions()));
635     Qt::DropAction action = dragOpToDropAction(page->dragController()->performDrag(&dragData));
636     ev->accept();
637 #endif
638 }
639
640 /*!
641     \enum QWebPage::WebAction
642
643     \value NoWebAction No action is triggered.
644     \value OpenLink Open the current link.
645     \value OpenLinkInNewWindow Open the current link in a new window.
646     \value OpenFrameInNewWindow Replicate the current frame in a new window.
647     \value DownloadLinkToDisk Download the current link to the disk.
648     \value CopyLinkToClipboard Copy the current link to the clipboard.
649     \value OpenImageInNewWindow Open the highlighted image in a new window.
650     \value DownloadImageToDisk Download the highlighted image to the disk.
651     \value CopyImageToClipboard Copy the highlighted image to the clipboard.
652     \value GoBack Navigate back in the history of navigated links.
653     \value GoForward Navigate forward in the history of navigated links.
654     \value Stop Stop loading the current page.
655     \value Reload Reload the current page.
656     \value Cut Cut the content currently selected into the clipboard.
657     \value Copy Copy the content currently selected into the clipboard.
658     \value Paste Paste content from the clipboard.
659     \value Undo Undo the last editing action.
660     \value Redo Redo the last editing action.
661     \value MoveToNextChar Move the cursor to the next character.
662     \value MoveToPreviousChar Move the cursor to the previous character.
663     \value MoveToNextWord Move the cursor to the next word.
664     \value MoveToPreviousWord Move the cursor to the previous word.
665     \value MoveToNextLine Move the cursor to the next line.
666     \value MoveToPreviousLine Move the cursor to the previous line.
667     \value MoveToStartOfLine Move the cursor to the start of the line.
668     \value MoveToEndOfLine Move the cursor to the end of the line.
669     \value MoveToStartOfBlock Move the cursor to the start of the block.
670     \value MoveToEndOfBlock Move the cursor to the end of the block.
671     \value MoveToStartOfDocument Move the cursor to the start of the document.
672     \value MoveToEndOfDocument Move the cursor to the end of the document.
673     \value SelectNextChar Select to the next character.
674     \value SelectPreviousChar Select to the previous character.
675     \value SelectNextWord Select to the next word.
676     \value SelectPreviousWord Select to the previous word.
677     \value SelectNextLine Select to the next line.
678     \value SelectPreviousLine Select to the previous line.
679     \value SelectStartOfLine Select to the start of the line.
680     \value SelectEndOfLine Select to the end of the line.
681     \value SelectStartOfBlock Select to the start of the block.
682     \value SelectEndOfBlock Select to the end of the block.
683     \value SelectStartOfDocument Select to the start of the document.
684     \value SelectEndOfDocument Select to the end of the document.
685     \value DeleteStartOfWord Delete to the start of the word.
686     \value DeleteEndOfWord Delete to the end of the word.
687     \value SetTextDirectionDefault Set the text direction to the default direction.
688     \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
689     \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
690     \value ToggleBold Toggle the formatting between bold and normal weight.
691     \value ToggleItalic Toggle the formatting between italic and normal style.
692     \value ToggleUnderline Toggle underlining.
693     \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
694     \omitvalue WebActionCount
695
696 */
697
698 /*!
699     \class QWebPage
700     \since 4.4
701     \brief The QWebPage class provides a widget that is used to view and edit web documents.
702
703     QWebPage holds a main frame responsible for web content, settings, the history
704     of navigated links as well as actions. This class can be used, together with QWebFrame,
705     if you want to provide functionality like QWebView in a setup without widgets.
706 */
707
708 /*!
709     Constructs an empty QWebView with parent \a parent.
710 */
711 QWebPage::QWebPage(QObject *parent)
712     : QObject(parent)
713     , d(new QWebPagePrivate(this))
714 {
715     setView(qobject_cast<QWidget *>(parent));
716
717     connect(this, SIGNAL(loadProgressChanged(int)), this, SLOT(_q_onLoadProgressChanged(int)));
718 }
719
720 /*!
721     Destructor.
722 */
723 QWebPage::~QWebPage()
724 {
725     FrameLoader *loader = d->mainFrame->d->frame->loader();
726     if (loader)
727         loader->detachFromParent();
728     delete d;
729 }
730
731 /*!
732     Returns the main frame of the page.
733
734     The main frame provides access to the hierarchy of sub-frames and is also needed if you
735     want to explicitly render a web page into a given painter.
736 */
737 QWebFrame *QWebPage::mainFrame() const
738 {
739     d->createMainFrame();
740     return d->mainFrame;
741 }
742
743 /*!
744     Returns the frame currently active.
745 */
746 QWebFrame *QWebPage::currentFrame() const
747 {
748     return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame();
749 }
750
751 /*!
752     Returns a pointer to the view's history of navigated web pages.
753
754 */
755 QWebHistory *QWebPage::history() const
756 {
757     return &d->history;
758 }
759
760 /*!
761     Sets the \a view that is associated with the web page.
762
763     \sa view()
764 */
765 void QWebPage::setView(QWidget *view)
766 {
767     d->view = view;
768     setViewportSize(view ? view->size() : QSize(0, 0));
769 }
770
771 /*!
772     Returns the view widget that is associated with the web page.
773
774     \sa setView()
775 */
776 QWidget *QWebPage::view() const
777 {
778     return d->view;
779 }
780
781
782 /*!
783     This function is called whenever a JavaScript program tries to print to what is the console in web browsers.
784 */
785 void QWebPage::javaScriptConsoleMessage(const QString& message, unsigned int lineNumber, const QString& sourceID)
786 {
787 }
788
789 /*!
790     This function is called whenever a JavaScript program calls the alert() function.
791 */
792 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
793 {
794     QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Ok);
795 }
796
797 /*!
798     This function is called whenever a JavaScript program calls the confirm() function.
799 */
800 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
801 {
802     return 0 == QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Yes, QMessageBox::No);
803 }
804
805 /*!
806     This function is called whenever a JavaScript program tries to prompt the user of input.
807 */
808 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
809 {
810     bool ok = false;
811 #ifndef QT_NO_INPUTDIALOG
812     QString x = QInputDialog::getText(d->view, mainFrame()->title(), msg, QLineEdit::Normal, defaultValue, &ok);
813     if (ok && result) {
814         *result = x;
815     }
816 #endif
817     return ok;
818 }
819
820 /*!
821     This function is called whenever WebKit wants to create a new window, for example as a result of
822     a JavaScript request to open a document in a new window.
823 */
824 QWebPage *QWebPage::createWindow()
825 {
826     QWebView *webView = qobject_cast<QWebView *>(d->view);
827     if (webView) {
828         QWebView *newView = webView->createWindow();
829         if (newView)
830             return newView->page();
831     }
832     return 0;
833 }
834
835 /*!
836     This function is called whenever WebKit wants to create a new window that should act as a modal dialog.
837 */
838 QWebPage *QWebPage::createModalDialog()
839 {
840     return 0;
841 }
842
843 /*!
844     This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin".
845     The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and
846     child elements to configure the embeddable object.
847 */
848 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
849 {
850     Q_UNUSED(classid)
851     Q_UNUSED(url)
852     Q_UNUSED(paramNames)
853     Q_UNUSED(paramValues)
854     return 0;
855 }
856
857 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
858 {
859     WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer());
860     return WebCore::FrameLoadRequest(rr);
861 }
862
863 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
864 {
865     if (Page* oldPage = frame->page()) {
866         WindowFeatures features;
867         if (Page* newPage = oldPage->chrome()->createWindow(frame,
868                 frameLoadRequest(url, frame), features))
869             newPage->chrome()->show();
870     }
871 }
872
873 /*!
874     This function can be called to trigger the specified \a action.
875     It is also called by QtWebKit if the user triggers the action, for example
876     through a context menu item.
877
878     If \a action is a checkable action then \a checked specified whether the action
879     is toggled or not.
880 */
881 void QWebPage::triggerAction(WebAction action, bool checked)
882 {
883     WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
884     WebCore::Editor *editor = frame->editor();
885     const char *command = 0;
886
887     switch (action) {
888         case OpenLink:
889             if (QWebFrame *targetFrame = d->currentContext.targetFrame()) {
890                 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
891                 targetFrame->d->frame->loader()->load(frameLoadRequest(d->currentContext.linkUrl(), wcFrame.get()),
892                                                       /*lockHistory*/ false,
893                                                       /*userGesture*/ true,
894                                                       /*event*/ 0,
895                                                       /*HTMLFormElement*/ 0,
896                                                       /*formValues*/
897                                                       WTF::HashMap<String, String>());
898                 break;
899             } else {
900             }
901             // fall through
902         case OpenLinkInNewWindow:
903             openNewWindow(d->currentContext.linkUrl(), frame);
904             break;
905         case OpenFrameInNewWindow:
906             break;
907         case CopyLinkToClipboard:
908             editor->copyURL(d->currentContext.linkUrl(), d->currentContext.text());
909             break;
910         case OpenImageInNewWindow:
911             openNewWindow(d->currentContext.imageUrl(), frame);
912             break;
913         case DownloadImageToDisk:
914         case DownloadLinkToDisk:
915             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->currentContext.linkUrl(), frame->loader()->outgoingReferrer()));
916             break;
917         case CopyImageToClipboard:
918             break;
919         case GoBack:
920             d->page->goBack();
921             break;
922         case GoForward:
923             d->page->goForward();
924             break;
925         case Stop:
926             mainFrame()->d->frame->loader()->stopForUserCancel();
927             break;
928         case Reload:
929             mainFrame()->d->frame->loader()->reload();
930             break;
931         case Cut:
932             command = "Cut";
933             break;
934         case Copy:
935             command = "Copy";
936             break;
937         case Paste:
938             command = "Paste";
939             break;
940
941         case Undo:
942             command = "Undo";
943             break;
944         case Redo:
945             command = "Redo";
946             break;
947
948         case MoveToNextChar:
949             command = "MoveForward";
950             break;
951         case MoveToPreviousChar:
952             command = "MoveBackward";
953             break;
954         case MoveToNextWord:
955             command = "MoveWordForward";
956             break;
957         case MoveToPreviousWord:
958             command = "MoveWordBackward";
959             break;
960         case MoveToNextLine:
961             command = "MoveDown";
962             break;
963         case MoveToPreviousLine:
964             command = "MoveUp";
965             break;
966         case MoveToStartOfLine:
967             command = "MoveToBeginningOfLine";
968             break;
969         case MoveToEndOfLine:
970             command = "MoveToEndOfLine";
971             break;
972         case MoveToStartOfBlock:
973             command = "MoveToBeginningOfParagraph";
974             break;
975         case MoveToEndOfBlock:
976             command = "MoveToEndOfParagraph";
977             break;
978         case MoveToStartOfDocument:
979             command = "MoveToBeginningOfDocument";
980             break;
981         case MoveToEndOfDocument:
982             command = "MoveToEndOfDocument";
983             break;
984         case SelectNextChar:
985             command = "MoveForwardAndModifySelection";
986             break;
987         case SelectPreviousChar:
988             command = "MoveBackwardAndModifySelection";
989             break;
990         case SelectNextWord:
991             command = "MoveWordForwardAndModifySelection";
992             break;
993         case SelectPreviousWord:
994             command = "MoveWordBackwardAndModifySelection";
995             break;
996         case SelectNextLine:
997             command = "MoveDownAndModifySelection";
998             break;
999         case SelectPreviousLine:
1000             command = "MoveUpAndModifySelection";
1001             break;
1002         case SelectStartOfLine:
1003             command = "MoveToBeginningOfLineAndModifySelection";
1004             break;
1005         case SelectEndOfLine:
1006             command = "MoveToEndOfLineAndModifySelection";
1007             break;
1008         case SelectStartOfBlock:
1009             command = "MoveToBeginningOfParagraphAndModifySelection";
1010             break;
1011         case SelectEndOfBlock:
1012             command = "MoveToEndOfParagraphAndModifySelection";
1013             break;
1014         case SelectStartOfDocument:
1015             command = "MoveToBeginningOfDocumentAndModifySelection";
1016             break;
1017         case SelectEndOfDocument:
1018             command = "MoveToEndOfDocumentAndModifySelection";
1019             break;
1020         case DeleteStartOfWord:
1021             command = "DeleteWordBackward";
1022             break;
1023         case DeleteEndOfWord:
1024             command = "DeleteWordForward";
1025             break;
1026
1027         case SetTextDirectionDefault:
1028             editor->setBaseWritingDirection("inherit");
1029             break;
1030         case SetTextDirectionLeftToRight:
1031             editor->setBaseWritingDirection("ltr");
1032             break;
1033         case SetTextDirectionRightToLeft:
1034             editor->setBaseWritingDirection("rtl");
1035             break;
1036
1037         case ToggleBold:
1038             command = "ToggleBold";
1039             break;
1040         case ToggleItalic:
1041             command = "ToggleItalic";
1042             break;
1043         case ToggleUnderline:
1044             editor->toggleUnderline();
1045
1046         case InspectElement:
1047             d->page->inspectorController()->inspect(d->currentContext.d->innerNonSharedNode.get());
1048             break;
1049
1050         default: break;
1051     }
1052
1053     if (command)
1054         editor->command(command).execute();
1055 }
1056
1057 QSize QWebPage::viewportSize() const
1058 {
1059     if (d->mainFrame && d->mainFrame->d->frame->view())
1060         return d->mainFrame->d->frame->view()->frameGeometry().size();
1061
1062     return d->viewportSize;
1063 }
1064
1065 /*!
1066     \property QWebPage::viewportSize
1067
1068     Specifies the size of the viewport. The size affects for example the visibility of scrollbars
1069     if the document is larger than the viewport.
1070 */
1071 void QWebPage::setViewportSize(const QSize &size) const
1072 {
1073     d->viewportSize = size;
1074
1075     QWebFrame *frame = mainFrame();
1076     if (frame->d->frame && frame->d->frame->view()) {
1077         WebCore::FrameView* view = frame->d->frame->view();
1078         view->setFrameGeometry(QRect(QPoint(0, 0), size));
1079         frame->d->frame->forceLayout();
1080         view->adjustViewSize();
1081     }
1082 }
1083
1084
1085 #if QT_VERSION < 0x040400
1086 QWebPage::NavigationRequestResponse QWebPage::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
1087 #else
1088 QWebPage::NavigationRequestResponse QWebPage::navigationRequested(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
1089 #endif
1090 {
1091     Q_UNUSED(request)
1092     return AcceptNavigationRequest;
1093 }
1094
1095 /*!
1096     \property QWebPage::selectedText
1097
1098     Returns the text currently selected.
1099 */
1100 QString QWebPage::selectedText() const
1101 {
1102     return d->page->focusController()->focusedOrMainFrame()->selectedText();
1103 }
1104
1105 /*!
1106    Returns a QAction for the specified WebAction \a action.
1107
1108    The action is owned by the QWebPage but you can customize the look by
1109    changing its properties.
1110
1111    QWebPage also takes care of implementing the action, so that upon
1112    triggering the corresponding action is performed on the page.
1113 */
1114 QAction *QWebPage::action(WebAction action) const
1115 {
1116     if (action == QWebPage::NoWebAction) return 0;
1117     if (d->actions[action])
1118         return d->actions[action];
1119
1120     QString text;
1121     QIcon icon;
1122     QStyle *style = view() ? view()->style() : qApp->style();
1123     bool checkable = false;
1124
1125     switch (action) {
1126         case OpenLink:
1127             text = contextMenuItemTagOpenLink();
1128             break;
1129         case OpenLinkInNewWindow:
1130             text = contextMenuItemTagOpenLinkInNewWindow();
1131             break;
1132         case OpenFrameInNewWindow:
1133             text = contextMenuItemTagOpenFrameInNewWindow();
1134             break;
1135
1136         case DownloadLinkToDisk:
1137             text = contextMenuItemTagDownloadLinkToDisk();
1138             break;
1139         case CopyLinkToClipboard:
1140             text = contextMenuItemTagCopyLinkToClipboard();
1141             break;
1142
1143         case OpenImageInNewWindow:
1144             text = contextMenuItemTagOpenImageInNewWindow();
1145             break;
1146         case DownloadImageToDisk:
1147             text = contextMenuItemTagDownloadImageToDisk();
1148             break;
1149         case CopyImageToClipboard:
1150             text = contextMenuItemTagCopyImageToClipboard();
1151             break;
1152
1153         case GoBack:
1154             text = contextMenuItemTagGoBack();
1155 #if QT_VERSION >= 0x040400
1156             icon = style->standardIcon(QStyle::SP_ArrowBack);
1157 #endif
1158             break;
1159         case GoForward:
1160             text = contextMenuItemTagGoForward();
1161 #if QT_VERSION >= 0x040400
1162             icon = style->standardIcon(QStyle::SP_ArrowForward);
1163 #endif
1164             break;
1165         case Stop:
1166             text = contextMenuItemTagStop();
1167 #if QT_VERSION >= 0x040400
1168             icon = style->standardIcon(QStyle::SP_BrowserStop);
1169 #endif
1170             break;
1171         case Reload:
1172             text = contextMenuItemTagReload();
1173 #if QT_VERSION >= 0x040400
1174             icon = style->standardIcon(QStyle::SP_BrowserReload);
1175 #endif
1176             break;
1177
1178         case Cut:
1179             text = contextMenuItemTagCut();
1180             break;
1181         case Copy:
1182             text = contextMenuItemTagCopy();
1183             break;
1184         case Paste:
1185             text = contextMenuItemTagPaste();
1186             break;
1187
1188         case Undo: {
1189             QAction *a = undoStack()->createUndoAction(d->q);
1190             d->actions[action] = a;
1191             return a;
1192         }
1193         case Redo: {
1194             QAction *a = undoStack()->createRedoAction(d->q);
1195             d->actions[action] = a;
1196             return a;
1197         }
1198         case MoveToNextChar:
1199         case MoveToPreviousChar:
1200         case MoveToNextWord:
1201         case MoveToPreviousWord:
1202         case MoveToNextLine:
1203         case MoveToPreviousLine:
1204         case MoveToStartOfLine:
1205         case MoveToEndOfLine:
1206         case MoveToStartOfBlock:
1207         case MoveToEndOfBlock:
1208         case MoveToStartOfDocument:
1209         case MoveToEndOfDocument:
1210         case SelectNextChar:
1211         case SelectPreviousChar:
1212         case SelectNextWord:
1213         case SelectPreviousWord:
1214         case SelectNextLine:
1215         case SelectPreviousLine:
1216         case SelectStartOfLine:
1217         case SelectEndOfLine:
1218         case SelectStartOfBlock:
1219         case SelectEndOfBlock:
1220         case SelectStartOfDocument:
1221         case SelectEndOfDocument:
1222         case DeleteStartOfWord:
1223         case DeleteEndOfWord:
1224             break; // ####
1225
1226         case SetTextDirectionDefault:
1227             text = contextMenuItemTagDefaultDirection();
1228             break;
1229         case SetTextDirectionLeftToRight:
1230             text = contextMenuItemTagLeftToRight();
1231             checkable = true;
1232             break;
1233         case SetTextDirectionRightToLeft:
1234             text = contextMenuItemTagRightToLeft();
1235             checkable = true;
1236             break;
1237
1238         case ToggleBold:
1239             text = contextMenuItemTagBold();
1240             checkable = true;
1241             break;
1242         case ToggleItalic:
1243             text = contextMenuItemTagItalic();
1244             checkable = true;
1245             break;
1246         case ToggleUnderline:
1247             text = contextMenuItemTagUnderline();
1248             checkable = true;
1249             break;
1250
1251         case InspectElement:
1252             text = contextMenuItemTagInspectElement();
1253             break;
1254
1255         case NoWebAction:
1256             return 0;
1257     }
1258
1259     if (text.isEmpty())
1260         return 0;
1261
1262     QAction *a = new QAction(d->q);
1263     a->setText(text);
1264     a->setData(action);
1265     a->setCheckable(checkable);
1266     a->setIcon(icon);
1267
1268     connect(a, SIGNAL(triggered(bool)),
1269             this, SLOT(_q_webActionTriggered(bool)));
1270
1271     d->actions[action] = a;
1272     d->updateAction(action);
1273     return a;
1274 }
1275
1276 /*!
1277     \property QWebPage::modified
1278
1279     Specifies if the page contains unsubmitted form data.
1280 */
1281 bool QWebPage::isModified() const
1282 {
1283     return d->modified;
1284 }
1285
1286
1287 /*!
1288     Returns a pointer to the undo stack used for editable content.
1289 */
1290 QUndoStack *QWebPage::undoStack() const
1291 {
1292     if (!d->undoStack)
1293         d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
1294
1295     return d->undoStack;
1296 }
1297
1298 /*! \reimp
1299 */
1300 bool QWebPage::event(QEvent *ev)
1301 {
1302     switch (ev->type()) {
1303     case QEvent::MouseMove:
1304         d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
1305         break;
1306     case QEvent::MouseButtonPress:
1307         d->mousePressEvent(static_cast<QMouseEvent*>(ev));
1308         break;
1309     case QEvent::MouseButtonDblClick:
1310         d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
1311         break;
1312     case QEvent::MouseButtonRelease:
1313         d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
1314         break;
1315     case QEvent::ContextMenu:
1316         d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev));
1317         break;
1318     case QEvent::Wheel:
1319         d->wheelEvent(static_cast<QWheelEvent*>(ev));
1320         break;
1321     case QEvent::KeyPress:
1322         d->keyPressEvent(static_cast<QKeyEvent*>(ev));
1323         break;
1324     case QEvent::KeyRelease:
1325         d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
1326         break;
1327     case QEvent::FocusIn:
1328         d->focusInEvent(static_cast<QFocusEvent*>(ev));
1329         break;
1330     case QEvent::FocusOut:
1331         d->focusOutEvent(static_cast<QFocusEvent*>(ev));
1332         break;
1333 #ifndef QT_NO_DRAGANDDROP
1334     case QEvent::DragEnter:
1335         d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
1336         break;
1337     case QEvent::DragLeave:
1338         d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
1339         break;
1340     case QEvent::DragMove:
1341         d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
1342         break;
1343     case QEvent::Drop:
1344         d->dropEvent(static_cast<QDropEvent*>(ev));
1345         break;
1346 #endif
1347     default:
1348         return QObject::event(ev);
1349     }
1350
1351     return true;
1352 }
1353
1354 /*!
1355     Similar to QWidget::focusNextPrevChild it focuses the next focusable web element
1356     if \a next is true. Otherwise the previous element is focused.
1357 */
1358 bool QWebPage::focusNextPrevChild(bool next)
1359 {
1360     QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
1361     d->keyPressEvent(&ev);
1362     bool hasFocusedNode = false;
1363     Frame *frame = d->page->focusController()->focusedFrame();
1364     if (frame) {
1365         Document *document = frame->document();
1366         hasFocusedNode = document && document->focusedNode();
1367     }
1368     //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
1369     return hasFocusedNode;
1370 }
1371
1372 /*!
1373     Returns a pointe to the page's settings object.
1374 */
1375 QWebSettings *QWebPage::settings()
1376 {
1377     return d->settings;
1378 }
1379
1380 /*!
1381     This function is called when the web content requests a file name, for example
1382     as a result of the user clicking on a "file upload" button in a HTML form.
1383 */
1384 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& oldFile)
1385 {
1386 #ifndef QT_NO_FILEDIALOG
1387     return QFileDialog::getOpenFileName(d->view, QString::null, oldFile);
1388 #else
1389     return QString::null;
1390 #endif
1391 }
1392
1393 #if QT_VERSION < 0x040400
1394
1395 void QWebPage::setNetworkInterface(QWebNetworkInterface *interface)
1396 {
1397     d->networkInterface = interface;
1398 }
1399
1400 QWebNetworkInterface *QWebPage::networkInterface() const
1401 {
1402     if (d->networkInterface)
1403         return d->networkInterface;
1404     else
1405         return QWebNetworkInterface::defaultInterface();
1406 }
1407
1408 #ifndef QT_NO_NETWORKPROXY
1409 void QWebPage::setNetworkProxy(const QNetworkProxy& proxy)
1410 {
1411     d->networkProxy = proxy;
1412 }
1413
1414 QNetworkProxy QWebPage::networkProxy() const
1415 {
1416     return d->networkProxy;
1417 }
1418 #endif
1419
1420 #else
1421
1422 /*!
1423     Sets the QNetworkAccessManager \a manager that is responsible for serving network
1424     requests for this QWebPage.
1425
1426     \sa networkAccessManager
1427 */
1428 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
1429 {
1430     if (manager == d->networkManager)
1431         return;
1432     delete d->networkManager;
1433     d->networkManager = manager;
1434 }
1435
1436 /*!
1437     Returns the QNetworkAccessManager \a manager that is responsible for serving network
1438     requests for this QWebPage.
1439
1440     \sa setNetworkAccessManager
1441 */
1442 QNetworkAccessManager *QWebPage::networkAccessManager() const
1443 {
1444     if (!d->networkManager) {
1445         QWebPage *that = const_cast<QWebPage *>(this);
1446         that->d->networkManager = new QNetworkAccessManager(that);
1447     }
1448     return d->networkManager;
1449 }
1450
1451 #endif
1452
1453 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
1454 {
1455     d->pluginFactory = factory;
1456 }
1457
1458 QWebPluginFactory *QWebPage::pluginFactory() const
1459 {
1460     return d->pluginFactory;
1461 }
1462
1463 /*!
1464     This function is called when a user agent for HTTP requests is needed. You can re-implement this
1465     function to dynamically return different user agent's for different urls, based on the \a url parameter.
1466 */
1467 QString QWebPage::userAgentFor(const QUrl& url) const
1468 {
1469     Q_UNUSED(url)
1470     return QLatin1String("Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/523.15 (KHTML, like Gecko) Safari/419.3 Qt");
1471 }
1472
1473
1474 void QWebPagePrivate::_q_onLoadProgressChanged(int) {
1475     m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
1476     m_bytesReceived = page->progress()->totalBytesReceived();
1477 }
1478
1479
1480 /*!
1481     Returns the total number of bytes that were received from the network to render the current page,
1482     including extra content such as embedded images.
1483 */
1484 quint64 QWebPage::totalBytes() const {
1485     return d->m_bytesReceived;
1486 }
1487
1488
1489 /*!
1490     Returns the number of bytes that were received from the network to render the current page.
1491 */
1492 quint64 QWebPage::bytesReceived() const {
1493     return d->m_totalBytes;
1494 }
1495
1496 QWebPageContext::QWebPageContext(const WebCore::HitTestResult &hitTest)
1497     : d(new QWebPageContextPrivate)
1498 {
1499     d->pos = hitTest.point();
1500     d->text = hitTest.textContent();
1501     d->linkUrl = hitTest.absoluteLinkURL().string();
1502     d->imageUrl = hitTest.absoluteImageURL().string();
1503     d->innerNonSharedNode = hitTest.innerNonSharedNode();
1504     WebCore::Image *img = hitTest.image();
1505     if (img) {
1506         QPixmap *pix = img->getPixmap();
1507         if (pix)
1508             d->image = *pix;
1509     }
1510     WebCore::Frame *frame = hitTest.targetFrame();
1511     if (frame)
1512         d->targetFrame = QWebFramePrivate::kit(frame);
1513 }
1514
1515 QWebPageContext::QWebPageContext()
1516     : d(0)
1517 {
1518 }
1519
1520 QWebPageContext::QWebPageContext(const QWebPageContext &other)
1521     : d(0)
1522 {
1523     if (other.d)
1524         d = new QWebPageContextPrivate(*other.d);
1525 }
1526
1527 QWebPageContext &QWebPageContext::operator=(const QWebPageContext &other)
1528 {
1529     if (this != &other) {
1530         if (other.d) {
1531             if (!d)
1532                 d = new QWebPageContextPrivate;
1533             *d = *other.d;
1534         } else {
1535             delete d;
1536             d = 0;
1537         }
1538     }
1539     return *this;
1540 }
1541
1542 QWebPageContext::~QWebPageContext()
1543 {
1544     delete d;
1545 }
1546
1547 QPoint QWebPageContext::pos() const
1548 {
1549     if (!d)
1550         return QPoint();
1551     return d->pos;
1552 }
1553
1554 QString QWebPageContext::text() const
1555 {
1556     if (!d)
1557         return QString();
1558     return d->text;
1559 }
1560
1561 QUrl QWebPageContext::linkUrl() const
1562 {
1563     if (!d)
1564         return QUrl();
1565     return d->linkUrl;
1566 }
1567
1568 QUrl QWebPageContext::imageUrl() const
1569 {
1570     if (!d)
1571         return QUrl();
1572     return d->linkUrl;
1573 }
1574
1575 QPixmap QWebPageContext::image() const
1576 {
1577     if (!d)
1578         return QPixmap();
1579     return d->image;
1580 }
1581
1582 QWebFrame *QWebPageContext::targetFrame() const
1583 {
1584     if (!d)
1585         return 0;
1586     return d->targetFrame;
1587 }
1588
1589 /*!
1590     \fn void QWebPage::loadProgressChanged(int progress)
1591
1592     This signal is emitted when the global progress status changes.
1593     The current value is provided by \a progress in percent.
1594     It accumulates changes from all the child frames.
1595 */
1596
1597 /*!
1598     \fn void QWebPage::hoveringOverLink(const QString &link, const QString &title, const QString &textContent)
1599
1600     This signal is emitted when the mouse is hovering over a link.
1601     The first parameter is the \a link url, the second is the link \a title
1602     if any, and third \a textContent is the text content. Method is emitter with both
1603     empty parameters when the mouse isn't hovering over any link element.
1604 */
1605
1606 /*!
1607     \fn void QWebPage::statusBarTextChanged(const QString& text)
1608
1609     This signal is emitted when the statusbar \a text is changed by the page.
1610 */
1611
1612 /*!
1613     \fn void QWebPage::frameCreated(QWebFrame *frame)
1614
1615     This signal is emitted whenever the page creates a new \a frame.
1616 */
1617
1618 /*!
1619     \fn void QWebPage::selectionChanged()
1620
1621     This signal is emitted whenever the selection changes.
1622 */
1623
1624 /*!
1625     \fn void QWebPage::geometryChangeRequest(const QRect& geom)
1626
1627     This signal is emitted whenever the document wants to change the position and size of the
1628     page to \a geom. This can happen for example through JavaScript.
1629 */
1630
1631 /*!
1632     \fn void QWebPage::handleUnsupportedContent(QNetworkReply *reply)
1633
1634     This signals is emitted when webkit cannot handle a link the user navigated to.
1635
1636     At signal emissions time the meta data of the QNetworkReply is available.
1637 */
1638
1639 /*!
1640     \fn void QWebPage::download(const QNetworkRequest &request)
1641
1642     This signals is emitted when the user decides to download a link.
1643 */
1644
1645 #include "moc_qwebpage.cpp"