ebe94c2cc432e43677a884d22b403971afca474e
[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 {
116     chromeClient = new ChromeClientQt(q);
117     contextMenuClient = new ContextMenuClientQt();
118     editorClient = new EditorClientQt(q);
119     page = new Page(chromeClient, contextMenuClient, editorClient,
120                     new DragClientQt(q), new InspectorClientQt(q));
121
122     // ### should be configurable
123     page->settings()->setDefaultTextEncodingName("iso-8859-1");
124
125     settings = new QWebSettings(page->settings());
126
127     undoStack = 0;
128     mainFrame = 0;
129 #if QT_VERSION < 0x040400
130     networkInterface = 0;
131 #else
132     networkManager = 0;
133     pluginFactory = 0;
134 #endif
135     insideOpenCall = false;
136
137     history.d = new QWebHistoryPrivate(page->backForwardList());
138     memset(actions, 0, sizeof(actions));
139 }
140
141 QWebPagePrivate::~QWebPagePrivate()
142 {
143     delete undoStack;
144     delete settings;
145     delete page;
146 #if QT_VERSION >= 0x040400
147     delete networkManager;
148 #endif
149 }
150
151 #if QT_VERSION < 0x040400
152 QWebPage::NavigationRequestResponse QWebPagePrivate::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
153 {
154     if (insideOpenCall
155         && frame == mainFrame)
156         return QWebPage::AcceptNavigationRequest;
157     return q->navigationRequested(frame, request, type);
158 }
159 #else
160 QWebPage::NavigationRequestResponse QWebPagePrivate::navigationRequested(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
161 {
162     if (insideOpenCall
163         && frame == mainFrame)
164         return QWebPage::AcceptNavigationRequest;
165     return q->navigationRequested(frame, request, type);
166 }
167 #endif
168
169 void QWebPagePrivate::createMainFrame()
170 {
171     if (!mainFrame) {
172         QWebFrameData frameData;
173         frameData.ownerElement = 0;
174         frameData.allowsScrolling = true;
175         frameData.marginWidth = 0;
176         frameData.marginHeight = 0;
177         mainFrame = new QWebFrame(q, &frameData);
178         mainFrame->d->frameView->setFrameGeometry(IntRect(IntPoint(0,0), q->viewportSize()));
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     QWebFrame *frame = mainFrame();
1059     if (frame->d->frame && frame->d->frame->view())
1060         return frame->d->frame->view()->frameGeometry().size();
1061     return QSize(0, 0);
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     QWebFrame *frame = mainFrame();
1073     if (frame->d->frame && frame->d->frame->view()) {
1074         WebCore::FrameView* view = frame->d->frame->view();
1075         view->setFrameGeometry(QRect(QPoint(0, 0), size));
1076         frame->d->frame->forceLayout();
1077         view->adjustViewSize();
1078     }
1079 }
1080
1081
1082 #if QT_VERSION < 0x040400
1083 QWebPage::NavigationRequestResponse QWebPage::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
1084 #else
1085 QWebPage::NavigationRequestResponse QWebPage::navigationRequested(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
1086 #endif
1087 {
1088     Q_UNUSED(request)
1089     return AcceptNavigationRequest;
1090 }
1091
1092 /*!
1093     \property QWebPage::selectedText
1094
1095     Returns the text currently selected.
1096 */
1097 QString QWebPage::selectedText() const
1098 {
1099     return d->page->focusController()->focusedOrMainFrame()->selectedText();
1100 }
1101
1102 /*!
1103    Returns a QAction for the specified WebAction \a action.
1104
1105    The action is owned by the QWebPage but you can customize the look by
1106    changing its properties.
1107
1108    QWebPage also takes care of implementing the action, so that upon
1109    triggering the corresponding action is performed on the page.
1110 */
1111 QAction *QWebPage::action(WebAction action) const
1112 {
1113     if (action == QWebPage::NoWebAction) return 0;
1114     if (d->actions[action])
1115         return d->actions[action];
1116
1117     QString text;
1118     QIcon icon;
1119     QStyle *style = view() ? view()->style() : qApp->style();
1120     bool checkable = false;
1121
1122     switch (action) {
1123         case OpenLink:
1124             text = contextMenuItemTagOpenLink();
1125             break;
1126         case OpenLinkInNewWindow:
1127             text = contextMenuItemTagOpenLinkInNewWindow();
1128             break;
1129         case OpenFrameInNewWindow:
1130             text = contextMenuItemTagOpenFrameInNewWindow();
1131             break;
1132
1133         case DownloadLinkToDisk:
1134             text = contextMenuItemTagDownloadLinkToDisk();
1135             break;
1136         case CopyLinkToClipboard:
1137             text = contextMenuItemTagCopyLinkToClipboard();
1138             break;
1139
1140         case OpenImageInNewWindow:
1141             text = contextMenuItemTagOpenImageInNewWindow();
1142             break;
1143         case DownloadImageToDisk:
1144             text = contextMenuItemTagDownloadImageToDisk();
1145             break;
1146         case CopyImageToClipboard:
1147             text = contextMenuItemTagCopyImageToClipboard();
1148             break;
1149
1150         case GoBack:
1151             text = contextMenuItemTagGoBack();
1152 #if QT_VERSION >= 0x040400
1153             icon = style->standardIcon(QStyle::SP_ArrowBack);
1154 #endif
1155             break;
1156         case GoForward:
1157             text = contextMenuItemTagGoForward();
1158 #if QT_VERSION >= 0x040400
1159             icon = style->standardIcon(QStyle::SP_ArrowForward);
1160 #endif
1161             break;
1162         case Stop:
1163             text = contextMenuItemTagStop();
1164 #if QT_VERSION >= 0x040400
1165             icon = style->standardIcon(QStyle::SP_BrowserStop);
1166 #endif
1167             break;
1168         case Reload:
1169             text = contextMenuItemTagReload();
1170 #if QT_VERSION >= 0x040400
1171             icon = style->standardIcon(QStyle::SP_BrowserReload);
1172 #endif
1173             break;
1174
1175         case Cut:
1176             text = contextMenuItemTagCut();
1177             break;
1178         case Copy:
1179             text = contextMenuItemTagCopy();
1180             break;
1181         case Paste:
1182             text = contextMenuItemTagPaste();
1183             break;
1184
1185         case Undo: {
1186             QAction *a = undoStack()->createUndoAction(d->q);
1187             d->actions[action] = a;
1188             return a;
1189         }
1190         case Redo: {
1191             QAction *a = undoStack()->createRedoAction(d->q);
1192             d->actions[action] = a;
1193             return a;
1194         }
1195         case MoveToNextChar:
1196         case MoveToPreviousChar:
1197         case MoveToNextWord:
1198         case MoveToPreviousWord:
1199         case MoveToNextLine:
1200         case MoveToPreviousLine:
1201         case MoveToStartOfLine:
1202         case MoveToEndOfLine:
1203         case MoveToStartOfBlock:
1204         case MoveToEndOfBlock:
1205         case MoveToStartOfDocument:
1206         case MoveToEndOfDocument:
1207         case SelectNextChar:
1208         case SelectPreviousChar:
1209         case SelectNextWord:
1210         case SelectPreviousWord:
1211         case SelectNextLine:
1212         case SelectPreviousLine:
1213         case SelectStartOfLine:
1214         case SelectEndOfLine:
1215         case SelectStartOfBlock:
1216         case SelectEndOfBlock:
1217         case SelectStartOfDocument:
1218         case SelectEndOfDocument:
1219         case DeleteStartOfWord:
1220         case DeleteEndOfWord:
1221             break; // ####
1222
1223         case SetTextDirectionDefault:
1224             text = contextMenuItemTagDefaultDirection();
1225             break;
1226         case SetTextDirectionLeftToRight:
1227             text = contextMenuItemTagLeftToRight();
1228             checkable = true;
1229             break;
1230         case SetTextDirectionRightToLeft:
1231             text = contextMenuItemTagRightToLeft();
1232             checkable = true;
1233             break;
1234
1235         case ToggleBold:
1236             text = contextMenuItemTagBold();
1237             checkable = true;
1238             break;
1239         case ToggleItalic:
1240             text = contextMenuItemTagItalic();
1241             checkable = true;
1242             break;
1243         case ToggleUnderline:
1244             text = contextMenuItemTagUnderline();
1245             checkable = true;
1246             break;
1247
1248         case InspectElement:
1249             text = contextMenuItemTagInspectElement();
1250             break;
1251
1252         case NoWebAction:
1253             return 0;
1254     }
1255
1256     if (text.isEmpty())
1257         return 0;
1258
1259     QAction *a = new QAction(d->q);
1260     a->setText(text);
1261     a->setData(action);
1262     a->setCheckable(checkable);
1263     a->setIcon(icon);
1264
1265     connect(a, SIGNAL(triggered(bool)),
1266             this, SLOT(_q_webActionTriggered(bool)));
1267
1268     d->actions[action] = a;
1269     d->updateAction(action);
1270     return a;
1271 }
1272
1273 /*!
1274     \property QWebPage::modified
1275
1276     Specifies if the page contains unsubmitted form data.
1277 */
1278 bool QWebPage::isModified() const
1279 {
1280     return d->modified;
1281 }
1282
1283
1284 /*!
1285     Returns a pointer to the undo stack used for editable content.
1286 */
1287 QUndoStack *QWebPage::undoStack() const
1288 {
1289     if (!d->undoStack)
1290         d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
1291
1292     return d->undoStack;
1293 }
1294
1295 /*! \reimp
1296 */
1297 bool QWebPage::event(QEvent *ev)
1298 {
1299     switch (ev->type()) {
1300     case QEvent::MouseMove:
1301         d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
1302         break;
1303     case QEvent::MouseButtonPress:
1304         d->mousePressEvent(static_cast<QMouseEvent*>(ev));
1305         break;
1306     case QEvent::MouseButtonDblClick:
1307         d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
1308         break;
1309     case QEvent::MouseButtonRelease:
1310         d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
1311         break;
1312     case QEvent::ContextMenu:
1313         d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev));
1314         break;
1315     case QEvent::Wheel:
1316         d->wheelEvent(static_cast<QWheelEvent*>(ev));
1317         break;
1318     case QEvent::KeyPress:
1319         d->keyPressEvent(static_cast<QKeyEvent*>(ev));
1320         break;
1321     case QEvent::KeyRelease:
1322         d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
1323         break;
1324     case QEvent::FocusIn:
1325         d->focusInEvent(static_cast<QFocusEvent*>(ev));
1326         break;
1327     case QEvent::FocusOut:
1328         d->focusOutEvent(static_cast<QFocusEvent*>(ev));
1329         break;
1330 #ifndef QT_NO_DRAGANDDROP
1331     case QEvent::DragEnter:
1332         d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
1333         break;
1334     case QEvent::DragLeave:
1335         d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
1336         break;
1337     case QEvent::DragMove:
1338         d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
1339         break;
1340     case QEvent::Drop:
1341         d->dropEvent(static_cast<QDropEvent*>(ev));
1342         break;
1343 #endif
1344     default:
1345         return QObject::event(ev);
1346     }
1347
1348     return true;
1349 }
1350
1351 /*!
1352     Similar to QWidget::focusNextPrevChild it focuses the next focusable web element
1353     if \a next is true. Otherwise the previous element is focused.
1354 */
1355 bool QWebPage::focusNextPrevChild(bool next)
1356 {
1357     QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
1358     d->keyPressEvent(&ev);
1359     bool hasFocusedNode = false;
1360     Frame *frame = d->page->focusController()->focusedFrame();
1361     if (frame) {
1362         Document *document = frame->document();
1363         hasFocusedNode = document && document->focusedNode();
1364     }
1365     //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
1366     return hasFocusedNode;
1367 }
1368
1369 /*!
1370     Returns a pointe to the page's settings object.
1371 */
1372 QWebSettings *QWebPage::settings()
1373 {
1374     return d->settings;
1375 }
1376
1377 /*!
1378     This function is called when the web content requests a file name, for example
1379     as a result of the user clicking on a "file upload" button in a HTML form.
1380 */
1381 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& oldFile)
1382 {
1383 #ifndef QT_NO_FILEDIALOG
1384     return QFileDialog::getOpenFileName(d->view, QString::null, oldFile);
1385 #else
1386     return QString::null;
1387 #endif
1388 }
1389
1390 #if QT_VERSION < 0x040400
1391
1392 void QWebPage::setNetworkInterface(QWebNetworkInterface *interface)
1393 {
1394     d->networkInterface = interface;
1395 }
1396
1397 QWebNetworkInterface *QWebPage::networkInterface() const
1398 {
1399     if (d->networkInterface)
1400         return d->networkInterface;
1401     else
1402         return QWebNetworkInterface::defaultInterface();
1403 }
1404
1405 #ifndef QT_NO_NETWORKPROXY
1406 void QWebPage::setNetworkProxy(const QNetworkProxy& proxy)
1407 {
1408     d->networkProxy = proxy;
1409 }
1410
1411 QNetworkProxy QWebPage::networkProxy() const
1412 {
1413     return d->networkProxy;
1414 }
1415 #endif
1416
1417 #else
1418
1419 /*!
1420     Sets the QNetworkAccessManager \a manager that is responsible for serving network
1421     requests for this QWebPage.
1422
1423     \sa networkAccessManager
1424 */
1425 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
1426 {
1427     if (manager == d->networkManager)
1428         return;
1429     delete d->networkManager;
1430     d->networkManager = manager;
1431 }
1432
1433 /*!
1434     Returns the QNetworkAccessManager \a manager that is responsible for serving network
1435     requests for this QWebPage.
1436
1437     \sa setNetworkAccessManager
1438 */
1439 QNetworkAccessManager *QWebPage::networkAccessManager() const
1440 {
1441     if (!d->networkManager) {
1442         QWebPage *that = const_cast<QWebPage *>(this);
1443         that->d->networkManager = new QNetworkAccessManager(that);
1444     }
1445     return d->networkManager;
1446 }
1447
1448 #endif
1449
1450 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
1451 {
1452     d->pluginFactory = factory;
1453 }
1454
1455 QWebPluginFactory *QWebPage::pluginFactory() const
1456 {
1457     return d->pluginFactory;
1458 }
1459
1460 /*!
1461     This function is called when a user agent for HTTP requests is needed. You can re-implement this
1462     function to dynamically return different user agent's for different urls, based on the \a url parameter.
1463 */
1464 QString QWebPage::userAgentFor(const QUrl& url) const
1465 {
1466     Q_UNUSED(url)
1467     return QLatin1String("Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/523.15 (KHTML, like Gecko) Safari/419.3 Qt");
1468 }
1469
1470
1471 void QWebPagePrivate::_q_onLoadProgressChanged(int) {
1472     m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
1473     m_bytesReceived = page->progress()->totalBytesReceived();
1474 }
1475
1476
1477 /*!
1478     Returns the total number of bytes that were received from the network to render the current page,
1479     including extra content such as embedded images.
1480 */
1481 quint64 QWebPage::totalBytes() const {
1482     return d->m_bytesReceived;
1483 }
1484
1485
1486 /*!
1487     Returns the number of bytes that were received from the network to render the current page.
1488 */
1489 quint64 QWebPage::bytesReceived() const {
1490     return d->m_totalBytes;
1491 }
1492
1493 QWebPageContext::QWebPageContext(const WebCore::HitTestResult &hitTest)
1494     : d(new QWebPageContextPrivate)
1495 {
1496     d->pos = hitTest.point();
1497     d->text = hitTest.textContent();
1498     d->linkUrl = hitTest.absoluteLinkURL().string();
1499     d->imageUrl = hitTest.absoluteImageURL().string();
1500     d->innerNonSharedNode = hitTest.innerNonSharedNode();
1501     WebCore::Image *img = hitTest.image();
1502     if (img) {
1503         QPixmap *pix = img->getPixmap();
1504         if (pix)
1505             d->image = *pix;
1506     }
1507     WebCore::Frame *frame = hitTest.targetFrame();
1508     if (frame)
1509         d->targetFrame = frame->view()->qwebframe();
1510 }
1511
1512 QWebPageContext::QWebPageContext()
1513     : d(0)
1514 {
1515 }
1516
1517 QWebPageContext::QWebPageContext(const QWebPageContext &other)
1518     : d(0)
1519 {
1520     if (other.d)
1521         d = new QWebPageContextPrivate(*other.d);
1522 }
1523
1524 QWebPageContext &QWebPageContext::operator=(const QWebPageContext &other)
1525 {
1526     if (this != &other) {
1527         if (other.d) {
1528             if (!d)
1529                 d = new QWebPageContextPrivate;
1530             *d = *other.d;
1531         } else {
1532             delete d;
1533             d = 0;
1534         }
1535     }
1536     return *this;
1537 }
1538
1539 QWebPageContext::~QWebPageContext()
1540 {
1541     delete d;
1542 }
1543
1544 QPoint QWebPageContext::pos() const
1545 {
1546     if (!d)
1547         return QPoint();
1548     return d->pos;
1549 }
1550
1551 QString QWebPageContext::text() const
1552 {
1553     if (!d)
1554         return QString();
1555     return d->text;
1556 }
1557
1558 QUrl QWebPageContext::linkUrl() const
1559 {
1560     if (!d)
1561         return QUrl();
1562     return d->linkUrl;
1563 }
1564
1565 QUrl QWebPageContext::imageUrl() const
1566 {
1567     if (!d)
1568         return QUrl();
1569     return d->linkUrl;
1570 }
1571
1572 QPixmap QWebPageContext::image() const
1573 {
1574     if (!d)
1575         return QPixmap();
1576     return d->image;
1577 }
1578
1579 QWebFrame *QWebPageContext::targetFrame() const
1580 {
1581     if (!d)
1582         return 0;
1583     return d->targetFrame;
1584 }
1585
1586 /*!
1587     \fn void QWebPage::loadProgressChanged(int progress)
1588
1589     This signal is emitted when the global progress status changes.
1590     The current value is provided by \a progress in percent.
1591     It accumulates changes from all the child frames.
1592 */
1593
1594 /*!
1595     \fn void QWebPage::hoveringOverLink(const QString &link, const QString &title, const QString &textContent)
1596
1597     This signal is emitted when the mouse is hovering over a link.
1598     The first parameter is the \a link url, the second is the link \a title
1599     if any, and third \a textContent is the text content. Method is emitter with both
1600     empty parameters when the mouse isn't hovering over any link element.
1601 */
1602
1603 /*!
1604     \fn void QWebPage::statusBarTextChanged(const QString& text)
1605
1606     This signal is emitted when the statusbar \a text is changed by the page.
1607 */
1608
1609 /*!
1610     \fn void QWebPage::frameCreated(QWebFrame *frame)
1611
1612     This signal is emitted whenever the page creates a new \a frame.
1613 */
1614
1615 /*!
1616     \fn void QWebPage::selectionChanged()
1617
1618     This signal is emitted whenever the selection changes.
1619 */
1620
1621 /*!
1622     \fn void QWebPage::geometryChangeRequest(const QRect& geom)
1623
1624     This signal is emitted whenever the document wants to change the position and size of the
1625     page to \a geom. This can happen for example through JavaScript.
1626 */
1627
1628 /*!
1629     \fn void QWebPage::handleUnsupportedContent(QNetworkReply *reply)
1630
1631     This signals is emitted when webkit cannot handle a link the user navigated to.
1632
1633     At signal emissions time the meta data of the QNetworkReply is available.
1634 */
1635
1636 /*!
1637     \fn void QWebPage::download(const QNetworkRequest &request)
1638
1639     This signals is emitted when the user decides to download a link.
1640 */
1641
1642 #include "moc_qwebpage.cpp"