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