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