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