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