47944fa7638e2727e0e8d2fc5e429696c61aa3fc
[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 "qwebview.h"
27 #include "qwebframe.h"
28 #include "qwebpage_p.h"
29 #include "qwebframe_p.h"
30 #include "qwebhistory.h"
31 #include "qwebhistory_p.h"
32 #include "qwebsettings.h"
33
34 #include "Frame.h"
35 #include "FrameTree.h"
36 #include "FrameLoaderClientQt.h"
37 #include "FrameView.h"
38 #include "ChromeClientQt.h"
39 #include "ContextMenu.h"
40 #include "ContextMenuClientQt.h"
41 #include "DocumentLoader.h"
42 #include "DragClientQt.h"
43 #include "DragController.h"
44 #include "DragData.h"
45 #include "EditorClientQt.h"
46 #include "Settings.h"
47 #include "Page.h"
48 #include "Pasteboard.h"
49 #include "FrameLoader.h"
50 #include "FrameLoadRequest.h"
51 #include "KURL.h"
52 #include "Image.h"
53 #include "InspectorClientQt.h"
54 #include "InspectorController.h"
55 #include "FocusController.h"
56 #include "Editor.h"
57 #include "PlatformScrollBar.h"
58 #include "PlatformKeyboardEvent.h"
59 #include "PlatformWheelEvent.h"
60 #include "ProgressTracker.h"
61 #include "RefPtr.h"
62 #include "HashMap.h"
63 #include "HitTestResult.h"
64 #include "WindowFeatures.h"
65 #include "LocalizedStrings.h"
66
67 #include <QApplication>
68 #include <QDebug>
69 #include <QDragEnterEvent>
70 #include <QDragLeaveEvent>
71 #include <QDragMoveEvent>
72 #include <QDropEvent>
73 #include <QFileDialog>
74 #include <QHttpRequestHeader>
75 #include <QInputDialog>
76 #include <QMessageBox>
77 #include <QNetworkProxy>
78 #include <QUndoStack>
79 #include <QUrl>
80 #include <QPainter>
81 #include <QClipboard>
82 #include <QSslSocket>
83 #include <QSysInfo>
84 #if QT_VERSION >= 0x040400
85 #include <QNetworkAccessManager>
86 #include <QNetworkRequest>
87 #else
88 #include "qwebnetworkinterface.h"
89 #endif
90
91 using namespace WebCore;
92
93 // If you change this make sure to also adjust the docs for QWebPage::userAgentForUrl
94 #define WEBKIT_VERSION "523.15"
95
96 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
97 {
98     unsigned result = 0;
99     if (actions & Qt::CopyAction)
100         result |= DragOperationCopy;
101     if (actions & Qt::MoveAction)
102         result |= DragOperationMove;
103     if (actions & Qt::LinkAction)
104         result |= DragOperationLink;
105     return (DragOperation)result;
106 }
107
108 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
109 {
110     Qt::DropAction result = Qt::IgnoreAction;
111     if (actions & DragOperationCopy)
112         result = Qt::CopyAction;
113     else if (actions & DragOperationMove)
114         result = Qt::MoveAction;
115     else if (actions & DragOperationLink)
116         result = Qt::LinkAction;
117     return result;
118 }
119
120 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
121     : q(qq)
122     , view(0)
123     , modified(false)
124     , viewportSize(QSize(0,0))
125 {
126     chromeClient = new ChromeClientQt(q);
127     contextMenuClient = new ContextMenuClientQt();
128     editorClient = new EditorClientQt(q);
129     page = new Page(chromeClient, contextMenuClient, editorClient,
130                     new DragClientQt(q), new InspectorClientQt(q));
131
132     // ### should be configurable
133     page->settings()->setDefaultTextEncodingName("iso-8859-1");
134
135     settings = new QWebSettings(page->settings());
136
137     undoStack = 0;
138     mainFrame = 0;
139 #if QT_VERSION < 0x040400
140     networkInterface = 0;
141     pluginFactory = 0;
142 #else
143     networkManager = 0;
144     pluginFactory = 0;
145 #endif
146     insideOpenCall = false;
147     forwardUnsupportedContent = false;
148     linkPolicy = QWebPage::DontDelegateLinks;
149     currentContextMenu = 0;
150
151     history.d = new QWebHistoryPrivate(page->backForwardList());
152     memset(actions, 0, sizeof(actions));
153 }
154
155 QWebPagePrivate::~QWebPagePrivate()
156 {
157     delete currentContextMenu;
158     delete undoStack;
159     delete settings;
160     delete page;
161 }
162
163 #if QT_VERSION < 0x040400
164 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
165 {
166     if (insideOpenCall
167         && frame == mainFrame)
168         return true;
169     return q->acceptNavigationRequest(frame, request, type);
170 }
171 #else
172 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
173 {
174     if (insideOpenCall
175         && frame == mainFrame)
176         return true;
177     return q->acceptNavigationRequest(frame, request, type);
178 }
179 #endif
180
181 void QWebPagePrivate::createMainFrame()
182 {
183     if (!mainFrame) {
184         QWebFrameData frameData;
185         frameData.ownerElement = 0;
186         frameData.allowsScrolling = true;
187         frameData.marginWidth = 0;
188         frameData.marginHeight = 0;
189         mainFrame = new QWebFrame(q, &frameData);
190
191         emit q->frameCreated(mainFrame);
192     }
193 }
194
195 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
196 {
197     switch (action) {
198         case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
199         case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
200         case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
201         case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
202         case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
203         case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
204         case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
205         case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
206         case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
207         case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
208         case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
209         case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
210         case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
211         case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
212         case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
213         case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
214         case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
215         case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
216         case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
217         case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
218         case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
219         case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
220         default: break;
221     }
222     return QWebPage::NoWebAction;
223 }
224
225 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu, const QList<WebCore::ContextMenuItem> *items)
226 {
227     QMenu *menu = new QMenu;
228     for (int i = 0; i < items->count(); ++i) {
229         const ContextMenuItem &item = items->at(i);
230         switch (item.type()) {
231             case WebCore::CheckableActionType: /* fall through */
232             case WebCore::ActionType: {
233                 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
234                 QAction *a = q->action(action);
235                 if (a) {
236                     ContextMenuItem it(item);
237                     webcoreMenu->checkOrEnableIfNeeded(it);
238                     PlatformMenuItemDescription desc = it.releasePlatformDescription();
239                     a->setEnabled(desc.enabled);
240                     a->setChecked(desc.checked);
241                     a->setCheckable(item.type() == WebCore::CheckableActionType);
242
243                     menu->addAction(a);
244                 }
245                 break;
246             }
247             case WebCore::SeparatorType:
248                 menu->addSeparator();
249                 break;
250             case WebCore::SubmenuType: {
251                 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu());
252
253                 bool anyEnabledAction = false;
254
255                 QList<QAction *> actions = subMenu->actions();
256                 for (int i = 0; i < actions.count(); ++i) {
257                     if (actions.at(i)->isVisible())
258                         anyEnabledAction |= actions.at(i)->isEnabled();
259                 }
260
261                 // don't show sub-menus with just disabled actions
262                 if (anyEnabledAction) {
263                     subMenu->setTitle(item.title());
264                     menu->addAction(subMenu->menuAction());
265                 } else {
266                     delete subMenu;
267                 }
268                 break;
269             }
270         }
271     }
272     return menu;
273 }
274
275 QWebFrame *QWebPagePrivate::frameAt(const QPoint &pos) const
276 {
277     QWebFrame *frame = mainFrame;
278
279 redo:
280     QList<QWebFrame*> children = frame->childFrames();
281     for (int i = 0; i < children.size(); ++i) {
282         if (children.at(i)->geometry().contains(pos)) {
283             frame = children.at(i);
284             goto redo;
285         }
286     }
287     if (frame->geometry().contains(pos))
288         return frame;
289     return 0;
290 }
291
292 void QWebPagePrivate::_q_webActionTriggered(bool checked)
293 {
294     QAction *a = qobject_cast<QAction *>(q->sender());
295     if (!a)
296         return;
297     QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
298     q->triggerAction(action, checked);
299 }
300
301 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
302 {
303     QAction *a = actions[action];
304     if (!a || !mainFrame)
305         return;
306
307     WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
308     WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
309
310     bool enabled = a->isEnabled();
311
312     switch (action) {
313         case QWebPage::Back:
314             enabled = loader->canGoBackOrForward(-1);
315             break;
316         case QWebPage::Forward:
317             enabled = loader->canGoBackOrForward(1);
318             break;
319         case QWebPage::Stop:
320             enabled = loader->isLoading();
321             break;
322         case QWebPage::Reload:
323             enabled = !loader->isLoading();
324             break;
325         case QWebPage::Cut:
326             enabled = editor->canCut();
327             break;
328         case QWebPage::Copy:
329             enabled = editor->canCopy();
330             break;
331         case QWebPage::Paste:
332             enabled = editor->canPaste();
333             break;
334         case QWebPage::Undo:
335         case QWebPage::Redo:
336             // those two are handled by QUndoStack
337             break;
338         default: break;
339     }
340
341     a->setEnabled(enabled);
342 }
343
344 void QWebPagePrivate::updateNavigationActions()
345 {
346     updateAction(QWebPage::Back);
347     updateAction(QWebPage::Forward);
348     updateAction(QWebPage::Stop);
349     updateAction(QWebPage::Reload);
350 }
351
352 void QWebPagePrivate::updateEditorActions()
353 {
354     updateAction(QWebPage::Cut);
355     updateAction(QWebPage::Copy);
356     updateAction(QWebPage::Paste);
357 }
358
359 void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev)
360 {
361     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
362     if (!frame->view())
363         return;
364
365     frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
366 }
367
368 void QWebPagePrivate::mousePressEvent(QMouseEvent *ev)
369 {
370     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
371     if (!frame->view())
372         return;
373
374     frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 1));
375 }
376
377 void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev)
378 {
379     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
380     if (!frame->view())
381         return;
382
383     frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 2));
384 }
385
386 void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev)
387 {
388     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
389     if (!frame->view())
390         return;
391
392     frame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(ev, 0));
393
394 #ifndef QT_NO_CLIPBOARD
395     if (QApplication::clipboard()->supportsSelection()) {
396         bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
397         Pasteboard::generalPasteboard()->setSelectionMode(true);
398         WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
399         if (ev->button() == Qt::LeftButton) {
400             if(focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
401                 focusFrame->editor()->copy();
402             }
403         } else if (ev->button() == Qt::MidButton) {
404             if(focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
405                 focusFrame->editor()->paste();
406             }
407         }
408         Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
409     }
410 #endif
411 }
412
413 void QWebPagePrivate::contextMenuEvent(QContextMenuEvent *ev)
414 {
415     if (currentContextMenu) {
416         currentContextMenu->exec(ev->globalPos());
417         delete currentContextMenu;
418         currentContextMenu = 0;
419     }
420 }
421
422 void QWebPagePrivate::wheelEvent(QWheelEvent *ev)
423 {
424     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
425     if (!frame->view())
426         return;
427
428     WebCore::PlatformWheelEvent pev(ev);
429     bool accepted = frame->eventHandler()->handleWheelEvent(pev);
430     ev->setAccepted(accepted);
431 }
432
433 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
434 {
435     bool handled = false;
436     WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
437     WebCore::Editor *editor = frame->editor();
438     if (editor->canEdit()) {
439         if (ev == QKeySequence::Cut) {
440             q->triggerAction(QWebPage::Cut);
441             handled = true;
442         } else if (ev == QKeySequence::Copy) {
443             q->triggerAction(QWebPage::Copy);
444             handled = true;
445         } else if (ev == QKeySequence::Paste) {
446             q->triggerAction(QWebPage::Paste);
447             handled = true;
448         } else if (ev == QKeySequence::Undo) {
449             q->triggerAction(QWebPage::Undo);
450             handled = true;
451         } else if (ev == QKeySequence::Redo) {
452             q->triggerAction(QWebPage::Redo);
453             handled = true;
454         } else if(ev == QKeySequence::MoveToNextChar) {
455             q->triggerAction(QWebPage::MoveToNextChar);
456             handled = true;
457         } else if(ev == QKeySequence::MoveToPreviousChar) {
458             q->triggerAction(QWebPage::MoveToPreviousChar);
459             handled = true;
460         } else if(ev == QKeySequence::MoveToNextWord) {
461             q->triggerAction(QWebPage::MoveToNextWord);
462             handled = true;
463         } else if(ev == QKeySequence::MoveToPreviousWord) {
464             q->triggerAction(QWebPage::MoveToPreviousWord);
465             handled = true;
466         } else if(ev == QKeySequence::MoveToNextLine) {
467             q->triggerAction(QWebPage::MoveToNextLine);
468             handled = true;
469         } else if(ev == QKeySequence::MoveToPreviousLine) {
470             q->triggerAction(QWebPage::MoveToPreviousLine);
471             handled = true;
472 //             } else if(ev == QKeySequence::MoveToNextPage) {
473 //             } else if(ev == QKeySequence::MoveToPreviousPage) {
474         } else if(ev == QKeySequence::MoveToStartOfLine) {
475             q->triggerAction(QWebPage::MoveToStartOfLine);
476             handled = true;
477         } else if(ev == QKeySequence::MoveToEndOfLine) {
478             q->triggerAction(QWebPage::MoveToEndOfLine);
479             handled = true;
480         } else if(ev == QKeySequence::MoveToStartOfBlock) {
481             q->triggerAction(QWebPage::MoveToStartOfBlock);
482             handled = true;
483         } else if(ev == QKeySequence::MoveToEndOfBlock) {
484             q->triggerAction(QWebPage::MoveToEndOfBlock);
485             handled = true;
486         } else if(ev == QKeySequence::MoveToStartOfDocument) {
487             q->triggerAction(QWebPage::MoveToStartOfDocument);
488             handled = true;
489         } else if(ev == QKeySequence::MoveToEndOfDocument) {
490             q->triggerAction(QWebPage::MoveToEndOfDocument);
491             handled = true;
492         } else if(ev == QKeySequence::SelectNextChar) {
493             q->triggerAction(QWebPage::SelectNextChar);
494             handled = true;
495         } else if(ev == QKeySequence::SelectPreviousChar) {
496             q->triggerAction(QWebPage::SelectPreviousChar);
497             handled = true;
498         } else if(ev == QKeySequence::SelectNextWord) {
499             q->triggerAction(QWebPage::SelectNextWord);
500             handled = true;
501         } else if(ev == QKeySequence::SelectPreviousWord) {
502             q->triggerAction(QWebPage::SelectPreviousWord);
503             handled = true;
504         } else if(ev == QKeySequence::SelectNextLine) {
505             q->triggerAction(QWebPage::SelectNextLine);
506             handled = true;
507         } else if(ev == QKeySequence::SelectPreviousLine) {
508             q->triggerAction(QWebPage::SelectPreviousLine);
509             handled = true;
510 //             } else if(ev == QKeySequence::SelectNextPage) {
511 //             } else if(ev == QKeySequence::SelectPreviousPage) {
512         } else if(ev == QKeySequence::SelectStartOfLine) {
513             q->triggerAction(QWebPage::SelectStartOfLine);
514             handled = true;
515         } else if(ev == QKeySequence::SelectEndOfLine) {
516             q->triggerAction(QWebPage::SelectEndOfLine);
517             handled = true;
518         } else if(ev == QKeySequence::SelectStartOfBlock) {
519             q->triggerAction(QWebPage::SelectStartOfBlock);
520             handled = true;
521         } else if(ev == QKeySequence::SelectEndOfBlock) {
522             q->triggerAction(QWebPage::SelectEndOfBlock);
523             handled = true;
524         } else if(ev == QKeySequence::SelectStartOfDocument) {
525             q->triggerAction(QWebPage::SelectStartOfDocument);
526             handled = true;
527         } else if(ev == QKeySequence::SelectEndOfDocument) {
528             q->triggerAction(QWebPage::SelectEndOfDocument);
529             handled = true;
530         } else if(ev == QKeySequence::DeleteStartOfWord) {
531             q->triggerAction(QWebPage::DeleteStartOfWord);
532             handled = true;
533         } else if(ev == QKeySequence::DeleteEndOfWord) {
534             q->triggerAction(QWebPage::DeleteEndOfWord);
535             handled = true;
536 //             } else if(ev == QKeySequence::DeleteEndOfLine) {
537         }
538     }
539     if (!handled)
540         handled = frame->eventHandler()->keyEvent(ev);
541     if (!handled) {
542         handled = true;
543         PlatformScrollbar *h, *v;
544         h = mainFrame->d->horizontalScrollBar();
545         v = mainFrame->d->verticalScrollBar();
546         QFont defaultFont;
547         if (view)
548             defaultFont = view->font();
549         QFontMetrics fm(defaultFont);
550         int fontHeight = fm.height();
551         if (ev == QKeySequence::MoveToNextPage
552             || ev->key() == Qt::Key_Space) {
553             if (v)
554                 v->setValue(v->value() + q->viewportSize().height() - fontHeight);
555         } else if (ev == QKeySequence::MoveToPreviousPage) {
556             if (v)
557                 v->setValue(v->value() - q->viewportSize().height() + fontHeight);
558         } else if (ev->key() == Qt::Key_Up && ev->modifiers() == Qt::ControlModifier) {
559             if (v)
560                 v->setValue(0);
561         } else if (ev->key() == Qt::Key_Down && ev->modifiers() == Qt::ControlModifier) {
562             if (v)
563                 v->setValue(INT_MAX);
564         } else {
565             switch (ev->key()) {
566             case Qt::Key_Up:
567                 if (v)
568                     v->setValue(v->value() - fontHeight);
569                 break;
570             case Qt::Key_Down:
571                 if (v)
572                     v->setValue(v->value() + fontHeight);
573                 break;
574             case Qt::Key_Left:
575                 if (h)
576                     h->setValue(h->value() - fontHeight);
577                 break;
578             case Qt::Key_Right:
579                 if (h)
580                     h->setValue(h->value() + fontHeight);
581                 break;
582             case Qt::Key_Backspace:
583                 if (ev->modifiers() == Qt::ShiftModifier)
584                     q->triggerAction(QWebPage::Forward);
585                 else
586                     q->triggerAction(QWebPage::Back);
587             default:
588                 handled = false;
589                 break;
590             }
591         }
592     }
593
594     ev->setAccepted(handled);
595 }
596
597 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
598 {
599     if (ev->isAutoRepeat()) {
600         ev->setAccepted(true);
601         return;
602     }
603
604     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
605     bool handled = frame->eventHandler()->keyEvent(ev);
606     ev->setAccepted(handled);
607 }
608
609 void QWebPagePrivate::focusInEvent(QFocusEvent *ev)
610 {
611     if (ev->reason() != Qt::PopupFocusReason)
612         page->focusController()->setFocusedFrame(QWebFramePrivate::core(mainFrame));
613 }
614
615 void QWebPagePrivate::focusOutEvent(QFocusEvent *ev)
616 {
617     if (ev->reason() != Qt::PopupFocusReason)
618         page->focusController()->setFocusedFrame(0);
619 }
620
621 void QWebPagePrivate::dragEnterEvent(QDragEnterEvent *ev)
622 {
623 #ifndef QT_NO_DRAGANDDROP
624     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
625                       dropActionToDragOp(ev->possibleActions()));
626     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
627     ev->setDropAction(action);
628     ev->accept();
629 #endif
630 }
631
632 void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent *ev)
633 {
634 #ifndef QT_NO_DRAGANDDROP
635     DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
636     page->dragController()->dragExited(&dragData);
637     ev->accept();
638 #endif
639 }
640
641 void QWebPagePrivate::dragMoveEvent(QDragMoveEvent *ev)
642 {
643 #ifndef QT_NO_DRAGANDDROP
644     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
645                       dropActionToDragOp(ev->possibleActions()));
646     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
647     ev->setDropAction(action);
648     ev->accept();
649 #endif
650 }
651
652 void QWebPagePrivate::dropEvent(QDropEvent *ev)
653 {
654 #ifndef QT_NO_DRAGANDDROP
655     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
656                       dropActionToDragOp(ev->possibleActions()));
657     Qt::DropAction action = dragOpToDropAction(page->dragController()->performDrag(&dragData));
658     ev->accept();
659 #endif
660 }
661
662 /*!
663     \property QWebPage::palette
664     \brief the page's palette
665
666     The background brush of the palette is used to draw the background of the main frame.
667 */
668 void QWebPage::setPalette(const QPalette &pal)
669 {
670     d->palette = pal;
671     if (d->mainFrame)
672         d->mainFrame->d->updateBackground();
673 }
674
675 QPalette QWebPage::palette() const
676 {
677     return d->palette;
678 }
679
680 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
681 {
682     WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
683     WebCore::Editor *editor = frame->editor();
684
685     if (!editor->canEdit()) {
686         ev->ignore();
687         return;
688     }
689
690     if (!ev->preeditString().isEmpty()) {        
691         QString preedit = ev->preeditString();
692         // ### FIXME: use the provided QTextCharFormat (use color at least)
693         Vector<CompositionUnderline> underlines;
694         underlines.append(CompositionUnderline(0, preedit.length(), Color(0,0,0), false));
695         editor->setComposition(preedit, underlines, preedit.length(), 0);
696     } else if (!ev->commitString().isEmpty()) {
697         editor->confirmComposition(ev->commitString());
698     }
699     ev->accept();
700 }
701
702 /*!
703   This method is used by the input method to query a set of properties of the page
704   to be able to support complex input method operations as support for surrounding
705   text and reconversions.
706
707   \a property specifies which property is queried.
708
709   \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
710 */
711 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
712 {
713     switch(property) {
714     case Qt::ImMicroFocus: {
715         Frame *frame = d->page->focusController()->focusedFrame();
716         if (frame) {
717             return QVariant(frame->selectionController()->caretRect());
718         }
719         return QVariant();
720     }
721     case Qt::ImFont: {
722         QWebView *webView = qobject_cast<QWebView *>(d->view);
723         if (webView)
724             return QVariant(webView->font());
725         return QVariant();
726     }
727     case Qt::ImCursorPosition: {
728         Frame *frame = d->page->focusController()->focusedFrame();
729         if (frame) {
730             Selection selection = frame->selectionController()->selection();
731             if (selection.isCaret()) {
732                 return QVariant(selection.start().offset());
733             }
734         }
735         return QVariant();
736     }
737     case Qt::ImSurroundingText: {
738         Frame *frame = d->page->focusController()->focusedFrame();
739         if (frame) {
740             Document *document = frame->document();
741             if (document->focusedNode()) {
742                 return QVariant(document->focusedNode()->nodeValue());
743             }
744         }
745         return QVariant();
746     }
747     case Qt::ImCurrentSelection:
748         return QVariant(selectedText());
749     default:
750         return QVariant();
751     }
752 }
753
754 /*!
755    \enum QWebPage::FindFlag
756
757    This enum describes the options available to QWebPage's findText() function. The options
758    can be OR-ed together from the following list:
759
760    \value FindBackward Searches backwards instead of forwards.
761    \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
762    changes the behaviour to a case sensitive find operation.
763    \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
764    was reached and the text was not found.
765 */
766
767 /*!
768     \enum QWebPage::LinkDelegationPolicy
769
770     This enum defines the delegation policies a webpage can have when activating links and emitting
771     the linkClicked() signal.
772
773     \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
774     \value DelegateExternalLinks When activating links that point to documents not stored on the
775     local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
776     \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
777 */
778
779 /*!
780     \enum QWebPage::NavigationType
781
782     This enum describes the types of navigation available when browsing through hyperlinked
783     documents.
784
785     \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
786     \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
787     \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
788     \value NavigationTypeReload The user activated the reload action.
789     \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
790     \value NavigationTypeOther A navigation to another document using a method not listed above.
791 */
792
793 /*!
794     \enum QWebPage::WebAction
795
796     \value NoWebAction No action is triggered.
797     \value OpenLink Open the current link.
798     \value OpenLinkInNewWindow Open the current link in a new window.
799     \value OpenFrameInNewWindow Replicate the current frame in a new window.
800     \value DownloadLinkToDisk Download the current link to the disk.
801     \value CopyLinkToClipboard Copy the current link to the clipboard.
802     \value OpenImageInNewWindow Open the highlighted image in a new window.
803     \value DownloadImageToDisk Download the highlighted image to the disk.
804     \value CopyImageToClipboard Copy the highlighted image to the clipboard.
805     \value Back Navigate back in the history of navigated links.
806     \value Forward Navigate forward in the history of navigated links.
807     \value Stop Stop loading the current page.
808     \value Reload Reload the current page.
809     \value Cut Cut the content currently selected into the clipboard.
810     \value Copy Copy the content currently selected into the clipboard.
811     \value Paste Paste content from the clipboard.
812     \value Undo Undo the last editing action.
813     \value Redo Redo the last editing action.
814     \value MoveToNextChar Move the cursor to the next character.
815     \value MoveToPreviousChar Move the cursor to the previous character.
816     \value MoveToNextWord Move the cursor to the next word.
817     \value MoveToPreviousWord Move the cursor to the previous word.
818     \value MoveToNextLine Move the cursor to the next line.
819     \value MoveToPreviousLine Move the cursor to the previous line.
820     \value MoveToStartOfLine Move the cursor to the start of the line.
821     \value MoveToEndOfLine Move the cursor to the end of the line.
822     \value MoveToStartOfBlock Move the cursor to the start of the block.
823     \value MoveToEndOfBlock Move the cursor to the end of the block.
824     \value MoveToStartOfDocument Move the cursor to the start of the document.
825     \value MoveToEndOfDocument Move the cursor to the end of the document.
826     \value SelectNextChar Select to the next character.
827     \value SelectPreviousChar Select to the previous character.
828     \value SelectNextWord Select to the next word.
829     \value SelectPreviousWord Select to the previous word.
830     \value SelectNextLine Select to the next line.
831     \value SelectPreviousLine Select to the previous line.
832     \value SelectStartOfLine Select to the start of the line.
833     \value SelectEndOfLine Select to the end of the line.
834     \value SelectStartOfBlock Select to the start of the block.
835     \value SelectEndOfBlock Select to the end of the block.
836     \value SelectStartOfDocument Select to the start of the document.
837     \value SelectEndOfDocument Select to the end of the document.
838     \value DeleteStartOfWord Delete to the start of the word.
839     \value DeleteEndOfWord Delete to the end of the word.
840     \value SetTextDirectionDefault Set the text direction to the default direction.
841     \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
842     \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
843     \value ToggleBold Toggle the formatting between bold and normal weight.
844     \value ToggleItalic Toggle the formatting between italic and normal style.
845     \value ToggleUnderline Toggle underlining.
846     \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
847     \omitvalue WebActionCount
848
849 */
850
851 /*!
852     \enum QWebPage::WebWindowType
853
854     \value WebBrowserWindow The window is a regular web browser window.
855     \value WebModalDialog The window acts as modal dialog.
856 */
857
858 /*!
859     \class QWebPage
860     \since 4.4
861     \brief The QWebPage class provides a widget that is used to view and edit web documents.
862
863     QWebPage holds a main frame responsible for web content, settings, the history
864     of navigated links as well as actions. This class can be used, together with QWebFrame,
865     if you want to provide functionality like QWebView in a setup without widgets.
866 */
867
868 /*!
869     Constructs an empty QWebView with parent \a parent.
870 */
871 QWebPage::QWebPage(QObject *parent)
872     : QObject(parent)
873     , d(new QWebPagePrivate(this))
874 {
875     setView(qobject_cast<QWidget *>(parent));
876
877     connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
878 }
879
880 /*!
881     Destructor.
882 */
883 QWebPage::~QWebPage()
884 {
885     FrameLoader *loader = d->mainFrame->d->frame->loader();
886     if (loader)
887         loader->detachFromParent();
888     delete d;
889 }
890
891 /*!
892     Returns the main frame of the page.
893
894     The main frame provides access to the hierarchy of sub-frames and is also needed if you
895     want to explicitly render a web page into a given painter.
896 */
897 QWebFrame *QWebPage::mainFrame() const
898 {
899     d->createMainFrame();
900     return d->mainFrame;
901 }
902
903 /*!
904     Returns the frame currently active.
905 */
906 QWebFrame *QWebPage::currentFrame() const
907 {
908     return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame();
909 }
910
911 /*!
912     Returns a pointer to the view's history of navigated web pages.
913
914 */
915 QWebHistory *QWebPage::history() const
916 {
917     return &d->history;
918 }
919
920 /*!
921     Sets the \a view that is associated with the web page.
922
923     \sa view()
924 */
925 void QWebPage::setView(QWidget *view)
926 {
927     d->view = view;
928     setViewportSize(view ? view->size() : QSize(0, 0));
929 }
930
931 /*!
932     Returns the view widget that is associated with the web page.
933
934     \sa setView()
935 */
936 QWidget *QWebPage::view() const
937 {
938     return d->view;
939 }
940
941
942 /*!
943     This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
944
945     For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
946
947     The default implementation prints nothing.
948 */
949 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
950 {
951     Q_UNUSED(message)
952     Q_UNUSED(lineNumber)
953     Q_UNUSED(sourceID)
954 }
955
956 /*!
957     This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
958     the message \a msg.
959
960     The default implementation shows the message, \a msg, with QMessageBox::information.
961 */
962 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
963 {
964     QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Ok);
965 }
966
967 /*!
968     This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
969     with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
970
971     The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
972 */
973 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
974 {
975     return 0 == QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Yes, QMessageBox::No);
976 }
977
978 /*!
979     This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
980     The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
981
982     If the prompt was cancelled by the user the implementation should return false; otherwise the
983     result should be written to \a result and true should be returned.
984
985     The default implementation uses QInputDialog::getText.
986 */
987 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
988 {
989     bool ok = false;
990 #ifndef QT_NO_INPUTDIALOG
991     QString x = QInputDialog::getText(d->view, mainFrame()->title(), msg, QLineEdit::Normal, defaultValue, &ok);
992     if (ok && result) {
993         *result = x;
994     }
995 #endif
996     return ok;
997 }
998
999 /*!
1000     This function is called whenever WebKit wants to create a new window of the given \a type, for
1001     example when a JavaScript program requests to open a document in a new window.
1002
1003     If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
1004
1005     If the view associated with the web page is a QWebView object, then the default implementation forwards
1006     the request to QWebView's createWindow() function; otherwise it returns a null pointer.
1007 */
1008 QWebPage *QWebPage::createWindow(WebWindowType type)
1009 {
1010     QWebView *webView = qobject_cast<QWebView *>(d->view);
1011     if (webView) {
1012         QWebView *newView = webView->createWindow(type);
1013         if (newView)
1014             return newView->page();
1015     }
1016     return 0;
1017 }
1018
1019 /*!
1020     This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin".
1021     The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and
1022     child elements to configure the embeddable object.
1023 */
1024 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
1025 {
1026     Q_UNUSED(classid)
1027     Q_UNUSED(url)
1028     Q_UNUSED(paramNames)
1029     Q_UNUSED(paramValues)
1030     return 0;
1031 }
1032
1033 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
1034 {
1035     WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer());
1036     return WebCore::FrameLoadRequest(rr);
1037 }
1038
1039 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
1040 {
1041     if (Page* oldPage = frame->page()) {
1042         WindowFeatures features;
1043         if (Page* newPage = oldPage->chrome()->createWindow(frame,
1044                 frameLoadRequest(url, frame), features))
1045             newPage->chrome()->show();
1046     }
1047 }
1048
1049 /*!
1050     This function can be called to trigger the specified \a action.
1051     It is also called by QtWebKit if the user triggers the action, for example
1052     through a context menu item.
1053
1054     If \a action is a checkable action then \a checked specified whether the action
1055     is toggled or not.
1056 */
1057 void QWebPage::triggerAction(WebAction action, bool checked)
1058 {
1059     WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
1060     if (!frame)
1061         return;
1062     WebCore::Editor *editor = frame->editor();
1063     const char *command = 0;
1064
1065     switch (action) {
1066         case OpenLink:
1067             if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
1068                 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
1069                 targetFrame->d->frame->loader()->load(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
1070                                                       /*lockHistory*/ false,
1071                                                       /*userGesture*/ true,
1072                                                       /*event*/ 0,
1073                                                       /*HTMLFormElement*/ 0,
1074                                                       /*formValues*/
1075                                                       WTF::HashMap<String, String>());
1076                 break;
1077             }
1078             // fall through
1079         case OpenLinkInNewWindow:
1080             openNewWindow(d->hitTestResult.linkUrl(), frame);
1081             break;
1082         case OpenFrameInNewWindow: {
1083             KURL url = frame->loader()->documentLoader()->unreachableURL();
1084             if (url.isEmpty())
1085                 url = frame->loader()->documentLoader()->url();
1086             openNewWindow(url, frame);
1087             break;
1088         }
1089         case CopyLinkToClipboard:
1090             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
1091             break;
1092         case OpenImageInNewWindow:
1093             openNewWindow(d->hitTestResult.imageUrl(), frame);
1094             break;
1095         case DownloadImageToDisk:
1096         case DownloadLinkToDisk:
1097             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
1098             break;
1099         case CopyImageToClipboard:
1100             QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
1101             break;
1102         case Back:
1103             d->page->goBack();
1104             break;
1105         case Forward:
1106             d->page->goForward();
1107             break;
1108         case Stop:
1109             mainFrame()->d->frame->loader()->stopForUserCancel();
1110             break;
1111         case Reload:
1112             mainFrame()->d->frame->loader()->reload();
1113             break;
1114         case Cut:
1115             command = "Cut";
1116             break;
1117         case Copy:
1118             command = "Copy";
1119             break;
1120         case Paste:
1121             command = "Paste";
1122             break;
1123
1124         case Undo:
1125             command = "Undo";
1126             break;
1127         case Redo:
1128             command = "Redo";
1129             break;
1130
1131         case MoveToNextChar:
1132             command = "MoveForward";
1133             break;
1134         case MoveToPreviousChar:
1135             command = "MoveBackward";
1136             break;
1137         case MoveToNextWord:
1138             command = "MoveWordForward";
1139             break;
1140         case MoveToPreviousWord:
1141             command = "MoveWordBackward";
1142             break;
1143         case MoveToNextLine:
1144             command = "MoveDown";
1145             break;
1146         case MoveToPreviousLine:
1147             command = "MoveUp";
1148             break;
1149         case MoveToStartOfLine:
1150             command = "MoveToBeginningOfLine";
1151             break;
1152         case MoveToEndOfLine:
1153             command = "MoveToEndOfLine";
1154             break;
1155         case MoveToStartOfBlock:
1156             command = "MoveToBeginningOfParagraph";
1157             break;
1158         case MoveToEndOfBlock:
1159             command = "MoveToEndOfParagraph";
1160             break;
1161         case MoveToStartOfDocument:
1162             command = "MoveToBeginningOfDocument";
1163             break;
1164         case MoveToEndOfDocument:
1165             command = "MoveToEndOfDocument";
1166             break;
1167         case SelectNextChar:
1168             command = "MoveForwardAndModifySelection";
1169             break;
1170         case SelectPreviousChar:
1171             command = "MoveBackwardAndModifySelection";
1172             break;
1173         case SelectNextWord:
1174             command = "MoveWordForwardAndModifySelection";
1175             break;
1176         case SelectPreviousWord:
1177             command = "MoveWordBackwardAndModifySelection";
1178             break;
1179         case SelectNextLine:
1180             command = "MoveDownAndModifySelection";
1181             break;
1182         case SelectPreviousLine:
1183             command = "MoveUpAndModifySelection";
1184             break;
1185         case SelectStartOfLine:
1186             command = "MoveToBeginningOfLineAndModifySelection";
1187             break;
1188         case SelectEndOfLine:
1189             command = "MoveToEndOfLineAndModifySelection";
1190             break;
1191         case SelectStartOfBlock:
1192             command = "MoveToBeginningOfParagraphAndModifySelection";
1193             break;
1194         case SelectEndOfBlock:
1195             command = "MoveToEndOfParagraphAndModifySelection";
1196             break;
1197         case SelectStartOfDocument:
1198             command = "MoveToBeginningOfDocumentAndModifySelection";
1199             break;
1200         case SelectEndOfDocument:
1201             command = "MoveToEndOfDocumentAndModifySelection";
1202             break;
1203         case DeleteStartOfWord:
1204             command = "DeleteWordBackward";
1205             break;
1206         case DeleteEndOfWord:
1207             command = "DeleteWordForward";
1208             break;
1209
1210         case SetTextDirectionDefault:
1211             editor->setBaseWritingDirection("inherit");
1212             break;
1213         case SetTextDirectionLeftToRight:
1214             editor->setBaseWritingDirection("ltr");
1215             break;
1216         case SetTextDirectionRightToLeft:
1217             editor->setBaseWritingDirection("rtl");
1218             break;
1219
1220         case ToggleBold:
1221             command = "ToggleBold";
1222             break;
1223         case ToggleItalic:
1224             command = "ToggleItalic";
1225             break;
1226         case ToggleUnderline:
1227             editor->toggleUnderline();
1228             break;
1229
1230         case InspectElement:
1231             d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
1232             break;
1233
1234         default: break;
1235     }
1236
1237     if (command)
1238         editor->command(command).execute();
1239 }
1240
1241 QSize QWebPage::viewportSize() const
1242 {
1243     if (d->mainFrame && d->mainFrame->d->frame->view())
1244         return d->mainFrame->d->frame->view()->frameGeometry().size();
1245
1246     return d->viewportSize;
1247 }
1248
1249 /*!
1250     \property QWebPage::viewportSize
1251     \brief the size of the viewport
1252
1253     The size affects for example the visibility of scrollbars
1254     if the document is larger than the viewport.
1255 */
1256 void QWebPage::setViewportSize(const QSize &size) const
1257 {
1258     d->viewportSize = size;
1259
1260     QWebFrame *frame = mainFrame();
1261     if (frame->d->frame && frame->d->frame->view()) {
1262         WebCore::FrameView* view = frame->d->frame->view();
1263         view->setFrameGeometry(QRect(QPoint(0, 0), size));
1264         frame->d->frame->forceLayout();
1265         view->adjustViewSize();
1266     }
1267 }
1268
1269
1270 /*!
1271     \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
1272
1273     This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
1274     the specified navigation type \a type.
1275
1276     The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
1277     to let QWebPage handle the navigation itself.
1278 */
1279 #if QT_VERSION < 0x040400
1280 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type)
1281 #else
1282 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
1283 #endif
1284 {
1285     if (type == NavigationTypeLinkClicked) {
1286         switch (d->linkPolicy) {
1287             case DontDelegateLinks:
1288                 return true;
1289
1290             case DelegateExternalLinks:
1291                 if (WebCore::FrameLoader::shouldTreatSchemeAsLocal(request.url().scheme()))
1292                     return true;
1293                 emit linkClicked(request.url());
1294                 return false;
1295
1296             case DelegateAllLinks:
1297                 emit linkClicked(request.url());
1298                 return false;
1299         }
1300     }
1301     return true;
1302 }
1303
1304 /*!
1305     \property QWebPage::selectedText
1306     \brief the text currently selected
1307 */
1308 QString QWebPage::selectedText() const
1309 {
1310     return d->page->focusController()->focusedOrMainFrame()->selectedText();
1311 }
1312
1313 /*!
1314    Returns a QAction for the specified WebAction \a action.
1315
1316    The action is owned by the QWebPage but you can customize the look by
1317    changing its properties.
1318
1319    QWebPage also takes care of implementing the action, so that upon
1320    triggering the corresponding action is performed on the page.
1321 */
1322 QAction *QWebPage::action(WebAction action) const
1323 {
1324     if (action == QWebPage::NoWebAction) return 0;
1325     if (d->actions[action])
1326         return d->actions[action];
1327
1328     QString text;
1329     QIcon icon;
1330     QStyle *style = view() ? view()->style() : qApp->style();
1331     bool checkable = false;
1332
1333     switch (action) {
1334         case OpenLink:
1335             text = contextMenuItemTagOpenLink();
1336             break;
1337         case OpenLinkInNewWindow:
1338             text = contextMenuItemTagOpenLinkInNewWindow();
1339             break;
1340         case OpenFrameInNewWindow:
1341             text = contextMenuItemTagOpenFrameInNewWindow();
1342             break;
1343
1344         case DownloadLinkToDisk:
1345             text = contextMenuItemTagDownloadLinkToDisk();
1346             break;
1347         case CopyLinkToClipboard:
1348             text = contextMenuItemTagCopyLinkToClipboard();
1349             break;
1350
1351         case OpenImageInNewWindow:
1352             text = contextMenuItemTagOpenImageInNewWindow();
1353             break;
1354         case DownloadImageToDisk:
1355             text = contextMenuItemTagDownloadImageToDisk();
1356             break;
1357         case CopyImageToClipboard:
1358             text = contextMenuItemTagCopyImageToClipboard();
1359             break;
1360
1361         case Back:
1362             text = contextMenuItemTagGoBack();
1363 #if QT_VERSION >= 0x040400
1364             icon = style->standardIcon(QStyle::SP_ArrowBack);
1365 #endif
1366             break;
1367         case Forward:
1368             text = contextMenuItemTagGoForward();
1369 #if QT_VERSION >= 0x040400
1370             icon = style->standardIcon(QStyle::SP_ArrowForward);
1371 #endif
1372             break;
1373         case Stop:
1374             text = contextMenuItemTagStop();
1375 #if QT_VERSION >= 0x040400
1376             icon = style->standardIcon(QStyle::SP_BrowserStop);
1377 #endif
1378             break;
1379         case Reload:
1380             text = contextMenuItemTagReload();
1381 #if QT_VERSION >= 0x040400
1382             icon = style->standardIcon(QStyle::SP_BrowserReload);
1383 #endif
1384             break;
1385
1386         case Cut:
1387             text = contextMenuItemTagCut();
1388             break;
1389         case Copy:
1390             text = contextMenuItemTagCopy();
1391             break;
1392         case Paste:
1393             text = contextMenuItemTagPaste();
1394             break;
1395
1396         case Undo: {
1397             QAction *a = undoStack()->createUndoAction(d->q);
1398             d->actions[action] = a;
1399             return a;
1400         }
1401         case Redo: {
1402             QAction *a = undoStack()->createRedoAction(d->q);
1403             d->actions[action] = a;
1404             return a;
1405         }
1406         case MoveToNextChar:
1407         case MoveToPreviousChar:
1408         case MoveToNextWord:
1409         case MoveToPreviousWord:
1410         case MoveToNextLine:
1411         case MoveToPreviousLine:
1412         case MoveToStartOfLine:
1413         case MoveToEndOfLine:
1414         case MoveToStartOfBlock:
1415         case MoveToEndOfBlock:
1416         case MoveToStartOfDocument:
1417         case MoveToEndOfDocument:
1418         case SelectNextChar:
1419         case SelectPreviousChar:
1420         case SelectNextWord:
1421         case SelectPreviousWord:
1422         case SelectNextLine:
1423         case SelectPreviousLine:
1424         case SelectStartOfLine:
1425         case SelectEndOfLine:
1426         case SelectStartOfBlock:
1427         case SelectEndOfBlock:
1428         case SelectStartOfDocument:
1429         case SelectEndOfDocument:
1430         case DeleteStartOfWord:
1431         case DeleteEndOfWord:
1432             break; // ####
1433
1434         case SetTextDirectionDefault:
1435             text = contextMenuItemTagDefaultDirection();
1436             break;
1437         case SetTextDirectionLeftToRight:
1438             text = contextMenuItemTagLeftToRight();
1439             checkable = true;
1440             break;
1441         case SetTextDirectionRightToLeft:
1442             text = contextMenuItemTagRightToLeft();
1443             checkable = true;
1444             break;
1445
1446         case ToggleBold:
1447             text = contextMenuItemTagBold();
1448             checkable = true;
1449             break;
1450         case ToggleItalic:
1451             text = contextMenuItemTagItalic();
1452             checkable = true;
1453             break;
1454         case ToggleUnderline:
1455             text = contextMenuItemTagUnderline();
1456             checkable = true;
1457             break;
1458
1459         case InspectElement:
1460             text = contextMenuItemTagInspectElement();
1461             break;
1462
1463         case NoWebAction:
1464             return 0;
1465     }
1466
1467     if (text.isEmpty())
1468         return 0;
1469
1470     QAction *a = new QAction(d->q);
1471     a->setText(text);
1472     a->setData(action);
1473     a->setCheckable(checkable);
1474     a->setIcon(icon);
1475
1476     connect(a, SIGNAL(triggered(bool)),
1477             this, SLOT(_q_webActionTriggered(bool)));
1478
1479     d->actions[action] = a;
1480     d->updateAction(action);
1481     return a;
1482 }
1483
1484 /*!
1485     \property QWebPage::modified
1486     \brief whether the page contains unsubmitted form data
1487 */
1488 bool QWebPage::isModified() const
1489 {
1490     return d->modified;
1491 }
1492
1493
1494 /*!
1495     Returns a pointer to the undo stack used for editable content.
1496 */
1497 QUndoStack *QWebPage::undoStack() const
1498 {
1499     if (!d->undoStack)
1500         d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
1501
1502     return d->undoStack;
1503 }
1504
1505 /*! \reimp
1506 */
1507 bool QWebPage::event(QEvent *ev)
1508 {
1509     switch (ev->type()) {
1510     case QEvent::MouseMove:
1511         d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
1512         break;
1513     case QEvent::MouseButtonPress:
1514         d->mousePressEvent(static_cast<QMouseEvent*>(ev));
1515         break;
1516     case QEvent::MouseButtonDblClick:
1517         d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
1518         break;
1519     case QEvent::MouseButtonRelease:
1520         d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
1521         break;
1522     case QEvent::ContextMenu:
1523         d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev));
1524         break;
1525     case QEvent::Wheel:
1526         d->wheelEvent(static_cast<QWheelEvent*>(ev));
1527         break;
1528     case QEvent::KeyPress:
1529         d->keyPressEvent(static_cast<QKeyEvent*>(ev));
1530         break;
1531     case QEvent::KeyRelease:
1532         d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
1533         break;
1534     case QEvent::FocusIn:
1535         d->focusInEvent(static_cast<QFocusEvent*>(ev));
1536         break;
1537     case QEvent::FocusOut:
1538         d->focusOutEvent(static_cast<QFocusEvent*>(ev));
1539         break;
1540 #ifndef QT_NO_DRAGANDDROP
1541     case QEvent::DragEnter:
1542         d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
1543         break;
1544     case QEvent::DragLeave:
1545         d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
1546         break;
1547     case QEvent::DragMove:
1548         d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
1549         break;
1550     case QEvent::Drop:
1551         d->dropEvent(static_cast<QDropEvent*>(ev));
1552         break;
1553 #endif
1554     case QEvent::InputMethod:
1555         d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
1556     default:
1557         return QObject::event(ev);
1558     }
1559
1560     return true;
1561 }
1562
1563 /*!
1564     Similar to QWidget::focusNextPrevChild it focuses the next focusable web element
1565     if \a next is true; otherwise the previous element is focused.
1566
1567     Returns true if it can find a new focusable element, or false if it can't.
1568 */
1569 bool QWebPage::focusNextPrevChild(bool next)
1570 {
1571     QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
1572     d->keyPressEvent(&ev);
1573     bool hasFocusedNode = false;
1574     Frame *frame = d->page->focusController()->focusedFrame();
1575     if (frame) {
1576         Document *document = frame->document();
1577         hasFocusedNode = document && document->focusedNode();
1578     }
1579     //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
1580     return hasFocusedNode;
1581 }
1582
1583 /*!
1584     \property QWebPage::forwardUnsupportedContent
1585     \brief whether QWebPage should forward unsupported content through the
1586     unsupportedContent signal
1587
1588     If disabled the download of such content is aborted immediately.
1589
1590     By default unsupported content is not forwarded.
1591 */
1592
1593 void QWebPage::setForwardUnsupportedContent(bool forward)
1594 {
1595     d->forwardUnsupportedContent = forward;
1596 }
1597
1598 bool QWebPage::forwardUnsupportedContent() const
1599 {
1600     return d->forwardUnsupportedContent;
1601 }
1602
1603 /*!
1604     \property QWebPage::linkDelegationPolicy
1605     \brief how QWebPage should delegate the handling of links through the
1606     linkClicked() signal
1607
1608     The default is to delegate no links.
1609 */
1610
1611 void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
1612 {
1613     d->linkPolicy = policy;
1614 }
1615
1616 QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
1617 {
1618     return d->linkPolicy;
1619 }
1620
1621 /*!
1622     Passes the context menu event, \a event, to the currently displayed webpage and
1623     returns true if the page handled the event; otherwise false is returned.
1624
1625     A web page may swallow a context menu event through a custom event handler, allowing for context
1626     menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
1627     Maps}, for example.
1628 */
1629 bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
1630 {
1631     d->page->contextMenuController()->clearContextMenu();
1632
1633     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
1634     focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
1635     ContextMenu *menu = d->page->contextMenuController()->contextMenu();
1636     // If the website defines its own handler then sendContextMenuEvent takes care of
1637     // calling/showing it and the context menu pointer will be zero. This is the case
1638     // on maps.google.com for example.
1639     return !menu;
1640 }
1641
1642 /*!
1643     Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
1644     element the CopyImageToClipboard action is enabled.
1645 */
1646 void QWebPage::updatePositionDependentActions(const QPoint &pos)
1647 {
1648     // disable position dependent actions first and enable them if WebCore adds them enabled to the context menu.
1649
1650     for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
1651         QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
1652         QAction *a = this->action(action);
1653         if (a)
1654             a->setEnabled(false);
1655     }
1656
1657     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
1658     HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
1659
1660     d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
1661     WebCore::ContextMenu menu(result);
1662     menu.populate();
1663
1664     delete d->currentContextMenu;
1665     // createContextMenu also enables actions if necessary
1666     d->currentContextMenu = d->createContextMenu(&menu, menu.platformDescription());
1667 }
1668
1669 /*!
1670     \enum QWebPage::Extension
1671
1672     This enum describes the types of extensions that the page can support. Before using these extensions, you
1673     should verify that the extension is supported by calling supportsExtension().
1674
1675     Currently there are no extensions.
1676 */
1677
1678 /*!
1679     \class QWebPage::ExtensionOption
1680     \since 4.4
1681     \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
1682
1683     \sa QWebPage::extension()
1684 */
1685
1686 /*!
1687     \class QWebPage::ExtensionReturn
1688     \since 4.4
1689     \brief The ExtensionOption class provides an extended output argument to QWebPage's extension support.
1690
1691     \sa QWebPage::extension()
1692 */
1693
1694 /*!
1695     This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
1696     argument is provided as input to the extension; the output results can be stored in \a output.
1697
1698     The behavior of this function is determined by \a extension.
1699
1700     You can call supportsExtension() to check if an extension is supported by the page.
1701
1702     By default, no extensions are supported, and this function returns false.
1703
1704     \sa supportsExtension(), Extension
1705 */
1706 bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
1707 {
1708     Q_UNUSED(extension)
1709     Q_UNUSED(option)
1710     Q_UNUSED(output)
1711     return false;
1712 }
1713
1714 /*!
1715     This virtual function returns true if the web page supports \a extension; otherwise false is returned.
1716
1717     \sa extension()
1718 */
1719 bool QWebPage::supportsExtension(Extension extension) const
1720 {
1721     Q_UNUSED(extension)
1722     return false;
1723 }
1724
1725 /*!
1726     Finds the next occurrence of the string, \a subString, in the page, using the given \a options.
1727     Returns true of \a subString was found and selects the match visually; otherwise returns false.
1728 */
1729 bool QWebPage::findText(const QString &subString, FindFlags options)
1730 {
1731     ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
1732     if (options & FindCaseSensitively)
1733         caseSensitivity = ::TextCaseSensitive;
1734
1735     ::FindDirection direction = ::FindDirectionForward;
1736     if (options & FindBackward)
1737         direction = ::FindDirectionBackward;
1738
1739     const bool shouldWrap = options & FindWrapsAroundDocument;
1740
1741     return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
1742 }
1743
1744 /*!
1745     Returns a pointer to the page's settings object.
1746 */
1747 QWebSettings *QWebPage::settings() const
1748 {
1749     return d->settings;
1750 }
1751
1752 /*!
1753     This function is called when the web content requests a file name, for example
1754     as a result of the user clicking on a "file upload" button in a HTML form.
1755
1756     A suggested filename may be provided in \a suggestedFile. The frame originating the
1757     request is provided as \a parentFrame.
1758 */
1759 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
1760 {
1761 #ifndef QT_NO_FILEDIALOG
1762     return QFileDialog::getOpenFileName(d->view, QString::null, suggestedFile);
1763 #else
1764     return QString::null;
1765 #endif
1766 }
1767
1768 #if QT_VERSION < 0x040400 && !defined qdoc
1769
1770 void QWebPage::setNetworkInterface(QWebNetworkInterface *interface)
1771 {
1772     d->networkInterface = interface;
1773 }
1774
1775 QWebNetworkInterface *QWebPage::networkInterface() const
1776 {
1777     if (d->networkInterface)
1778         return d->networkInterface;
1779     else
1780         return QWebNetworkInterface::defaultInterface();
1781 }
1782
1783 #ifndef QT_NO_NETWORKPROXY
1784 void QWebPage::setNetworkProxy(const QNetworkProxy& proxy)
1785 {
1786     d->networkProxy = proxy;
1787 }
1788
1789 QNetworkProxy QWebPage::networkProxy() const
1790 {
1791     return d->networkProxy;
1792 }
1793 #endif
1794
1795 #else
1796
1797 /*!
1798     Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
1799     QWebPage.
1800
1801     \sa networkAccessManager()
1802 */
1803 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
1804 {
1805     if (manager == d->networkManager)
1806         return;
1807     if (d->networkManager && d->networkManager->parent() == this)
1808         delete d->networkManager;
1809     d->networkManager = manager;
1810 }
1811
1812 /*!
1813     Returns the QNetworkAccessManager that is responsible for serving network
1814     requests for this QWebPage.
1815
1816     \sa setNetworkAccessManager()
1817 */
1818 QNetworkAccessManager *QWebPage::networkAccessManager() const
1819 {
1820     if (!d->networkManager) {
1821         QWebPage *that = const_cast<QWebPage *>(this);
1822         that->d->networkManager = new QNetworkAccessManager(that);
1823     }
1824     return d->networkManager;
1825 }
1826
1827 #endif
1828
1829 /*!
1830     Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
1831     QWebPage.
1832
1833     \sa pluginFactory()
1834 */
1835 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
1836 {
1837     d->pluginFactory = factory;
1838 }
1839
1840 /*!
1841     Returns the QWebPluginFactory that is responsible for creating plugins embedded into
1842     this QWebPage. If no plugin factory is installed a null pointer is returned.
1843
1844     \sa setPluginFactory()
1845 */
1846 QWebPluginFactory *QWebPage::pluginFactory() const
1847 {
1848     return d->pluginFactory;
1849 }
1850
1851 /*!
1852     This function is called when a user agent for HTTP requests is needed. You can re-implement this
1853     function to dynamically return different user agent's for different urls, based on the \a url parameter.
1854
1855     The default implementation returns the following value:
1856
1857     "Mozilla/5.0 (%Platform%; %Security%; %Subplatform%; %Locale%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko, Safari/419.3) %AppVersion"
1858
1859     In this string the following values are replaced at run-time:
1860     \list
1861     \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system.
1862     \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true.
1863     \o %Locale% is replaced with QLocale::name().
1864     \o %WebKitVersion% currently expands to 523.15
1865     \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
1866     \endlist
1867 */
1868 QString QWebPage::userAgentForUrl(const QUrl& url) const
1869 {
1870     Q_UNUSED(url)
1871     QString ua = QLatin1String("Mozilla/5.0 ("
1872
1873     // Plastform
1874 #ifdef Q_WS_MAC
1875     "Macintosh"
1876 #elif defined Q_WS_QWS
1877     "QtEmbedded"
1878 #elif defined Q_WS_WIN
1879     "Windows"
1880 #elif defined Q_WS_X11
1881     "X11"
1882 #else
1883     "Unknown"
1884 #endif
1885     "; "
1886
1887     // Placeholder for security strength (N or U)
1888     "%1; "
1889
1890     // Subplatform"
1891 #ifdef Q_OS_AIX
1892     "AIX"
1893 #elif defined Q_OS_WIN32
1894     "%2"
1895 #elif defined Q_OS_DARWIN
1896 #ifdef __i386__ || __x86_64__
1897     "Intel Mac OS X"
1898 #else
1899     "PPC Mac OS X"
1900 #endif
1901
1902 #elif defined Q_OS_BSDI
1903     "BSD"
1904 #elif defined Q_OS_BSD4
1905     "BSD Four"
1906 #elif defined Q_OS_CYGWIN
1907     "Cygwin"
1908 #elif defined Q_OS_DGUX
1909     "DG/UX"
1910 #elif defined Q_OS_DYNIX
1911     "DYNIX/ptx"
1912 #elif defined Q_OS_FREEBSD
1913     "FreeBSD"
1914 #elif defined Q_OS_HPUX
1915     "HP-UX"
1916 #elif defined Q_OS_HURD
1917     "GNU Hurd"
1918 #elif defined Q_OS_IRIX
1919     "SGI Irix"
1920 #elif defined Q_OS_LINUX
1921     "Linux"
1922 #elif defined Q_OS_LYNX
1923     "LynxOS"
1924 #elif defined Q_OS_NETBSD
1925     "NetBSD"
1926 #elif defined Q_OS_OS2
1927     "OS/2"
1928 #elif defined Q_OS_OPENBSD
1929     "OpenBSD"
1930 #elif defined Q_OS_OS2EMX
1931     "OS/2"
1932 #elif defined Q_OS_OSF
1933     "HP Tru64 UNIX"
1934 #elif defined Q_OS_QNX6
1935     "QNX RTP Six"
1936 #elif defined Q_OS_QNX
1937     "QNX"
1938 #elif defined Q_OS_RELIANT
1939     "Reliant UNIX"
1940 #elif defined Q_OS_SCO
1941     "SCO OpenServer"
1942 #elif defined Q_OS_SOLARIS
1943     "Sun Solaris"
1944 #elif defined Q_OS_ULTRIX
1945     "DEC Ultrix"
1946 #elif defined Q_OS_UNIX
1947     "UNIX BSD/SYSV system"
1948 #elif defined Q_OS_UNIXWARE
1949     "UnixWare Seven, Open UNIX Eight"
1950 #else
1951     "Unknown"
1952 #endif
1953     "; ");
1954
1955     QChar securityStrength(QLatin1Char('N'));
1956 #if !defined(QT_NO_OPENSSL)
1957     if (QSslSocket::supportsSsl())
1958         securityStrength = QLatin1Char('U');
1959 #endif
1960     ua = ua.arg(securityStrength);
1961
1962 #if defined Q_OS_WIN32
1963     QString ver;
1964     switch(QSysInfo::WindowsVersion) {
1965         case QSysInfo::WV_32s:
1966             ver = "Windows 3.1";
1967             break;
1968         case QSysInfo::WV_95:
1969             ver = "Windows 95";
1970             break;
1971         case QSysInfo::WV_98:
1972             ver = "Windows 98";
1973             break;
1974         case QSysInfo::WV_Me:
1975             ver = "Windows 98; Win 9x 4.90";
1976             break;
1977         case QSysInfo::WV_NT:
1978             ver = "WinNT4.0";
1979             break;
1980         case QSysInfo::WV_2000:
1981             ver = "Windows NT 5.0";
1982             break;
1983         case QSysInfo::WV_XP:
1984             ver = "Windows NT 5.1";
1985             break;
1986         case QSysInfo::WV_2003:
1987             ver = "Windows NT 5.2";
1988             break;
1989         case QSysInfo::WV_VISTA:
1990             ver = "Windows NT 6.0";
1991             break;
1992         case QSysInfo::WV_CE:
1993             ver = "Windows CE";
1994             break;
1995         case QSysInfo::WV_CENET:
1996             ver = "Windows CE .NET";
1997             break;
1998         case QSysInfo::WV_CE_5:
1999             ver = "Windows CE 5.x";
2000             break;
2001         case QSysInfo::WV_CE_6:
2002             ver = "Windows CE 6.x";
2003             break;
2004     }
2005     ua = QString(ua).arg(ver);
2006 #endif
2007
2008     // Language
2009     QLocale locale;
2010     if (d->view)
2011         locale = d->view->locale();
2012     QString name = locale.name();
2013     name[2] = QLatin1Char('-');
2014     ua.append(name);
2015     ua.append(QLatin1String(") "));
2016
2017     // webkit/qt version
2018     ua.append(QLatin1String("AppleWebKit/" WEBKIT_VERSION " (KHTML, like Gecko, Safari/419.3) "));
2019
2020     // Application name/version
2021     QString appName = QCoreApplication::applicationName();
2022     if (!appName.isEmpty()) {
2023         ua.append(QLatin1Char(' ') + appName);
2024         QString appVer = QCoreApplication::applicationVersion();
2025         if (!appVer.isEmpty())
2026             ua.append(QLatin1Char('/') + appVer);
2027     } else {
2028         // Qt version
2029         ua.append(QLatin1String("Qt/"));
2030         ua.append(QLatin1String(qVersion()));
2031     }
2032     return ua;
2033 }
2034
2035
2036 void QWebPagePrivate::_q_onLoadProgressChanged(int) {
2037     m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
2038     m_bytesReceived = page->progress()->totalBytesReceived();
2039 }
2040
2041
2042 /*!
2043     Returns the total number of bytes that were received from the network to render the current page,
2044     including extra content such as embedded images.
2045 */
2046 quint64 QWebPage::totalBytes() const {
2047     return d->m_bytesReceived;
2048 }
2049
2050
2051 /*!
2052     Returns the number of bytes that were received from the network to render the current page.
2053 */
2054 quint64 QWebPage::bytesReceived() const {
2055     return d->m_totalBytes;
2056 }
2057
2058 /*!
2059     \fn void QWebPage::loadProgress(int progress)
2060
2061     This signal is emitted when the global progress status changes.
2062     The current value is provided by \a progress and scales from 0 to 100,
2063     which is the default range of QProgressBar.
2064     It accumulates changes from all the child frames.
2065 */
2066
2067 /*!
2068     \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
2069
2070     This signal is emitted when the mouse is hovering over a link.
2071     The first parameter is the \a link url, the second is the link \a title
2072     if any, and third \a textContent is the text content. Method is emitter with both
2073     empty parameters when the mouse isn't hovering over any link element.
2074 */
2075
2076 /*!
2077     \fn void QWebPage::statusBarMessage(const QString& text)
2078
2079     This signal is emitted when the statusbar \a text is changed by the page.
2080 */
2081
2082 /*!
2083     \fn void QWebPage::frameCreated(QWebFrame *frame)
2084
2085     This signal is emitted whenever the page creates a new \a frame.
2086 */
2087
2088 /*!
2089     \fn void QWebPage::selectionChanged()
2090
2091     This signal is emitted whenever the selection changes.
2092 */
2093
2094 /*!
2095     \fn void QWebPage::geometryChangeRequested(const QRect& geom)
2096
2097     This signal is emitted whenever the document wants to change the position and size of the
2098     page to \a geom. This can happen for example through JavaScript.
2099 */
2100
2101 /*!
2102     \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
2103
2104     This signal is emitted whenever this QWebPage should be updated and no view was set.
2105     \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
2106     the mainFrame() and call the render(QPainter*, const QRegion&) method with the
2107     \a dirtyRect as the second parameter.
2108
2109     \sa mainFrame()
2110     \sa view()
2111 */
2112
2113 /*!
2114     \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
2115
2116     This signal is emitted whenever the content given by \a rectToScroll needs
2117     to be scrolled \a dx and \a dy downwards and no view was set.
2118
2119     \sa view()
2120 */
2121
2122 /*!
2123     \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
2124
2125     This signals is emitted when webkit cannot handle a link the user navigated to.
2126
2127     At signal emissions time the meta data of the QNetworkReply \a reply is available.
2128
2129     \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
2130 */
2131
2132 /*!
2133     \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
2134
2135     This signal is emitted when the user decides to download a link. The url of
2136     the link as well as additional meta-information is contained in \a request.
2137 */
2138
2139 /*!
2140     \fn void QWebPage::microFocusChanged()
2141
2142     This signal is emitted when for example the position of the cursor in an editable form
2143     element changes. It is used inform input methods about the new on-screen position where
2144     the user is able to enter text. This signal is usually connected to QWidget's updateMicroFocus()
2145     slot.
2146 */
2147
2148 /*!
2149     \fn void QWebPage::linkClicked(const QUrl &url)
2150
2151     This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
2152     property is set to delegate the link handling for the specified \a url.
2153
2154     By default no links are delegated and are handled by QWebPage instead.
2155 */
2156
2157 /*!
2158     \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
2159
2160     This signal is emitted whenever the visibility of the toolbar in a web browser
2161     window that hosts QWebPage should be changed to \a visible.
2162 */
2163
2164 /*!
2165     \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
2166
2167     This signal is emitted whenever the visibility of the statusbar in a web browser
2168     window that hosts QWebPage should be changed to \a visible.
2169 */
2170
2171 /*!
2172     \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
2173
2174     This signal is emitted whenever the visibility of the menubar in a web browser
2175     window that hosts QWebPage should be changed to \a visible.
2176 */
2177
2178 #include "moc_qwebpage.cpp"