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