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