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