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