• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies)
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 
22 #include "config.h"
23 #include "qwebpage.h"
24 #include "qwebview.h"
25 #include "qwebframe.h"
26 #include "qwebpage_p.h"
27 #include "qwebframe_p.h"
28 #include "qwebhistory.h"
29 #include "qwebhistory_p.h"
30 #include "qwebinspector.h"
31 #include "qwebinspector_p.h"
32 #include "qwebsettings.h"
33 #include "qwebkitversion.h"
34 
35 #include "Chrome.h"
36 #include "ContextMenuController.h"
37 #include "Frame.h"
38 #include "FrameTree.h"
39 #include "FrameLoader.h"
40 #include "FrameLoaderClientQt.h"
41 #include "FrameView.h"
42 #include "FormState.h"
43 #include "ApplicationCacheStorage.h"
44 #include "ChromeClientQt.h"
45 #include "ContextMenu.h"
46 #include "ContextMenuClientQt.h"
47 #include "DocumentLoader.h"
48 #include "DragClientQt.h"
49 #include "DragController.h"
50 #include "DragData.h"
51 #include "EditorClientQt.h"
52 #include "SecurityOrigin.h"
53 #include "Settings.h"
54 #include "Page.h"
55 #include "Pasteboard.h"
56 #include "FrameLoader.h"
57 #include "FrameLoadRequest.h"
58 #include "KURL.h"
59 #include "Logging.h"
60 #include "Image.h"
61 #include "InspectorClientQt.h"
62 #include "InspectorController.h"
63 #include "FocusController.h"
64 #include "Editor.h"
65 #include "Scrollbar.h"
66 #include "PlatformKeyboardEvent.h"
67 #include "PlatformWheelEvent.h"
68 #include "PluginDatabase.h"
69 #include "ProgressTracker.h"
70 #include "RefPtr.h"
71 #include "RenderTextControl.h"
72 #include "TextIterator.h"
73 #include "HashMap.h"
74 #include "HTMLFormElement.h"
75 #include "HTMLInputElement.h"
76 #include "HTMLNames.h"
77 #include "HitTestResult.h"
78 #include "WindowFeatures.h"
79 #include "LocalizedStrings.h"
80 #include "Cache.h"
81 #include "runtime/InitializeThreading.h"
82 #include "PageGroup.h"
83 #include "QWebPageClient.h"
84 #include "WorkerThread.h"
85 
86 #include <QApplication>
87 #include <QBasicTimer>
88 #include <QBitArray>
89 #include <QDebug>
90 #include <QDragEnterEvent>
91 #include <QDragLeaveEvent>
92 #include <QDragMoveEvent>
93 #include <QDropEvent>
94 #include <QFileDialog>
95 #include <QHttpRequestHeader>
96 #include <QInputDialog>
97 #include <QLocale>
98 #include <QMessageBox>
99 #include <QNetworkProxy>
100 #include <QUndoStack>
101 #include <QUrl>
102 #include <QPainter>
103 #include <QClipboard>
104 #include <QSslSocket>
105 #include <QStyle>
106 #include <QSysInfo>
107 #include <QTextCharFormat>
108 #include <QTextDocument>
109 #include <QNetworkAccessManager>
110 #include <QNetworkRequest>
111 #if defined(Q_WS_X11)
112 #include <QX11Info>
113 #endif
114 
115 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
116 #include <QTouchEvent>
117 #include "PlatformTouchEvent.h"
118 #endif
119 
120 using namespace WebCore;
121 
qt_drt_overwritePluginDirectories()122 void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories()
123 {
124     PluginDatabase* db = PluginDatabase::installedPlugins(/* populate */ false);
125 
126     Vector<String> paths;
127     String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").data());
128     qtPath.split(UChar(':'), /* allowEmptyEntries */ false, paths);
129 
130     db->setPluginDirectories(paths);
131     db->refresh();
132 }
133 
qt_drt_workerThreadCount()134 int QWEBKIT_EXPORT qt_drt_workerThreadCount()
135 {
136 #if ENABLE(WORKERS)
137     return WebCore::WorkerThread::workerThreadCount();
138 #else
139     return 0;
140 #endif
141 }
142 
143 bool QWebPagePrivate::drtRun = false;
qt_drt_run(bool b)144 void QWEBKIT_EXPORT qt_drt_run(bool b)
145 {
146     QWebPagePrivate::drtRun = b;
147 }
148 
qt_drt_setFrameSetFlatteningEnabled(QWebPage * page,bool enabled)149 void QWEBKIT_EXPORT qt_drt_setFrameSetFlatteningEnabled(QWebPage* page, bool enabled)
150 {
151     QWebPagePrivate::core(page)->settings()->setFrameSetFlatteningEnabled(enabled);
152 }
153 
qt_webpage_setGroupName(QWebPage * page,const QString & groupName)154 void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName)
155 {
156     page->handle()->page->setGroupName(groupName);
157 }
158 
qt_webpage_groupName(QWebPage * page)159 QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page)
160 {
161     return page->handle()->page->groupName();
162 }
163 
164 class QWebPageWidgetClient : public QWebPageClient {
165 public:
QWebPageWidgetClient(QWidget * view)166     QWebPageWidgetClient(QWidget* view)
167         : view(view)
168     {
169         Q_ASSERT(view);
170     }
171 
172     virtual void scroll(int dx, int dy, const QRect&);
173     virtual void update(const QRect& dirtyRect);
174     virtual void setInputMethodEnabled(bool enable);
175     virtual bool inputMethodEnabled() const;
176 #if QT_VERSION >= 0x040600
177     virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable);
178 #endif
179 
180 #ifndef QT_NO_CURSOR
181     virtual QCursor cursor() const;
182     virtual void updateCursor(const QCursor& cursor);
183 #endif
184 
185     virtual QPalette palette() const;
186     virtual int screenNumber() const;
187     virtual QWidget* ownerWidget() const;
188 
189     virtual QObject* pluginParent() const;
190 
191     virtual QStyle* style() const;
192 
193     QWidget* view;
194 };
195 
scroll(int dx,int dy,const QRect & rectToScroll)196 void QWebPageWidgetClient::scroll(int dx, int dy, const QRect& rectToScroll)
197 {
198     view->scroll(qreal(dx), qreal(dy), rectToScroll);
199 }
200 
update(const QRect & dirtyRect)201 void QWebPageWidgetClient::update(const QRect & dirtyRect)
202 {
203     view->update(dirtyRect);
204 }
205 
setInputMethodEnabled(bool enable)206 void QWebPageWidgetClient::setInputMethodEnabled(bool enable)
207 {
208     view->setAttribute(Qt::WA_InputMethodEnabled, enable);
209 }
210 
inputMethodEnabled() const211 bool QWebPageWidgetClient::inputMethodEnabled() const
212 {
213     return view->testAttribute(Qt::WA_InputMethodEnabled);
214 }
215 
216 #if QT_VERSION >= 0x040600
setInputMethodHint(Qt::InputMethodHint hint,bool enable)217 void QWebPageWidgetClient::setInputMethodHint(Qt::InputMethodHint hint, bool enable)
218 {
219     if (enable)
220         view->setInputMethodHints(view->inputMethodHints() | hint);
221     else
222         view->setInputMethodHints(view->inputMethodHints() & ~hint);
223 }
224 #endif
225 #ifndef QT_NO_CURSOR
cursor() const226 QCursor QWebPageWidgetClient::cursor() const
227 {
228     return view->cursor();
229 }
230 
updateCursor(const QCursor & cursor)231 void QWebPageWidgetClient::updateCursor(const QCursor& cursor)
232 {
233     view->setCursor(cursor);
234 }
235 #endif
236 
palette() const237 QPalette QWebPageWidgetClient::palette() const
238 {
239     return view->palette();
240 }
241 
screenNumber() const242 int QWebPageWidgetClient::screenNumber() const
243 {
244 #if defined(Q_WS_X11)
245     if (view)
246         return view->x11Info().screen();
247 #endif
248 
249     return 0;
250 }
251 
ownerWidget() const252 QWidget* QWebPageWidgetClient::ownerWidget() const
253 {
254     return view;
255 }
256 
pluginParent() const257 QObject* QWebPageWidgetClient::pluginParent() const
258 {
259     return view;
260 }
261 
style() const262 QStyle* QWebPageWidgetClient::style() const
263 {
264     return view->style();
265 }
266 
267 // Lookup table mapping QWebPage::WebActions to the associated Editor commands
268 static const char* editorCommandWebActions[] =
269 {
270     0, // OpenLink,
271 
272     0, // OpenLinkInNewWindow,
273     0, // OpenFrameInNewWindow,
274 
275     0, // DownloadLinkToDisk,
276     0, // CopyLinkToClipboard,
277 
278     0, // OpenImageInNewWindow,
279     0, // DownloadImageToDisk,
280     0, // CopyImageToClipboard,
281 
282     0, // Back,
283     0, // Forward,
284     0, // Stop,
285     0, // Reload,
286 
287     "Cut", // Cut,
288     "Copy", // Copy,
289     "Paste", // Paste,
290 
291     "Undo", // Undo,
292     "Redo", // Redo,
293     "MoveForward", // MoveToNextChar,
294     "MoveBackward", // MoveToPreviousChar,
295     "MoveWordForward", // MoveToNextWord,
296     "MoveWordBackward", // MoveToPreviousWord,
297     "MoveDown", // MoveToNextLine,
298     "MoveUp", // MoveToPreviousLine,
299     "MoveToBeginningOfLine", // MoveToStartOfLine,
300     "MoveToEndOfLine", // MoveToEndOfLine,
301     "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
302     "MoveToEndOfParagraph", // MoveToEndOfBlock,
303     "MoveToBeginningOfDocument", // MoveToStartOfDocument,
304     "MoveToEndOfDocument", // MoveToEndOfDocument,
305     "MoveForwardAndModifySelection", // SelectNextChar,
306     "MoveBackwardAndModifySelection", // SelectPreviousChar,
307     "MoveWordForwardAndModifySelection", // SelectNextWord,
308     "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
309     "MoveDownAndModifySelection", // SelectNextLine,
310     "MoveUpAndModifySelection", // SelectPreviousLine,
311     "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
312     "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
313     "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
314     "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
315     "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
316     "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
317     "DeleteWordBackward", // DeleteStartOfWord,
318     "DeleteWordForward", // DeleteEndOfWord,
319 
320     0, // SetTextDirectionDefault,
321     0, // SetTextDirectionLeftToRight,
322     0, // SetTextDirectionRightToLeft,
323 
324     "ToggleBold", // ToggleBold,
325     "ToggleItalic", // ToggleItalic,
326     "ToggleUnderline", // ToggleUnderline,
327 
328     0, // InspectElement,
329 
330     "InsertNewline", // InsertParagraphSeparator
331     "InsertLineBreak", // InsertLineSeparator
332 
333     "SelectAll", // SelectAll
334     0, // ReloadAndBypassCache,
335 
336     "PasteAndMatchStyle", // PasteAndMatchStyle
337     "RemoveFormat", // RemoveFormat
338     "Strikethrough", // ToggleStrikethrough,
339     "Subscript", // ToggleSubscript
340     "Superscript", // ToggleSuperscript
341     "InsertUnorderedList", // InsertUnorderedList
342     "InsertOrderedList", // InsertOrderedList
343     "Indent", // Indent
344     "Outdent", // Outdent,
345 
346     "AlignCenter", // AlignCenter,
347     "AlignJustified", // AlignJustified,
348     "AlignLeft", // AlignLeft,
349     "AlignRight", // AlignRight,
350 
351     0 // WebActionCount
352 };
353 
354 // Lookup the appropriate editor command to use for WebAction \a action
editorCommandForWebActions(QWebPage::WebAction action)355 const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
356 {
357     if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
358         return editorCommandWebActions[action];
359     return 0;
360 }
361 
362 // If you change this make sure to also adjust the docs for QWebPage::userAgentForUrl
363 #define WEBKIT_VERSION "527+"
364 
dropActionToDragOp(Qt::DropActions actions)365 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
366 {
367     unsigned result = 0;
368     if (actions & Qt::CopyAction)
369         result |= DragOperationCopy;
370     // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
371     // hence it should be considered as "move"
372     if (actions & Qt::MoveAction)
373         result |= (DragOperationMove | DragOperationGeneric);
374     if (actions & Qt::LinkAction)
375         result |= DragOperationLink;
376     return (DragOperation)result;
377 }
378 
dragOpToDropAction(unsigned actions)379 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
380 {
381     Qt::DropAction result = Qt::IgnoreAction;
382     if (actions & DragOperationCopy)
383         result = Qt::CopyAction;
384     else if (actions & DragOperationMove)
385         result = Qt::MoveAction;
386     // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
387     // hence it should be considered as "move"
388     else if (actions & DragOperationGeneric)
389         result = Qt::MoveAction;
390     else if (actions & DragOperationLink)
391         result = Qt::LinkAction;
392     return result;
393 }
394 
QWebPagePrivate(QWebPage * qq)395 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
396     : q(qq)
397     , client(0)
398 #if QT_VERSION < 0x040600
399     , view(0)
400 #endif
401     , clickCausedFocus(false)
402     , viewportSize(QSize(0, 0))
403     , inspectorFrontend(0)
404     , inspector(0)
405     , inspectorIsInternalOnly(false)
406 {
407     WebCore::InitializeLoggingChannelsIfNecessary();
408     JSC::initializeThreading();
409     WebCore::SecurityOrigin::setLocalLoadPolicy(WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
410 
411     chromeClient = new ChromeClientQt(q);
412     contextMenuClient = new ContextMenuClientQt();
413     editorClient = new EditorClientQt(q);
414     page = new Page(chromeClient, contextMenuClient, editorClient,
415                     new DragClientQt(q), new InspectorClientQt(q), 0, 0);
416 
417     settings = new QWebSettings(page->settings());
418 
419 #ifndef QT_NO_UNDOSTACK
420     undoStack = 0;
421 #endif
422     mainFrame = 0;
423     networkManager = 0;
424     pluginFactory = 0;
425     insideOpenCall = false;
426     forwardUnsupportedContent = false;
427     editable = false;
428     useFixedLayout = false;
429     linkPolicy = QWebPage::DontDelegateLinks;
430 #ifndef QT_NO_CONTEXTMENU
431     currentContextMenu = 0;
432 #endif
433 
434     history.d = new QWebHistoryPrivate(page->backForwardList());
435     memset(actions, 0, sizeof(actions));
436 
437     PageGroup::setShouldTrackVisitedLinks(true);
438 }
439 
~QWebPagePrivate()440 QWebPagePrivate::~QWebPagePrivate()
441 {
442 #ifndef QT_NO_CONTEXTMENU
443     delete currentContextMenu;
444 #endif
445 #ifndef QT_NO_UNDOSTACK
446     delete undoStack;
447 #endif
448     delete settings;
449     delete page;
450 }
451 
core(QWebPage * page)452 WebCore::Page* QWebPagePrivate::core(QWebPage* page)
453 {
454     return page->d->page;
455 }
456 
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)457 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
458 {
459     if (insideOpenCall
460         && frame == mainFrame)
461         return true;
462     return q->acceptNavigationRequest(frame, request, type);
463 }
464 
createMainFrame()465 void QWebPagePrivate::createMainFrame()
466 {
467     if (!mainFrame) {
468         QWebFrameData frameData(page);
469         mainFrame = new QWebFrame(q, &frameData);
470 
471         emit q->frameCreated(mainFrame);
472     }
473 }
474 
webActionForContextMenuAction(WebCore::ContextMenuAction action)475 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
476 {
477     switch (action) {
478         case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
479         case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
480         case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
481         case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
482         case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
483         case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
484         case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
485         case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
486         case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
487         case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
488         case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
489         case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
490         case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
491         case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
492         case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
493         case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
494         case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
495         case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
496         case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
497         case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
498         case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
499 #if ENABLE(INSPECTOR)
500         case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
501 #endif
502         default: break;
503     }
504     return QWebPage::NoWebAction;
505 }
506 
507 #ifndef QT_NO_CONTEXTMENU
createContextMenu(const WebCore::ContextMenu * webcoreMenu,const QList<WebCore::ContextMenuItem> * items,QBitArray * visitedWebActions)508 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
509         const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
510 {
511     QMenu* menu = new QMenu(q->view());
512     for (int i = 0; i < items->count(); ++i) {
513         const ContextMenuItem &item = items->at(i);
514         switch (item.type()) {
515             case WebCore::CheckableActionType: /* fall through */
516             case WebCore::ActionType: {
517                 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
518                 QAction *a = q->action(action);
519                 if (a) {
520                     ContextMenuItem it(item);
521                     webcoreMenu->checkOrEnableIfNeeded(it);
522                     PlatformMenuItemDescription desc = it.releasePlatformDescription();
523                     a->setEnabled(desc.enabled);
524                     a->setChecked(desc.checked);
525                     a->setCheckable(item.type() == WebCore::CheckableActionType);
526 
527                     menu->addAction(a);
528                     visitedWebActions->setBit(action);
529                 }
530                 break;
531             }
532             case WebCore::SeparatorType:
533                 menu->addSeparator();
534                 break;
535             case WebCore::SubmenuType: {
536                 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
537 
538                 bool anyEnabledAction = false;
539 
540                 QList<QAction *> actions = subMenu->actions();
541                 for (int i = 0; i < actions.count(); ++i) {
542                     if (actions.at(i)->isVisible())
543                         anyEnabledAction |= actions.at(i)->isEnabled();
544                 }
545 
546                 // don't show sub-menus with just disabled actions
547                 if (anyEnabledAction) {
548                     subMenu->setTitle(item.title());
549                     menu->addAction(subMenu->menuAction());
550                 } else
551                     delete subMenu;
552                 break;
553             }
554         }
555     }
556     return menu;
557 }
558 #endif // QT_NO_CONTEXTMENU
559 
_q_webActionTriggered(bool checked)560 void QWebPagePrivate::_q_webActionTriggered(bool checked)
561 {
562     QAction *a = qobject_cast<QAction *>(q->sender());
563     if (!a)
564         return;
565     QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
566     q->triggerAction(action, checked);
567 }
568 
_q_cleanupLeakMessages()569 void QWebPagePrivate::_q_cleanupLeakMessages()
570 {
571 #ifndef NDEBUG
572     // Need this to make leak messages accurate.
573     cache()->setCapacities(0, 0, 0);
574 #endif
575 }
576 
updateAction(QWebPage::WebAction action)577 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
578 {
579     QAction *a = actions[action];
580     if (!a || !mainFrame)
581         return;
582 
583     WebCore::FrameLoader *loader = mainFrame->d->frame->loader();
584     WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
585 
586     bool enabled = a->isEnabled();
587     bool checked = a->isChecked();
588 
589     switch (action) {
590         case QWebPage::Back:
591             enabled = page->canGoBackOrForward(-1);
592             break;
593         case QWebPage::Forward:
594             enabled = page->canGoBackOrForward(1);
595             break;
596         case QWebPage::Stop:
597             enabled = loader->isLoading();
598             break;
599         case QWebPage::Reload:
600         case QWebPage::ReloadAndBypassCache:
601             enabled = !loader->isLoading();
602             break;
603 #ifndef QT_NO_UNDOSTACK
604         case QWebPage::Undo:
605         case QWebPage::Redo:
606             // those two are handled by QUndoStack
607             break;
608 #endif // QT_NO_UNDOSTACK
609         case QWebPage::SelectAll: // editor command is always enabled
610             break;
611         case QWebPage::SetTextDirectionDefault:
612         case QWebPage::SetTextDirectionLeftToRight:
613         case QWebPage::SetTextDirectionRightToLeft:
614             enabled = editor->canEdit();
615             checked = false;
616             break;
617         default: {
618             // see if it's an editor command
619             const char* commandName = editorCommandForWebActions(action);
620 
621             // if it's an editor command, let it's logic determine state
622             if (commandName) {
623                 Editor::Command command = editor->command(commandName);
624                 enabled = command.isEnabled();
625                 if (enabled)
626                     checked = command.state() != FalseTriState;
627                 else
628                     checked = false;
629             }
630             break;
631         }
632     }
633 
634     a->setEnabled(enabled);
635 
636     if (a->isCheckable())
637         a->setChecked(checked);
638 }
639 
updateNavigationActions()640 void QWebPagePrivate::updateNavigationActions()
641 {
642     updateAction(QWebPage::Back);
643     updateAction(QWebPage::Forward);
644     updateAction(QWebPage::Stop);
645     updateAction(QWebPage::Reload);
646     updateAction(QWebPage::ReloadAndBypassCache);
647 }
648 
updateEditorActions()649 void QWebPagePrivate::updateEditorActions()
650 {
651     updateAction(QWebPage::Cut);
652     updateAction(QWebPage::Copy);
653     updateAction(QWebPage::Paste);
654     updateAction(QWebPage::MoveToNextChar);
655     updateAction(QWebPage::MoveToPreviousChar);
656     updateAction(QWebPage::MoveToNextWord);
657     updateAction(QWebPage::MoveToPreviousWord);
658     updateAction(QWebPage::MoveToNextLine);
659     updateAction(QWebPage::MoveToPreviousLine);
660     updateAction(QWebPage::MoveToStartOfLine);
661     updateAction(QWebPage::MoveToEndOfLine);
662     updateAction(QWebPage::MoveToStartOfBlock);
663     updateAction(QWebPage::MoveToEndOfBlock);
664     updateAction(QWebPage::MoveToStartOfDocument);
665     updateAction(QWebPage::MoveToEndOfDocument);
666     updateAction(QWebPage::SelectNextChar);
667     updateAction(QWebPage::SelectPreviousChar);
668     updateAction(QWebPage::SelectNextWord);
669     updateAction(QWebPage::SelectPreviousWord);
670     updateAction(QWebPage::SelectNextLine);
671     updateAction(QWebPage::SelectPreviousLine);
672     updateAction(QWebPage::SelectStartOfLine);
673     updateAction(QWebPage::SelectEndOfLine);
674     updateAction(QWebPage::SelectStartOfBlock);
675     updateAction(QWebPage::SelectEndOfBlock);
676     updateAction(QWebPage::SelectStartOfDocument);
677     updateAction(QWebPage::SelectEndOfDocument);
678     updateAction(QWebPage::DeleteStartOfWord);
679     updateAction(QWebPage::DeleteEndOfWord);
680     updateAction(QWebPage::SetTextDirectionDefault);
681     updateAction(QWebPage::SetTextDirectionLeftToRight);
682     updateAction(QWebPage::SetTextDirectionRightToLeft);
683     updateAction(QWebPage::ToggleBold);
684     updateAction(QWebPage::ToggleItalic);
685     updateAction(QWebPage::ToggleUnderline);
686     updateAction(QWebPage::InsertParagraphSeparator);
687     updateAction(QWebPage::InsertLineSeparator);
688     updateAction(QWebPage::PasteAndMatchStyle);
689     updateAction(QWebPage::RemoveFormat);
690     updateAction(QWebPage::ToggleStrikethrough);
691     updateAction(QWebPage::ToggleSubscript);
692     updateAction(QWebPage::ToggleSuperscript);
693     updateAction(QWebPage::InsertUnorderedList);
694     updateAction(QWebPage::InsertOrderedList);
695     updateAction(QWebPage::Indent);
696     updateAction(QWebPage::Outdent);
697     updateAction(QWebPage::AlignCenter);
698     updateAction(QWebPage::AlignJustified);
699     updateAction(QWebPage::AlignLeft);
700     updateAction(QWebPage::AlignRight);
701 }
702 
timerEvent(QTimerEvent * ev)703 void QWebPagePrivate::timerEvent(QTimerEvent *ev)
704 {
705     int timerId = ev->timerId();
706     if (timerId == tripleClickTimer.timerId())
707         tripleClickTimer.stop();
708     else
709         q->QObject::timerEvent(ev);
710 }
711 
mouseMoveEvent(QGraphicsSceneMouseEvent * ev)712 void QWebPagePrivate::mouseMoveEvent(QGraphicsSceneMouseEvent* ev)
713 {
714     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
715     if (!frame->view())
716         return;
717 
718     bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
719     ev->setAccepted(accepted);
720 }
721 
mouseMoveEvent(QMouseEvent * ev)722 void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev)
723 {
724     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
725     if (!frame->view())
726         return;
727 
728     bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
729     ev->setAccepted(accepted);
730 }
731 
mousePressEvent(QGraphicsSceneMouseEvent * ev)732 void QWebPagePrivate::mousePressEvent(QGraphicsSceneMouseEvent* ev)
733 {
734     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
735     if (!frame->view())
736         return;
737 
738     if (tripleClickTimer.isActive()
739             && (ev->pos().toPoint() - tripleClick).manhattanLength()
740                 < QApplication::startDragDistance()) {
741         mouseTripleClickEvent(ev);
742         return;
743     }
744 
745     bool accepted = false;
746     PlatformMouseEvent mev(ev, 1);
747     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
748     if (mev.button() != NoButton)
749         accepted = frame->eventHandler()->handleMousePressEvent(mev);
750     ev->setAccepted(accepted);
751 }
752 
mousePressEvent(QMouseEvent * ev)753 void QWebPagePrivate::mousePressEvent(QMouseEvent *ev)
754 {
755     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
756     if (!frame->view())
757         return;
758 
759     RefPtr<WebCore::Node> oldNode;
760     if (page->focusController()->focusedFrame()
761         && page->focusController()->focusedFrame()->document())
762         oldNode = page->focusController()->focusedFrame()->document()->focusedNode();
763 
764     if (tripleClickTimer.isActive()
765             && (ev->pos() - tripleClick).manhattanLength()
766                 < QApplication::startDragDistance()) {
767         mouseTripleClickEvent(ev);
768         return;
769     }
770 
771     bool accepted = false;
772     PlatformMouseEvent mev(ev, 1);
773     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
774     if (mev.button() != NoButton)
775         accepted = frame->eventHandler()->handleMousePressEvent(mev);
776     ev->setAccepted(accepted);
777 
778     RefPtr<WebCore::Node> newNode;
779     if (page->focusController()->focusedFrame()
780         && page->focusController()->focusedFrame()->document())
781         newNode = page->focusController()->focusedFrame()->document()->focusedNode();
782 
783     if (newNode && oldNode != newNode)
784         clickCausedFocus = true;
785 }
786 
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * ev)787 void QWebPagePrivate::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *ev)
788 {
789     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
790     if (!frame->view())
791         return;
792 
793     bool accepted = false;
794     PlatformMouseEvent mev(ev, 2);
795     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
796     if (mev.button() != NoButton)
797         accepted = frame->eventHandler()->handleMousePressEvent(mev);
798     ev->setAccepted(accepted);
799 
800     tripleClickTimer.start(QApplication::doubleClickInterval(), q);
801     tripleClick = ev->pos().toPoint();
802 }
803 
mouseDoubleClickEvent(QMouseEvent * ev)804 void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev)
805 {
806     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
807     if (!frame->view())
808         return;
809 
810     bool accepted = false;
811     PlatformMouseEvent mev(ev, 2);
812     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
813     if (mev.button() != NoButton)
814         accepted = frame->eventHandler()->handleMousePressEvent(mev);
815     ev->setAccepted(accepted);
816 
817     tripleClickTimer.start(QApplication::doubleClickInterval(), q);
818     tripleClick = ev->pos();
819 }
820 
mouseTripleClickEvent(QGraphicsSceneMouseEvent * ev)821 void QWebPagePrivate::mouseTripleClickEvent(QGraphicsSceneMouseEvent *ev)
822 {
823     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
824     if (!frame->view())
825         return;
826 
827     bool accepted = false;
828     PlatformMouseEvent mev(ev, 3);
829     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
830     if (mev.button() != NoButton)
831         accepted = frame->eventHandler()->handleMousePressEvent(mev);
832     ev->setAccepted(accepted);
833 }
834 
mouseTripleClickEvent(QMouseEvent * ev)835 void QWebPagePrivate::mouseTripleClickEvent(QMouseEvent *ev)
836 {
837     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
838     if (!frame->view())
839         return;
840 
841     bool accepted = false;
842     PlatformMouseEvent mev(ev, 3);
843     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
844     if (mev.button() != NoButton)
845         accepted = frame->eventHandler()->handleMousePressEvent(mev);
846     ev->setAccepted(accepted);
847 }
848 
handleClipboard(QEvent * ev,Qt::MouseButton button)849 void QWebPagePrivate::handleClipboard(QEvent* ev, Qt::MouseButton button)
850 {
851 #ifndef QT_NO_CLIPBOARD
852     if (QApplication::clipboard()->supportsSelection()) {
853         bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
854         Pasteboard::generalPasteboard()->setSelectionMode(true);
855         WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
856         if (button == Qt::LeftButton) {
857             if (focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
858                 focusFrame->editor()->copy();
859                 ev->setAccepted(true);
860             }
861         } else if (button == Qt::MidButton) {
862             if (focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
863                 focusFrame->editor()->paste();
864                 ev->setAccepted(true);
865             }
866         }
867         Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
868     }
869 #endif
870 }
871 
mouseReleaseEvent(QGraphicsSceneMouseEvent * ev)872 void QWebPagePrivate::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev)
873 {
874     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
875     if (!frame->view())
876         return;
877 
878     bool accepted = false;
879     PlatformMouseEvent mev(ev, 0);
880     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
881     if (mev.button() != NoButton)
882         accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
883     ev->setAccepted(accepted);
884 
885     handleClipboard(ev, ev->button());
886     handleSoftwareInputPanel(ev->button());
887 }
888 
handleSoftwareInputPanel(Qt::MouseButton button)889 void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button)
890 {
891 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
892     Frame* frame = page->focusController()->focusedFrame();
893     if (!frame)
894         return;
895 
896     if (client && client->inputMethodEnabled()
897         && frame->document()->focusedNode()
898         && button == Qt::LeftButton && qApp->autoSipEnabled()) {
899         QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
900             client->ownerWidget()->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
901         if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
902             QEvent event(QEvent::RequestSoftwareInputPanel);
903             QApplication::sendEvent(client->ownerWidget(), &event);
904         }
905     }
906 
907     clickCausedFocus = false;
908 #endif
909 }
910 
mouseReleaseEvent(QMouseEvent * ev)911 void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev)
912 {
913     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
914     if (!frame->view())
915         return;
916 
917     bool accepted = false;
918     PlatformMouseEvent mev(ev, 0);
919     // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
920     if (mev.button() != NoButton)
921         accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
922     ev->setAccepted(accepted);
923 
924     handleClipboard(ev, ev->button());
925     handleSoftwareInputPanel(ev->button());
926 }
927 
928 #ifndef QT_NO_CONTEXTMENU
contextMenuEvent(const QPoint & globalPos)929 void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
930 {
931     QMenu *menu = q->createStandardContextMenu();
932     if (menu) {
933         menu->exec(globalPos);
934         delete menu;
935     }
936 }
937 #endif // QT_NO_CONTEXTMENU
938 
939 /*!
940     \since 4.5
941     This function creates the standard context menu which is shown when
942     the user clicks on the web page with the right mouse button. It is
943     called from the default contextMenuEvent() handler. The popup menu's
944     ownership is transferred to the caller.
945  */
createStandardContextMenu()946 QMenu *QWebPage::createStandardContextMenu()
947 {
948 #ifndef QT_NO_CONTEXTMENU
949     QMenu *menu = d->currentContextMenu;
950     d->currentContextMenu = 0;
951     return menu;
952 #else
953     return 0;
954 #endif
955 }
956 
957 #ifndef QT_NO_WHEELEVENT
wheelEvent(QGraphicsSceneWheelEvent * ev)958 void QWebPagePrivate::wheelEvent(QGraphicsSceneWheelEvent* ev)
959 {
960     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
961     if (!frame->view())
962         return;
963 
964     WebCore::PlatformWheelEvent pev(ev);
965     bool accepted = frame->eventHandler()->handleWheelEvent(pev);
966     ev->setAccepted(accepted);
967 }
968 
wheelEvent(QWheelEvent * ev)969 void QWebPagePrivate::wheelEvent(QWheelEvent *ev)
970 {
971     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
972     if (!frame->view())
973         return;
974 
975     WebCore::PlatformWheelEvent pev(ev);
976     bool accepted = frame->eventHandler()->handleWheelEvent(pev);
977     ev->setAccepted(accepted);
978 }
979 #endif // QT_NO_WHEELEVENT
980 
981 #ifndef QT_NO_SHORTCUT
editorActionForKeyEvent(QKeyEvent * event)982 QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
983 {
984     static struct {
985         QKeySequence::StandardKey standardKey;
986         QWebPage::WebAction action;
987     } editorActions[] = {
988         { QKeySequence::Cut, QWebPage::Cut },
989         { QKeySequence::Copy, QWebPage::Copy },
990         { QKeySequence::Paste, QWebPage::Paste },
991         { QKeySequence::Undo, QWebPage::Undo },
992         { QKeySequence::Redo, QWebPage::Redo },
993         { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
994         { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
995         { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
996         { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
997         { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
998         { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
999         { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
1000         { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
1001         { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
1002         { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
1003         { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
1004         { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
1005         { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
1006         { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
1007         { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
1008         { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
1009         { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
1010         { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
1011         { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
1012         { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
1013         { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
1014         { QKeySequence::SelectEndOfBlock,  QWebPage::SelectEndOfBlock },
1015         { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
1016         { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
1017         { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
1018         { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
1019 #if QT_VERSION >= 0x040500
1020         { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
1021         { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
1022 #endif
1023         { QKeySequence::SelectAll, QWebPage::SelectAll },
1024         { QKeySequence::UnknownKey, QWebPage::NoWebAction }
1025     };
1026 
1027     for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
1028         if (event == editorActions[i].standardKey)
1029             return editorActions[i].action;
1030 
1031     return QWebPage::NoWebAction;
1032 }
1033 #endif // QT_NO_SHORTCUT
1034 
keyPressEvent(QKeyEvent * ev)1035 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
1036 {
1037     bool handled = false;
1038     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1039     // we forward the key event to WebCore first to handle potential DOM
1040     // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
1041     // to trigger editor commands via triggerAction().
1042     if (!handled)
1043         handled = frame->eventHandler()->keyEvent(ev);
1044     if (!handled) {
1045         handled = true;
1046         QFont defaultFont;
1047         if (q->view())
1048             defaultFont = q->view()->font();
1049         QFontMetrics fm(defaultFont);
1050         if (!handleScrolling(ev, frame)) {
1051             switch (ev->key()) {
1052             case Qt::Key_Back:
1053                 q->triggerAction(QWebPage::Back);
1054                 break;
1055             case Qt::Key_Forward:
1056                 q->triggerAction(QWebPage::Forward);
1057                 break;
1058             case Qt::Key_Stop:
1059                 q->triggerAction(QWebPage::Stop);
1060                 break;
1061             case Qt::Key_Refresh:
1062                 q->triggerAction(QWebPage::Reload);
1063                 break;
1064             case Qt::Key_Backspace:
1065                 if (ev->modifiers() == Qt::ShiftModifier)
1066                     q->triggerAction(QWebPage::Forward);
1067                 else
1068                     q->triggerAction(QWebPage::Back);
1069                 break;
1070             default:
1071                 handled = false;
1072                 break;
1073             }
1074         }
1075     }
1076 
1077     ev->setAccepted(handled);
1078 }
1079 
keyReleaseEvent(QKeyEvent * ev)1080 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
1081 {
1082     if (ev->isAutoRepeat()) {
1083         ev->setAccepted(true);
1084         return;
1085     }
1086 
1087     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1088     bool handled = frame->eventHandler()->keyEvent(ev);
1089     ev->setAccepted(handled);
1090 }
1091 
focusInEvent(QFocusEvent *)1092 void QWebPagePrivate::focusInEvent(QFocusEvent*)
1093 {
1094     FocusController *focusController = page->focusController();
1095     focusController->setActive(true);
1096     focusController->setFocused(true);
1097     if (!focusController->focusedFrame())
1098         focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame));
1099 }
1100 
focusOutEvent(QFocusEvent *)1101 void QWebPagePrivate::focusOutEvent(QFocusEvent*)
1102 {
1103     // only set the focused frame inactive so that we stop painting the caret
1104     // and the focus frame. But don't tell the focus controller so that upon
1105     // focusInEvent() we can re-activate the frame.
1106     FocusController *focusController = page->focusController();
1107     // Call setFocused first so that window.onblur doesn't get called twice
1108     focusController->setFocused(false);
1109     focusController->setActive(false);
1110 }
1111 
dragEnterEvent(QGraphicsSceneDragDropEvent * ev)1112 void QWebPagePrivate::dragEnterEvent(QGraphicsSceneDragDropEvent* ev)
1113 {
1114 #ifndef QT_NO_DRAGANDDROP
1115     DragData dragData(ev->mimeData(), ev->pos().toPoint(),
1116             QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1117     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
1118     ev->setDropAction(action);
1119     if (action != Qt::IgnoreAction)
1120         ev->accept();
1121 #endif
1122 }
1123 
dragEnterEvent(QDragEnterEvent * ev)1124 void QWebPagePrivate::dragEnterEvent(QDragEnterEvent* ev)
1125 {
1126 #ifndef QT_NO_DRAGANDDROP
1127     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
1128                       dropActionToDragOp(ev->possibleActions()));
1129     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
1130     ev->setDropAction(action);
1131     // We must accept this event in order to receive the drag move events that are sent
1132     // while the drag and drop action is in progress.
1133     ev->accept();
1134 #endif
1135 }
1136 
dragLeaveEvent(QGraphicsSceneDragDropEvent * ev)1137 void QWebPagePrivate::dragLeaveEvent(QGraphicsSceneDragDropEvent* ev)
1138 {
1139 #ifndef QT_NO_DRAGANDDROP
1140     DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1141     page->dragController()->dragExited(&dragData);
1142     ev->accept();
1143 #endif
1144 }
1145 
dragLeaveEvent(QDragLeaveEvent * ev)1146 void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent* ev)
1147 {
1148 #ifndef QT_NO_DRAGANDDROP
1149     DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1150     page->dragController()->dragExited(&dragData);
1151     ev->accept();
1152 #endif
1153 }
1154 
dragMoveEvent(QGraphicsSceneDragDropEvent * ev)1155 void QWebPagePrivate::dragMoveEvent(QGraphicsSceneDragDropEvent* ev)
1156 {
1157 #ifndef QT_NO_DRAGANDDROP
1158     DragData dragData(ev->mimeData(), ev->pos().toPoint(),
1159             QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1160     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
1161     ev->setDropAction(action);
1162     if (action != Qt::IgnoreAction)
1163         ev->accept();
1164 #endif
1165 }
1166 
dragMoveEvent(QDragMoveEvent * ev)1167 void QWebPagePrivate::dragMoveEvent(QDragMoveEvent* ev)
1168 {
1169 #ifndef QT_NO_DRAGANDDROP
1170     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
1171                       dropActionToDragOp(ev->possibleActions()));
1172     Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
1173     m_lastDropAction = action;
1174     ev->setDropAction(action);
1175     // We must accept this event in order to receive the drag move events that are sent
1176     // while the drag and drop action is in progress.
1177     ev->accept();
1178 #endif
1179 }
1180 
dropEvent(QGraphicsSceneDragDropEvent * ev)1181 void QWebPagePrivate::dropEvent(QGraphicsSceneDragDropEvent* ev)
1182 {
1183 #ifndef QT_NO_DRAGANDDROP
1184     DragData dragData(ev->mimeData(), ev->pos().toPoint(),
1185             QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1186     if (page->dragController()->performDrag(&dragData))
1187         ev->accept();
1188 #endif
1189 }
1190 
dropEvent(QDropEvent * ev)1191 void QWebPagePrivate::dropEvent(QDropEvent* ev)
1192 {
1193 #ifndef QT_NO_DRAGANDDROP
1194     // Overwrite the defaults set by QDragManager::defaultAction()
1195     ev->setDropAction(m_lastDropAction);
1196     DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(),
1197                       dropActionToDragOp(Qt::DropAction(ev->dropAction())));
1198     if (page->dragController()->performDrag(&dragData))
1199         ev->accept();
1200 #endif
1201 }
1202 
leaveEvent(QEvent *)1203 void QWebPagePrivate::leaveEvent(QEvent*)
1204 {
1205     // Fake a mouse move event just outside of the widget, since all
1206     // the interesting mouse-out behavior like invalidating scrollbars
1207     // is handled by the WebKit event handler's mouseMoved function.
1208     QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
1209     mouseMoveEvent(&fakeEvent);
1210 }
1211 
1212 /*!
1213     \property QWebPage::palette
1214     \brief the page's palette
1215 
1216     The base brush of the palette is used to draw the background of the main frame.
1217 
1218     By default, this property contains the application's default palette.
1219 */
setPalette(const QPalette & pal)1220 void QWebPage::setPalette(const QPalette &pal)
1221 {
1222     d->palette = pal;
1223     if (!d->mainFrame || !d->mainFrame->d->frame->view())
1224         return;
1225 
1226     QBrush brush = pal.brush(QPalette::Base);
1227     QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
1228     QWebFramePrivate::core(d->mainFrame)->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha());
1229 }
1230 
palette() const1231 QPalette QWebPage::palette() const
1232 {
1233     return d->palette;
1234 }
1235 
inputMethodEvent(QInputMethodEvent * ev)1236 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
1237 {
1238     WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
1239     WebCore::Editor *editor = frame->editor();
1240 
1241     if (!editor->canEdit()) {
1242         ev->ignore();
1243         return;
1244     }
1245 
1246     RenderObject* renderer = 0;
1247     RenderTextControl* renderTextControl = 0;
1248 
1249     if (frame->selection()->rootEditableElement())
1250         renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1251 
1252     if (renderer && renderer->isTextControl())
1253         renderTextControl = toRenderTextControl(renderer);
1254 
1255     Vector<CompositionUnderline> underlines;
1256 
1257     for (int i = 0; i < ev->attributes().size(); ++i) {
1258         const QInputMethodEvent::Attribute& a = ev->attributes().at(i);
1259         switch (a.type) {
1260         case QInputMethodEvent::TextFormat: {
1261             QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat();
1262             QColor qcolor = textCharFormat.underlineColor();
1263             underlines.append(CompositionUnderline(a.start, a.length, Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())), false));
1264             break;
1265         }
1266         case QInputMethodEvent::Cursor: {
1267             frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible
1268             if (a.length > 0) {
1269                 RenderObject* caretRenderer = frame->selection()->caretRenderer();
1270                 if (caretRenderer) {
1271                     QColor qcolor = a.value.value<QColor>();
1272                     caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())));
1273                 }
1274             }
1275             break;
1276         }
1277 #if QT_VERSION >= 0x040600
1278         case QInputMethodEvent::Selection: {
1279             if (renderTextControl) {
1280                 renderTextControl->setSelectionStart(a.start);
1281                 renderTextControl->setSelectionEnd(a.start + a.length);
1282             }
1283             break;
1284         }
1285 #endif
1286         }
1287     }
1288 
1289     if (!ev->commitString().isEmpty())
1290         editor->confirmComposition(ev->commitString());
1291     else if (!ev->preeditString().isEmpty()) {
1292         QString preedit = ev->preeditString();
1293         editor->setComposition(preedit, underlines, preedit.length(), 0);
1294     }
1295     ev->accept();
1296 }
1297 
shortcutOverrideEvent(QKeyEvent * event)1298 void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
1299 {
1300     WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1301     WebCore::Editor* editor = frame->editor();
1302     if (editor->canEdit()) {
1303         if (event->modifiers() == Qt::NoModifier
1304             || event->modifiers() == Qt::ShiftModifier
1305             || event->modifiers() == Qt::KeypadModifier) {
1306                 if (event->key() < Qt::Key_Escape) {
1307                     event->accept();
1308                 } else {
1309                     switch (event->key()) {
1310                     case Qt::Key_Return:
1311                     case Qt::Key_Enter:
1312                     case Qt::Key_Delete:
1313                     case Qt::Key_Home:
1314                     case Qt::Key_End:
1315                     case Qt::Key_Backspace:
1316                     case Qt::Key_Left:
1317                     case Qt::Key_Right:
1318                     case Qt::Key_Up:
1319                     case Qt::Key_Down:
1320                     case Qt::Key_Tab:
1321                         event->accept();
1322                     default:
1323                         break;
1324                     }
1325                 }
1326         }
1327 #ifndef QT_NO_SHORTCUT
1328         else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
1329             event->accept();
1330 #endif
1331     }
1332 }
1333 
handleScrolling(QKeyEvent * ev,Frame * frame)1334 bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame)
1335 {
1336     ScrollDirection direction;
1337     ScrollGranularity granularity;
1338 
1339 #ifndef QT_NO_SHORTCUT
1340     if (ev == QKeySequence::MoveToNextPage
1341         || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
1342         granularity = ScrollByPage;
1343         direction = ScrollDown;
1344     } else if (ev == QKeySequence::MoveToPreviousPage
1345                || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) {
1346         granularity = ScrollByPage;
1347         direction = ScrollUp;
1348     } else
1349 #endif // QT_NO_SHORTCUT
1350     if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier)
1351                || ev->key() == Qt::Key_Home) {
1352         granularity = ScrollByDocument;
1353         direction = ScrollUp;
1354     } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier)
1355                || ev->key() == Qt::Key_End) {
1356         granularity = ScrollByDocument;
1357         direction = ScrollDown;
1358     } else {
1359         switch (ev->key()) {
1360             case Qt::Key_Up:
1361                 granularity = ScrollByLine;
1362                 direction = ScrollUp;
1363                 break;
1364             case Qt::Key_Down:
1365                 granularity = ScrollByLine;
1366                 direction = ScrollDown;
1367                 break;
1368             case Qt::Key_Left:
1369                 granularity = ScrollByLine;
1370                 direction = ScrollLeft;
1371                 break;
1372             case Qt::Key_Right:
1373                 granularity = ScrollByLine;
1374                 direction = ScrollRight;
1375                 break;
1376             default:
1377                 return false;
1378         }
1379     }
1380 
1381     return frame->eventHandler()->scrollRecursively(direction, granularity);
1382 }
1383 
1384 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
touchEvent(QTouchEvent * event)1385 void QWebPagePrivate::touchEvent(QTouchEvent* event)
1386 {
1387     WebCore::Frame* frame = QWebFramePrivate::core(mainFrame);
1388     if (!frame->view())
1389         return;
1390 
1391     bool accepted = frame->eventHandler()->handleTouchEvent(PlatformTouchEvent(event));
1392     event->setAccepted(accepted);
1393 }
1394 #endif
1395 
1396 /*!
1397   This method is used by the input method to query a set of properties of the page
1398   to be able to support complex input method operations as support for surrounding
1399   text and reconversions.
1400 
1401   \a property specifies which property is queried.
1402 
1403   \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
1404 */
inputMethodQuery(Qt::InputMethodQuery property) const1405 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1406 {
1407     Frame* frame = d->page->focusController()->focusedFrame();
1408     if (!frame)
1409         return QVariant();
1410 
1411     WebCore::Editor* editor = frame->editor();
1412 
1413     RenderObject* renderer = 0;
1414     RenderTextControl* renderTextControl = 0;
1415 
1416     if (frame->selection()->rootEditableElement())
1417         renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1418 
1419     if (renderer && renderer->isTextControl())
1420         renderTextControl = toRenderTextControl(renderer);
1421 
1422     switch (property) {
1423         case Qt::ImMicroFocus: {
1424             WebCore::FrameView* view = frame->view();
1425             if (view && view->needsLayout()) {
1426                 // We can't access absoluteCaretBounds() while the view needs to layout.
1427                 return QVariant();
1428             }
1429             return QVariant(frame->selection()->absoluteCaretBounds());
1430         }
1431         case Qt::ImFont: {
1432             if (renderTextControl) {
1433                 RenderStyle* renderStyle = renderTextControl->style();
1434                 return QVariant(QFont(renderStyle->font().font()));
1435             }
1436             return QVariant(QFont());
1437         }
1438         case Qt::ImCursorPosition: {
1439             if (renderTextControl) {
1440                 if (editor->hasComposition()) {
1441                     RefPtr<Range> range = editor->compositionRange();
1442                     return QVariant(renderTextControl->selectionEnd() - TextIterator::rangeLength(range.get()));
1443                 }
1444                 return QVariant(renderTextControl->selectionEnd());
1445             }
1446             return QVariant();
1447         }
1448         case Qt::ImSurroundingText: {
1449             if (renderTextControl) {
1450                 QString text = renderTextControl->text();
1451                 RefPtr<Range> range = editor->compositionRange();
1452                 if (range) {
1453                     text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get()));
1454                 }
1455                 return QVariant(text);
1456             }
1457             return QVariant();
1458         }
1459         case Qt::ImCurrentSelection: {
1460             if (renderTextControl) {
1461                 int start = renderTextControl->selectionStart();
1462                 int end = renderTextControl->selectionEnd();
1463                 if (end > start)
1464                     return QVariant(QString(renderTextControl->text()).mid(start,end-start));
1465             }
1466             return QVariant();
1467 
1468         }
1469 #if QT_VERSION >= 0x040600
1470         case Qt::ImAnchorPosition: {
1471             if (renderTextControl) {
1472                 if (editor->hasComposition()) {
1473                     RefPtr<Range> range = editor->compositionRange();
1474                     return QVariant(renderTextControl->selectionStart() - TextIterator::rangeLength(range.get()));
1475                 }
1476                 return QVariant(renderTextControl->selectionStart());
1477             }
1478             return QVariant();
1479         }
1480         case Qt::ImMaximumTextLength: {
1481             if (frame->selection()->isContentEditable()) {
1482                 if (frame->document() && frame->document()->focusedNode()) {
1483                     if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
1484                         HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
1485                         return QVariant(inputElement->maxLength());
1486                     }
1487                 }
1488                 return QVariant(InputElement::s_maximumLength);
1489             }
1490             return QVariant(0);
1491         }
1492 #endif
1493         default:
1494             return QVariant();
1495     }
1496 }
1497 
1498 /*!
1499     \internal
1500 */
setInspector(QWebInspector * insp)1501 void QWebPagePrivate::setInspector(QWebInspector* insp)
1502 {
1503     if (inspector)
1504         inspector->d->setFrontend(0);
1505 
1506     if (inspectorIsInternalOnly) {
1507         QWebInspector* inspToDelete = inspector;
1508         inspector = 0;
1509         inspectorIsInternalOnly = false;
1510         delete inspToDelete;    // Delete after to prevent infinite recursion
1511     }
1512 
1513     inspector = insp;
1514 
1515     // Give inspector frontend web view if previously created
1516     if (inspector && inspectorFrontend)
1517         inspector->d->setFrontend(inspectorFrontend);
1518 }
1519 
1520 /*!
1521     \internal
1522     Returns the inspector and creates it if it wasn't created yet.
1523     The instance created here will not be available through QWebPage's API.
1524 */
getOrCreateInspector()1525 QWebInspector* QWebPagePrivate::getOrCreateInspector()
1526 {
1527 #if ENABLE(INSPECTOR)
1528     if (!inspector) {
1529         QWebInspector* insp = new QWebInspector;
1530         insp->setPage(q);
1531         inspectorIsInternalOnly = true;
1532 
1533         Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1534     }
1535 #endif
1536     return inspector;
1537 }
1538 
1539 /*! \internal */
inspectorController()1540 InspectorController* QWebPagePrivate::inspectorController()
1541 {
1542 #if ENABLE(INSPECTOR)
1543     return page->inspectorController();
1544 #else
1545     return 0;
1546 #endif
1547 }
1548 
1549 
1550 /*!
1551    \enum QWebPage::FindFlag
1552 
1553    This enum describes the options available to QWebPage's findText() function. The options
1554    can be OR-ed together from the following list:
1555 
1556    \value FindBackward Searches backwards instead of forwards.
1557    \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1558    changes the behaviour to a case sensitive find operation.
1559    \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1560    was reached and the text was not found.
1561    \value HighlightAllOccurrences Highlights all existing occurrences of a specific string.
1562 */
1563 
1564 /*!
1565     \enum QWebPage::LinkDelegationPolicy
1566 
1567     This enum defines the delegation policies a webpage can have when activating links and emitting
1568     the linkClicked() signal.
1569 
1570     \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1571     \value DelegateExternalLinks When activating links that point to documents not stored on the
1572     local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1573     \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1574 */
1575 
1576 /*!
1577     \enum QWebPage::NavigationType
1578 
1579     This enum describes the types of navigation available when browsing through hyperlinked
1580     documents.
1581 
1582     \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1583     \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1584     \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1585     \value NavigationTypeReload The user activated the reload action.
1586     \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1587     \value NavigationTypeOther A navigation to another document using a method not listed above.
1588 */
1589 
1590 /*!
1591     \enum QWebPage::WebAction
1592 
1593     This enum describes the types of action which can be performed on the web page.
1594 
1595     Actions only have an effect when they are applicable. The availability of
1596     actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1597     action returned by \l{QWebPage::}{action()}.
1598 
1599     One method of enabling the text editing, cursor movement, and text selection actions
1600     is by setting \l contentEditable to true.
1601 
1602     \value NoWebAction No action is triggered.
1603     \value OpenLink Open the current link.
1604     \value OpenLinkInNewWindow Open the current link in a new window.
1605     \value OpenFrameInNewWindow Replicate the current frame in a new window.
1606     \value DownloadLinkToDisk Download the current link to the disk.
1607     \value CopyLinkToClipboard Copy the current link to the clipboard.
1608     \value OpenImageInNewWindow Open the highlighted image in a new window.
1609     \value DownloadImageToDisk Download the highlighted image to the disk.
1610     \value CopyImageToClipboard Copy the highlighted image to the clipboard.
1611     \value Back Navigate back in the history of navigated links.
1612     \value Forward Navigate forward in the history of navigated links.
1613     \value Stop Stop loading the current page.
1614     \value Reload Reload the current page.
1615     \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1616     \value Cut Cut the content currently selected into the clipboard.
1617     \value Copy Copy the content currently selected into the clipboard.
1618     \value Paste Paste content from the clipboard.
1619     \value Undo Undo the last editing action.
1620     \value Redo Redo the last editing action.
1621     \value MoveToNextChar Move the cursor to the next character.
1622     \value MoveToPreviousChar Move the cursor to the previous character.
1623     \value MoveToNextWord Move the cursor to the next word.
1624     \value MoveToPreviousWord Move the cursor to the previous word.
1625     \value MoveToNextLine Move the cursor to the next line.
1626     \value MoveToPreviousLine Move the cursor to the previous line.
1627     \value MoveToStartOfLine Move the cursor to the start of the line.
1628     \value MoveToEndOfLine Move the cursor to the end of the line.
1629     \value MoveToStartOfBlock Move the cursor to the start of the block.
1630     \value MoveToEndOfBlock Move the cursor to the end of the block.
1631     \value MoveToStartOfDocument Move the cursor to the start of the document.
1632     \value MoveToEndOfDocument Move the cursor to the end of the document.
1633     \value SelectNextChar Select to the next character.
1634     \value SelectPreviousChar Select to the previous character.
1635     \value SelectNextWord Select to the next word.
1636     \value SelectPreviousWord Select to the previous word.
1637     \value SelectNextLine Select to the next line.
1638     \value SelectPreviousLine Select to the previous line.
1639     \value SelectStartOfLine Select to the start of the line.
1640     \value SelectEndOfLine Select to the end of the line.
1641     \value SelectStartOfBlock Select to the start of the block.
1642     \value SelectEndOfBlock Select to the end of the block.
1643     \value SelectStartOfDocument Select to the start of the document.
1644     \value SelectEndOfDocument Select to the end of the document.
1645     \value DeleteStartOfWord Delete to the start of the word.
1646     \value DeleteEndOfWord Delete to the end of the word.
1647     \value SetTextDirectionDefault Set the text direction to the default direction.
1648     \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1649     \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1650     \value ToggleBold Toggle the formatting between bold and normal weight.
1651     \value ToggleItalic Toggle the formatting between italic and normal style.
1652     \value ToggleUnderline Toggle underlining.
1653     \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1654     \value InsertParagraphSeparator Insert a new paragraph.
1655     \value InsertLineSeparator Insert a new line.
1656     \value SelectAll Selects all content.
1657     \value PasteAndMatchStyle Paste content from the clipboard with current style.
1658     \value RemoveFormat Removes formatting and style.
1659     \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style.
1660     \value ToggleSubscript Toggle the formatting between subscript and baseline.
1661     \value ToggleSuperscript Toggle the formatting between supercript and baseline.
1662     \value InsertUnorderedList Toggles the selection between an ordered list and a normal block.
1663     \value InsertOrderedList Toggles the selection between an ordered list and a normal block.
1664     \value Indent Increases the indentation of the currently selected format block by one increment.
1665     \value Outdent Decreases the indentation of the currently selected format block by one increment.
1666     \value AlignCenter Applies center alignment to content.
1667     \value AlignJustified Applies full justification to content.
1668     \value AlignLeft Applies left justification to content.
1669     \value AlignRight Applies right justification to content.
1670 
1671 
1672     \omitvalue WebActionCount
1673 
1674 */
1675 
1676 /*!
1677     \enum QWebPage::WebWindowType
1678 
1679     \value WebBrowserWindow The window is a regular web browser window.
1680     \value WebModalDialog The window acts as modal dialog.
1681 */
1682 
1683 /*!
1684     \class QWebPage
1685     \since 4.4
1686     \brief The QWebPage class provides an object to view and edit web documents.
1687 
1688     \inmodule QtWebKit
1689 
1690     QWebPage holds a main frame responsible for web content, settings, the history
1691     of navigated links and actions. This class can be used, together with QWebFrame,
1692     to provide functionality like QWebView in a widget-less environment.
1693 
1694     QWebPage's API is very similar to QWebView, as you are still provided with
1695     common functions like action() (known as \l{QWebView::}{pageAction()} in
1696     QWebView), triggerAction(), findText() and settings(). More QWebView-like
1697     functions can be found in the main frame of QWebPage, obtained via
1698     QWebPage::mainFrame(). For example, the load(), setUrl() and setHtml()
1699     unctions for QWebPage can be accessed using QWebFrame.
1700 
1701     The loadStarted() signal is emitted when the page begins to load.The
1702     loadProgress() signal, on the other hand, is emitted whenever an element
1703     of the web page completes loading, such as an embedded image, a script,
1704     etc. Finally, the loadFinished() signal is emitted when the page has
1705     loaded completely. Its argument, either true or false, indicates whether
1706     or not the load operation succeeded.
1707 
1708     \section1 Using QWebPage in a Widget-less Environment
1709 
1710     Before you begin painting a QWebPage object, you need to set the size of
1711     the viewport by calling setViewportSize(). Then, you invoke the main
1712     frame's render function (QWebFrame::render()). An example of this
1713     is shown in the code snippet below.
1714 
1715     Suppose we have a \c Thumbnail class as follows:
1716 
1717     \snippet webkitsnippets/webpage/main.cpp 0
1718 
1719     The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1720     object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1721     \c render().
1722 
1723     \snippet webkitsnippets/webpage/main.cpp 1
1724 
1725     The \c render() function shows how we can paint a thumbnail using a
1726     QWebPage object.
1727 
1728     \snippet webkitsnippets/webpage/main.cpp 2
1729 
1730     We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1731     then we instantiate a QImage object, \c image, with the same size as our
1732     \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1733     as a parameter to \c painter. Next, we render the contents of the main
1734     frame and its subframes into \c painter. Finally, we save the scaled image.
1735 
1736     \sa QWebFrame
1737 */
1738 
1739 /*!
1740     Constructs an empty QWebPage with parent \a parent.
1741 */
QWebPage(QObject * parent)1742 QWebPage::QWebPage(QObject *parent)
1743     : QObject(parent)
1744     , d(new QWebPagePrivate(this))
1745 {
1746     setView(qobject_cast<QWidget *>(parent));
1747 
1748     connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1749 #ifndef NDEBUG
1750     connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1751 #endif
1752 }
1753 
1754 /*!
1755     Destroys the web page.
1756 */
~QWebPage()1757 QWebPage::~QWebPage()
1758 {
1759     d->createMainFrame();
1760     FrameLoader *loader = d->mainFrame->d->frame->loader();
1761     if (loader)
1762         loader->detachFromParent();
1763     if (d->inspector) {
1764         // Since we have to delete an internal inspector,
1765         // call setInspector(0) directly to prevent potential crashes
1766         if (d->inspectorIsInternalOnly)
1767             d->setInspector(0);
1768         else
1769             d->inspector->setPage(0);
1770     }
1771     delete d;
1772 }
1773 
1774 /*!
1775     Returns the main frame of the page.
1776 
1777     The main frame provides access to the hierarchy of sub-frames and is also needed if you
1778     want to explicitly render a web page into a given painter.
1779 
1780     \sa currentFrame()
1781 */
mainFrame() const1782 QWebFrame *QWebPage::mainFrame() const
1783 {
1784     d->createMainFrame();
1785     return d->mainFrame;
1786 }
1787 
1788 /*!
1789     Returns the frame currently active.
1790 
1791     \sa mainFrame(), frameCreated()
1792 */
currentFrame() const1793 QWebFrame *QWebPage::currentFrame() const
1794 {
1795     d->createMainFrame();
1796     return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame();
1797 }
1798 
1799 
1800 /*!
1801     \since 4.6
1802 
1803     Returns the frame at the given point \a pos.
1804 
1805     \sa mainFrame(), currentFrame()
1806 */
frameAt(const QPoint & pos) const1807 QWebFrame* QWebPage::frameAt(const QPoint& pos) const
1808 {
1809     QWebFrame* webFrame = mainFrame();
1810     if (!webFrame->geometry().contains(pos))
1811         return 0;
1812     QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
1813     return hitTestResult.frame();
1814 }
1815 
1816 /*!
1817     Returns a pointer to the view's history of navigated web pages.
1818 */
history() const1819 QWebHistory *QWebPage::history() const
1820 {
1821     d->createMainFrame();
1822     return &d->history;
1823 }
1824 
1825 /*!
1826     Sets the \a view that is associated with the web page.
1827 
1828     \sa view()
1829 */
setView(QWidget * view)1830 void QWebPage::setView(QWidget *view)
1831 {
1832     if (this->view() != view) {
1833         d->view = view;
1834         if (!view) {
1835             delete d->client;
1836             d->client = 0;
1837         } else {
1838             if (!d->client)
1839                 d->client = new QWebPageWidgetClient(view);
1840             else
1841                 static_cast<QWebPageWidgetClient*>(d->client)->view = view;
1842         }
1843         setViewportSize(view ? view->size() : QSize(0, 0));
1844     }
1845 }
1846 
1847 /*!
1848     Returns the view widget that is associated with the web page.
1849 
1850     \sa setView()
1851 */
view() const1852 QWidget *QWebPage::view() const
1853 {
1854 #if QT_VERSION < 0x040600
1855     return d->view;
1856 #else
1857     return d->view.data();
1858 #endif
1859 }
1860 
1861 /*!
1862     This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
1863 
1864     For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
1865 
1866     The default implementation prints nothing.
1867 */
javaScriptConsoleMessage(const QString & message,int lineNumber,const QString & sourceID)1868 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
1869 {
1870     Q_UNUSED(message)
1871     Q_UNUSED(lineNumber)
1872     Q_UNUSED(sourceID)
1873 }
1874 
1875 /*!
1876     This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
1877     the message \a msg.
1878 
1879     The default implementation shows the message, \a msg, with QMessageBox::information.
1880 */
javaScriptAlert(QWebFrame * frame,const QString & msg)1881 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
1882 {
1883     Q_UNUSED(frame)
1884 #ifndef QT_NO_MESSAGEBOX
1885     QMessageBox::information(view(), tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Ok);
1886 #endif
1887 }
1888 
1889 /*!
1890     This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
1891     with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
1892 
1893     The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1894 */
javaScriptConfirm(QWebFrame * frame,const QString & msg)1895 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
1896 {
1897     Q_UNUSED(frame)
1898 #ifdef QT_NO_MESSAGEBOX
1899     return true;
1900 #else
1901     return QMessageBox::Yes == QMessageBox::information(view(), tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Yes, QMessageBox::No);
1902 #endif
1903 }
1904 
1905 /*!
1906     This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
1907     The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
1908 
1909     If the prompt was cancelled by the user the implementation should return false; otherwise the
1910     result should be written to \a result and true should be returned. If the prompt was not cancelled by the
1911     user, the implementation should return true and the result string must not be null.
1912 
1913     The default implementation uses QInputDialog::getText.
1914 */
javaScriptPrompt(QWebFrame * frame,const QString & msg,const QString & defaultValue,QString * result)1915 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
1916 {
1917     Q_UNUSED(frame)
1918     bool ok = false;
1919 #ifndef QT_NO_INPUTDIALOG
1920     QString x = QInputDialog::getText(view(), tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QLineEdit::Normal, defaultValue, &ok);
1921     if (ok && result)
1922         *result = x;
1923 #endif
1924     return ok;
1925 }
1926 
1927 /*!
1928     \fn bool QWebPage::shouldInterruptJavaScript()
1929     \since 4.6
1930     This function is called when a JavaScript program is running for a long period of time.
1931 
1932     If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
1933 
1934     The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1935 
1936     \warning Because of binary compatibility constraints, this function is not virtual. If you want to
1937     provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript()
1938     slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
1939 */
shouldInterruptJavaScript()1940 bool QWebPage::shouldInterruptJavaScript()
1941 {
1942 #ifdef QT_NO_MESSAGEBOX
1943     return false;
1944 #else
1945     return QMessageBox::Yes == QMessageBox::information(view(), tr("JavaScript Problem - %1").arg(mainFrame()->url().host()), tr("The script on this page appears to have a problem. Do you want to stop the script?"), QMessageBox::Yes, QMessageBox::No);
1946 #endif
1947 }
1948 
1949 /*!
1950     This function is called whenever WebKit wants to create a new window of the given \a type, for
1951     example when a JavaScript program requests to open a document in a new window.
1952 
1953     If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
1954 
1955     If the view associated with the web page is a QWebView object, then the default implementation forwards
1956     the request to QWebView's createWindow() function; otherwise it returns a null pointer.
1957 
1958     If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
1959 
1960     \sa acceptNavigationRequest()
1961 */
createWindow(WebWindowType type)1962 QWebPage *QWebPage::createWindow(WebWindowType type)
1963 {
1964     QWebView *webView = qobject_cast<QWebView *>(view());
1965     if (webView) {
1966         QWebView *newView = webView->createWindow(type);
1967         if (newView)
1968             return newView->page();
1969     }
1970     return 0;
1971 }
1972 
1973 /*!
1974     This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin".
1975     The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and
1976     child elements to configure the embeddable object.
1977 */
createPlugin(const QString & classid,const QUrl & url,const QStringList & paramNames,const QStringList & paramValues)1978 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
1979 {
1980     Q_UNUSED(classid)
1981     Q_UNUSED(url)
1982     Q_UNUSED(paramNames)
1983     Q_UNUSED(paramValues)
1984     return 0;
1985 }
1986 
frameLoadRequest(const QUrl & url,WebCore::Frame * frame)1987 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
1988 {
1989     WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer());
1990     return WebCore::FrameLoadRequest(rr);
1991 }
1992 
openNewWindow(const QUrl & url,WebCore::Frame * frame)1993 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
1994 {
1995     if (Page* oldPage = frame->page()) {
1996         WindowFeatures features;
1997         if (Page* newPage = oldPage->chrome()->createWindow(frame,
1998                 frameLoadRequest(url, frame), features))
1999             newPage->chrome()->show();
2000     }
2001 }
2002 
2003 /*!
2004     This function can be called to trigger the specified \a action.
2005     It is also called by QtWebKit if the user triggers the action, for example
2006     through a context menu item.
2007 
2008     If \a action is a checkable action then \a checked specified whether the action
2009     is toggled or not.
2010 
2011     \sa action()
2012 */
triggerAction(WebAction action,bool)2013 void QWebPage::triggerAction(WebAction action, bool)
2014 {
2015     WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2016     if (!frame)
2017         return;
2018     WebCore::Editor *editor = frame->editor();
2019     const char *command = 0;
2020 
2021     switch (action) {
2022         case OpenLink:
2023             if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
2024                 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
2025                 targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
2026                                                                   /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0,
2027                                                                   /*FormState*/ 0, SendReferrer);
2028                 break;
2029             }
2030             // fall through
2031         case OpenLinkInNewWindow:
2032             openNewWindow(d->hitTestResult.linkUrl(), frame);
2033             break;
2034         case OpenFrameInNewWindow: {
2035             KURL url = frame->loader()->documentLoader()->unreachableURL();
2036             if (url.isEmpty())
2037                 url = frame->loader()->documentLoader()->url();
2038             openNewWindow(url, frame);
2039             break;
2040         }
2041         case CopyLinkToClipboard: {
2042 #if defined(Q_WS_X11)
2043             bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
2044             Pasteboard::generalPasteboard()->setSelectionMode(true);
2045             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2046             Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
2047 #endif
2048             editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2049             break;
2050         }
2051         case OpenImageInNewWindow:
2052             openNewWindow(d->hitTestResult.imageUrl(), frame);
2053             break;
2054         case DownloadImageToDisk:
2055             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
2056             break;
2057         case DownloadLinkToDisk:
2058             frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
2059             break;
2060 #ifndef QT_NO_CLIPBOARD
2061         case CopyImageToClipboard:
2062             QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
2063             break;
2064 #endif
2065         case Back:
2066             d->page->goBack();
2067             break;
2068         case Forward:
2069             d->page->goForward();
2070             break;
2071         case Stop:
2072             mainFrame()->d->frame->loader()->stopForUserCancel();
2073             break;
2074         case Reload:
2075             mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false);
2076             break;
2077         case ReloadAndBypassCache:
2078             mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true);
2079             break;
2080         case SetTextDirectionDefault:
2081             editor->setBaseWritingDirection(NaturalWritingDirection);
2082             break;
2083         case SetTextDirectionLeftToRight:
2084             editor->setBaseWritingDirection(LeftToRightWritingDirection);
2085             break;
2086         case SetTextDirectionRightToLeft:
2087             editor->setBaseWritingDirection(RightToLeftWritingDirection);
2088             break;
2089         case InspectElement: {
2090 #if ENABLE(INSPECTOR)
2091             if (!d->hitTestResult.isNull()) {
2092                 d->getOrCreateInspector(); // Make sure the inspector is created
2093                 d->inspector->show(); // The inspector is expected to be shown on inspection
2094                 d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
2095             }
2096 #endif
2097             break;
2098         }
2099         default:
2100             command = QWebPagePrivate::editorCommandForWebActions(action);
2101             break;
2102     }
2103 
2104     if (command)
2105         editor->command(command).execute();
2106 }
2107 
viewportSize() const2108 QSize QWebPage::viewportSize() const
2109 {
2110     if (d->mainFrame && d->mainFrame->d->frame->view())
2111         return d->mainFrame->d->frame->view()->frameRect().size();
2112 
2113     return d->viewportSize;
2114 }
2115 
2116 /*!
2117     \property QWebPage::viewportSize
2118     \brief the size of the viewport
2119 
2120     The size affects for example the visibility of scrollbars
2121     if the document is larger than the viewport.
2122 
2123     By default, for a newly-created Web page, this property contains a size with
2124     zero width and height.
2125 */
setViewportSize(const QSize & size) const2126 void QWebPage::setViewportSize(const QSize &size) const
2127 {
2128     d->viewportSize = size;
2129 
2130     QWebFrame *frame = mainFrame();
2131     if (frame->d->frame && frame->d->frame->view()) {
2132         WebCore::FrameView* view = frame->d->frame->view();
2133         view->setFrameRect(QRect(QPoint(0, 0), size));
2134         view->forceLayout();
2135         view->adjustViewSize();
2136     }
2137 }
2138 
preferredContentsSize() const2139 QSize QWebPage::preferredContentsSize() const
2140 {
2141     QWebFrame* frame = d->mainFrame;
2142     if (frame) {
2143         WebCore::FrameView* view = frame->d->frame->view();
2144         if (view && view->useFixedLayout())
2145             return d->mainFrame->d->frame->view()->fixedLayoutSize();
2146     }
2147 
2148     return d->fixedLayoutSize;
2149 }
2150 
2151 /*!
2152     \property QWebPage::preferredContentsSize
2153     \since 4.6
2154     \brief the size of the fixed layout
2155 
2156     The size affects the layout of the page in the viewport.  If set to a fixed size of
2157     1024x768 for example then webkit will layout the page as if the viewport were that size
2158     rather than something different.
2159 */
setPreferredContentsSize(const QSize & size) const2160 void QWebPage::setPreferredContentsSize(const QSize &size) const
2161 {
2162     d->fixedLayoutSize = size;
2163 
2164     QWebFrame *frame = mainFrame();
2165     if (frame->d->frame && frame->d->frame->view()) {
2166         WebCore::FrameView* view = frame->d->frame->view();
2167 
2168         if (size.isValid()) {
2169             view->setUseFixedLayout(true);
2170             view->setFixedLayoutSize(size);
2171             view->forceLayout();
2172         } else if (view->useFixedLayout()) {
2173             view->setUseFixedLayout(false);
2174             view->forceLayout();
2175         }
2176     }
2177 }
2178 
2179 /*!
2180     \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2181 
2182     This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
2183     the specified navigation type \a type.
2184 
2185     If \a frame is a null pointer then navigation to a new window is requested. If the request is
2186     accepted createWindow() will be called.
2187 
2188     The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
2189     to let QWebPage handle the navigation itself.
2190 
2191     \sa createWindow()
2192 */
acceptNavigationRequest(QWebFrame * frame,const QNetworkRequest & request,QWebPage::NavigationType type)2193 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2194 {
2195     Q_UNUSED(frame)
2196     if (type == NavigationTypeLinkClicked) {
2197         switch (d->linkPolicy) {
2198             case DontDelegateLinks:
2199                 return true;
2200 
2201             case DelegateExternalLinks:
2202                 if (WebCore::SecurityOrigin::shouldTreatURLSchemeAsLocal(request.url().scheme()))
2203                     return true;
2204                 emit linkClicked(request.url());
2205                 return false;
2206 
2207             case DelegateAllLinks:
2208                 emit linkClicked(request.url());
2209                 return false;
2210         }
2211     }
2212     return true;
2213 }
2214 
2215 /*!
2216     \property QWebPage::selectedText
2217     \brief the text currently selected
2218 
2219     By default, this property contains an empty string.
2220 
2221     \sa selectionChanged()
2222 */
selectedText() const2223 QString QWebPage::selectedText() const
2224 {
2225     d->createMainFrame();
2226     return d->page->focusController()->focusedOrMainFrame()->selectedText();
2227 }
2228 
2229 /*!
2230    Returns a QAction for the specified WebAction \a action.
2231 
2232    The action is owned by the QWebPage but you can customize the look by
2233    changing its properties.
2234 
2235    QWebPage also takes care of implementing the action, so that upon
2236    triggering the corresponding action is performed on the page.
2237 
2238    \sa triggerAction()
2239 */
action(WebAction action) const2240 QAction *QWebPage::action(WebAction action) const
2241 {
2242     if (action == QWebPage::NoWebAction) return 0;
2243     if (d->actions[action])
2244         return d->actions[action];
2245 
2246     QString text;
2247     QIcon icon;
2248     QStyle *style = view() ? view()->style() : qApp->style();
2249     bool checkable = false;
2250 
2251     switch (action) {
2252         case OpenLink:
2253             text = contextMenuItemTagOpenLink();
2254             break;
2255         case OpenLinkInNewWindow:
2256             text = contextMenuItemTagOpenLinkInNewWindow();
2257             break;
2258         case OpenFrameInNewWindow:
2259             text = contextMenuItemTagOpenFrameInNewWindow();
2260             break;
2261 
2262         case DownloadLinkToDisk:
2263             text = contextMenuItemTagDownloadLinkToDisk();
2264             break;
2265         case CopyLinkToClipboard:
2266             text = contextMenuItemTagCopyLinkToClipboard();
2267             break;
2268 
2269         case OpenImageInNewWindow:
2270             text = contextMenuItemTagOpenImageInNewWindow();
2271             break;
2272         case DownloadImageToDisk:
2273             text = contextMenuItemTagDownloadImageToDisk();
2274             break;
2275         case CopyImageToClipboard:
2276             text = contextMenuItemTagCopyImageToClipboard();
2277             break;
2278 
2279         case Back:
2280             text = contextMenuItemTagGoBack();
2281             icon = style->standardIcon(QStyle::SP_ArrowBack);
2282             break;
2283         case Forward:
2284             text = contextMenuItemTagGoForward();
2285             icon = style->standardIcon(QStyle::SP_ArrowForward);
2286             break;
2287         case Stop:
2288             text = contextMenuItemTagStop();
2289             icon = style->standardIcon(QStyle::SP_BrowserStop);
2290             break;
2291         case Reload:
2292             text = contextMenuItemTagReload();
2293             icon = style->standardIcon(QStyle::SP_BrowserReload);
2294             break;
2295 
2296         case Cut:
2297             text = contextMenuItemTagCut();
2298             break;
2299         case Copy:
2300             text = contextMenuItemTagCopy();
2301             break;
2302         case Paste:
2303             text = contextMenuItemTagPaste();
2304             break;
2305 #ifndef QT_NO_UNDOSTACK
2306         case Undo: {
2307             QAction *a = undoStack()->createUndoAction(d->q);
2308             d->actions[action] = a;
2309             return a;
2310         }
2311         case Redo: {
2312             QAction *a = undoStack()->createRedoAction(d->q);
2313             d->actions[action] = a;
2314             return a;
2315         }
2316 #endif // QT_NO_UNDOSTACK
2317         case MoveToNextChar:
2318             text = tr("Move the cursor to the next character");
2319             break;
2320         case MoveToPreviousChar:
2321             text = tr("Move the cursor to the previous character");
2322             break;
2323         case MoveToNextWord:
2324             text = tr("Move the cursor to the next word");
2325             break;
2326         case MoveToPreviousWord:
2327             text = tr("Move the cursor to the previous word");
2328             break;
2329         case MoveToNextLine:
2330             text = tr("Move the cursor to the next line");
2331             break;
2332         case MoveToPreviousLine:
2333             text = tr("Move the cursor to the previous line");
2334             break;
2335         case MoveToStartOfLine:
2336             text = tr("Move the cursor to the start of the line");
2337             break;
2338         case MoveToEndOfLine:
2339             text = tr("Move the cursor to the end of the line");
2340             break;
2341         case MoveToStartOfBlock:
2342             text = tr("Move the cursor to the start of the block");
2343             break;
2344         case MoveToEndOfBlock:
2345             text = tr("Move the cursor to the end of the block");
2346             break;
2347         case MoveToStartOfDocument:
2348             text = tr("Move the cursor to the start of the document");
2349             break;
2350         case MoveToEndOfDocument:
2351             text = tr("Move the cursor to the end of the document");
2352             break;
2353         case SelectAll:
2354             text = tr("Select all");
2355             break;
2356         case SelectNextChar:
2357             text = tr("Select to the next character");
2358             break;
2359         case SelectPreviousChar:
2360             text = tr("Select to the previous character");
2361             break;
2362         case SelectNextWord:
2363             text = tr("Select to the next word");
2364             break;
2365         case SelectPreviousWord:
2366             text = tr("Select to the previous word");
2367             break;
2368         case SelectNextLine:
2369             text = tr("Select to the next line");
2370             break;
2371         case SelectPreviousLine:
2372             text = tr("Select to the previous line");
2373             break;
2374         case SelectStartOfLine:
2375             text = tr("Select to the start of the line");
2376             break;
2377         case SelectEndOfLine:
2378             text = tr("Select to the end of the line");
2379             break;
2380         case SelectStartOfBlock:
2381             text = tr("Select to the start of the block");
2382             break;
2383         case SelectEndOfBlock:
2384             text = tr("Select to the end of the block");
2385             break;
2386         case SelectStartOfDocument:
2387             text = tr("Select to the start of the document");
2388             break;
2389         case SelectEndOfDocument:
2390             text = tr("Select to the end of the document");
2391             break;
2392         case DeleteStartOfWord:
2393             text = tr("Delete to the start of the word");
2394             break;
2395         case DeleteEndOfWord:
2396             text = tr("Delete to the end of the word");
2397             break;
2398 
2399         case SetTextDirectionDefault:
2400             text = contextMenuItemTagDefaultDirection();
2401             break;
2402         case SetTextDirectionLeftToRight:
2403             text = contextMenuItemTagLeftToRight();
2404             checkable = true;
2405             break;
2406         case SetTextDirectionRightToLeft:
2407             text = contextMenuItemTagRightToLeft();
2408             checkable = true;
2409             break;
2410 
2411         case ToggleBold:
2412             text = contextMenuItemTagBold();
2413             checkable = true;
2414             break;
2415         case ToggleItalic:
2416             text = contextMenuItemTagItalic();
2417             checkable = true;
2418             break;
2419         case ToggleUnderline:
2420             text = contextMenuItemTagUnderline();
2421             checkable = true;
2422             break;
2423 
2424         case InspectElement:
2425             text = contextMenuItemTagInspectElement();
2426             break;
2427 
2428         case InsertParagraphSeparator:
2429             text = tr("Insert a new paragraph");
2430             break;
2431         case InsertLineSeparator:
2432             text = tr("Insert a new line");
2433             break;
2434 
2435         case PasteAndMatchStyle:
2436             text = tr("Paste and Match Style");
2437             break;
2438         case RemoveFormat:
2439             text = tr("Remove formatting");
2440             break;
2441 
2442         case ToggleStrikethrough:
2443             text = tr("Strikethrough");
2444             checkable = true;
2445             break;
2446         case ToggleSubscript:
2447             text = tr("Subscript");
2448             checkable = true;
2449             break;
2450         case ToggleSuperscript:
2451             text = tr("Superscript");
2452             checkable = true;
2453             break;
2454         case InsertUnorderedList:
2455             text = tr("Insert Bulleted List");
2456             checkable = true;
2457             break;
2458         case InsertOrderedList:
2459             text = tr("Insert Numbered List");
2460             checkable = true;
2461             break;
2462         case Indent:
2463             text = tr("Indent");
2464             break;
2465         case Outdent:
2466             text = tr("Outdent");
2467             break;
2468         case AlignCenter:
2469             text = tr("Center");
2470             break;
2471         case AlignJustified:
2472             text = tr("Justify");
2473             break;
2474         case AlignLeft:
2475             text = tr("Align Left");
2476             break;
2477         case AlignRight:
2478             text = tr("Align Right");
2479             break;
2480 
2481         case NoWebAction:
2482             return 0;
2483     }
2484 
2485     if (text.isEmpty())
2486         return 0;
2487 
2488     QAction *a = new QAction(d->q);
2489     a->setText(text);
2490     a->setData(action);
2491     a->setCheckable(checkable);
2492     a->setIcon(icon);
2493 
2494     connect(a, SIGNAL(triggered(bool)),
2495             this, SLOT(_q_webActionTriggered(bool)));
2496 
2497     d->actions[action] = a;
2498     d->updateAction(action);
2499     return a;
2500 }
2501 
2502 /*!
2503     \property QWebPage::modified
2504     \brief whether the page contains unsubmitted form data
2505 
2506     By default, this property is false.
2507 */
isModified() const2508 bool QWebPage::isModified() const
2509 {
2510 #ifdef QT_NO_UNDOSTACK
2511     return false;
2512 #else
2513     if (!d->undoStack)
2514         return false;
2515     return d->undoStack->canUndo();
2516 #endif // QT_NO_UNDOSTACK
2517 }
2518 
2519 #ifndef QT_NO_UNDOSTACK
2520 /*!
2521     Returns a pointer to the undo stack used for editable content.
2522 */
undoStack() const2523 QUndoStack *QWebPage::undoStack() const
2524 {
2525     if (!d->undoStack)
2526         d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
2527 
2528     return d->undoStack;
2529 }
2530 #endif // QT_NO_UNDOSTACK
2531 
2532 /*! \reimp
2533 */
event(QEvent * ev)2534 bool QWebPage::event(QEvent *ev)
2535 {
2536     switch (ev->type()) {
2537     case QEvent::Timer:
2538         d->timerEvent(static_cast<QTimerEvent*>(ev));
2539         break;
2540     case QEvent::MouseMove:
2541         d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
2542         break;
2543     case QEvent::GraphicsSceneMouseMove:
2544         d->mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2545         break;
2546     case QEvent::MouseButtonPress:
2547         d->mousePressEvent(static_cast<QMouseEvent*>(ev));
2548         break;
2549     case QEvent::GraphicsSceneMousePress:
2550         d->mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2551         break;
2552     case QEvent::MouseButtonDblClick:
2553         d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
2554         break;
2555     case QEvent::GraphicsSceneMouseDoubleClick:
2556         d->mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2557         break;
2558     case QEvent::MouseButtonRelease:
2559         d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
2560         break;
2561     case QEvent::GraphicsSceneMouseRelease:
2562         d->mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
2563         break;
2564 #ifndef QT_NO_CONTEXTMENU
2565     case QEvent::ContextMenu:
2566         d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos());
2567         break;
2568     case QEvent::GraphicsSceneContextMenu:
2569         d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos());
2570         break;
2571 #endif
2572 #ifndef QT_NO_WHEELEVENT
2573     case QEvent::Wheel:
2574         d->wheelEvent(static_cast<QWheelEvent*>(ev));
2575         break;
2576     case QEvent::GraphicsSceneWheel:
2577         d->wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(ev));
2578         break;
2579 #endif
2580     case QEvent::KeyPress:
2581         d->keyPressEvent(static_cast<QKeyEvent*>(ev));
2582         break;
2583     case QEvent::KeyRelease:
2584         d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
2585         break;
2586     case QEvent::FocusIn:
2587         d->focusInEvent(static_cast<QFocusEvent*>(ev));
2588         break;
2589     case QEvent::FocusOut:
2590         d->focusOutEvent(static_cast<QFocusEvent*>(ev));
2591         break;
2592 #ifndef QT_NO_DRAGANDDROP
2593     case QEvent::DragEnter:
2594         d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
2595         break;
2596     case QEvent::GraphicsSceneDragEnter:
2597         d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2598         break;
2599     case QEvent::DragLeave:
2600         d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
2601         break;
2602     case QEvent::GraphicsSceneDragLeave:
2603         d->dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2604         break;
2605     case QEvent::DragMove:
2606         d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
2607         break;
2608     case QEvent::GraphicsSceneDragMove:
2609         d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2610         break;
2611     case QEvent::Drop:
2612         d->dropEvent(static_cast<QDropEvent*>(ev));
2613         break;
2614     case QEvent::GraphicsSceneDrop:
2615         d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2616         break;
2617 #endif
2618     case QEvent::InputMethod:
2619         d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
2620     case QEvent::ShortcutOverride:
2621         d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
2622         break;
2623     case QEvent::Leave:
2624         d->leaveEvent(ev);
2625         break;
2626 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
2627     case QEvent::TouchBegin:
2628     case QEvent::TouchUpdate:
2629     case QEvent::TouchEnd:
2630         d->touchEvent(static_cast<QTouchEvent*>(ev));
2631         break;
2632 #endif
2633     default:
2634         return QObject::event(ev);
2635     }
2636 
2637     return true;
2638 }
2639 
2640 /*!
2641     Similar to QWidget::focusNextPrevChild it focuses the next focusable web element
2642     if \a next is true; otherwise the previous element is focused.
2643 
2644     Returns true if it can find a new focusable element, or false if it can't.
2645 */
focusNextPrevChild(bool next)2646 bool QWebPage::focusNextPrevChild(bool next)
2647 {
2648     QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
2649     d->keyPressEvent(&ev);
2650     bool hasFocusedNode = false;
2651     Frame *frame = d->page->focusController()->focusedFrame();
2652     if (frame) {
2653         Document *document = frame->document();
2654         hasFocusedNode = document && document->focusedNode();
2655     }
2656     //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
2657     return hasFocusedNode;
2658 }
2659 
2660 /*!
2661     \property QWebPage::contentEditable
2662     \brief whether the content in this QWebPage is editable or not
2663     \since 4.5
2664 
2665     If this property is enabled the contents of the page can be edited by the user through a visible
2666     cursor. If disabled (the default) only HTML elements in the web page with their
2667     \c{contenteditable} attribute set are editable.
2668 */
setContentEditable(bool editable)2669 void QWebPage::setContentEditable(bool editable)
2670 {
2671     if (d->editable != editable) {
2672         d->editable = editable;
2673         d->page->setTabKeyCyclesThroughElements(!editable);
2674         if (d->mainFrame) {
2675             WebCore::Frame* frame = d->mainFrame->d->frame;
2676             if (editable) {
2677                 frame->applyEditingStyleToBodyElement();
2678                 // FIXME: mac port calls this if there is no selectedDOMRange
2679                 //frame->setSelectionFromNone();
2680             } else
2681                 frame->removeEditingStyleFromBodyElement();
2682         }
2683 
2684         d->updateEditorActions();
2685     }
2686 }
2687 
isContentEditable() const2688 bool QWebPage::isContentEditable() const
2689 {
2690     return d->editable;
2691 }
2692 
2693 /*!
2694     \property QWebPage::forwardUnsupportedContent
2695     \brief whether QWebPage should forward unsupported content
2696 
2697     If enabled, the unsupportedContent() signal is emitted with a network reply that
2698     can be used to read the content.
2699 
2700     If disabled, the download of such content is aborted immediately.
2701 
2702     By default unsupported content is not forwarded.
2703 */
2704 
setForwardUnsupportedContent(bool forward)2705 void QWebPage::setForwardUnsupportedContent(bool forward)
2706 {
2707     d->forwardUnsupportedContent = forward;
2708 }
2709 
forwardUnsupportedContent() const2710 bool QWebPage::forwardUnsupportedContent() const
2711 {
2712     return d->forwardUnsupportedContent;
2713 }
2714 
2715 /*!
2716     \property QWebPage::linkDelegationPolicy
2717     \brief how QWebPage should delegate the handling of links through the
2718     linkClicked() signal
2719 
2720     The default is to delegate no links.
2721 */
2722 
setLinkDelegationPolicy(LinkDelegationPolicy policy)2723 void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
2724 {
2725     d->linkPolicy = policy;
2726 }
2727 
linkDelegationPolicy() const2728 QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
2729 {
2730     return d->linkPolicy;
2731 }
2732 
2733 #ifndef QT_NO_CONTEXTMENU
2734 /*!
2735     Filters the context menu event, \a event, through handlers for scrollbars and
2736     custom event handlers in the web page. Returns true if the event was handled;
2737     otherwise false.
2738 
2739     A web page may swallow a context menu event through a custom event handler, allowing for context
2740     menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
2741     Maps}, for example.
2742 */
swallowContextMenuEvent(QContextMenuEvent * event)2743 bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
2744 {
2745     d->page->contextMenuController()->clearContextMenu();
2746 
2747     if (QWebFrame* webFrame = frameAt(event->pos())) {
2748         Frame* frame = QWebFramePrivate::core(webFrame);
2749         if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).pos()))
2750             return scrollbar->contextMenu(PlatformMouseEvent(event, 1));
2751     }
2752 
2753     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
2754     focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
2755     ContextMenu *menu = d->page->contextMenuController()->contextMenu();
2756     // If the website defines its own handler then sendContextMenuEvent takes care of
2757     // calling/showing it and the context menu pointer will be zero. This is the case
2758     // on maps.google.com for example.
2759 
2760     return !menu;
2761 }
2762 #endif // QT_NO_CONTEXTMENU
2763 
2764 /*!
2765     Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
2766     element the CopyImageToClipboard action is enabled.
2767 */
updatePositionDependentActions(const QPoint & pos)2768 void QWebPage::updatePositionDependentActions(const QPoint &pos)
2769 {
2770     // First we disable all actions, but keep track of which ones were originally enabled.
2771     QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
2772     for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
2773         QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
2774         if (QAction *a = this->action(action)) {
2775             originallyEnabledWebActions.setBit(action, a->isEnabled());
2776             a->setEnabled(false);
2777         }
2778     }
2779 
2780     d->createMainFrame();
2781     WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
2782     HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
2783 
2784     if (result.scrollbar())
2785         d->hitTestResult = QWebHitTestResult();
2786     else
2787         d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
2788     WebCore::ContextMenu menu(result);
2789     menu.populate();
2790 
2791 #if ENABLE(INSPECTOR)
2792     if (d->page->inspectorController()->enabled())
2793         menu.addInspectElementItem();
2794 #endif
2795 
2796     QBitArray visitedWebActions(QWebPage::WebActionCount);
2797 
2798 #ifndef QT_NO_CONTEXTMENU
2799     delete d->currentContextMenu;
2800 
2801     // Then we let createContextMenu() enable the actions that are put into the menu
2802     d->currentContextMenu = d->createContextMenu(&menu, menu.platformDescription(), &visitedWebActions);
2803 #endif // QT_NO_CONTEXTMENU
2804 
2805     // Finally, we restore the original enablement for the actions that were not put into the menu.
2806     originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
2807     for (int i = 0; i < QWebPage::WebActionCount; ++i) {
2808         if (originallyEnabledWebActions.at(i)) {
2809             if (QAction *a = this->action(QWebPage::WebAction(i)))
2810                 a->setEnabled(true);
2811         }
2812     }
2813 
2814     // This whole process ensures that any actions put into to the context menu has the right
2815     // enablement, while also keeping the correct enablement for actions that were left out of
2816     // the menu.
2817 
2818 }
2819 
2820 
2821 
2822 /*!
2823     \enum QWebPage::Extension
2824 
2825     This enum describes the types of extensions that the page can support. Before using these extensions, you
2826     should verify that the extension is supported by calling supportsExtension().
2827 
2828     \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection.
2829     This extension is invoked when the web content requests one or more file names, for example
2830     as a result of the user clicking on a "file upload" button in a HTML form where multiple
2831     file selection is allowed.
2832 
2833     \omitvalue ErrorPageExtension (introduced in Qt 4.6)
2834 */
2835 
2836 /*!
2837     \enum QWebPage::ErrorDomain
2838     \since 4.6
2839     \internal
2840 
2841     \value QtNetwork
2842     \value Http
2843     \value WebKit
2844 */
2845 
2846 /*!
2847     \class QWebPage::ExtensionOption
2848     \since 4.4
2849     \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
2850 
2851     \inmodule QtWebKit
2852 
2853     \sa QWebPage::extension()
2854 */
2855 
2856 /*!
2857     \class QWebPage::ErrorPageExtensionOption
2858     \since 4.6
2859     \brief The ErrorPageExtensionOption class describes the option
2860     for the error page extension.
2861 
2862     \inmodule QtWebKit
2863 
2864     The ErrorPageExtensionOption class holds the \a url for which an error occoured as well as
2865     the associated \a frame.
2866 
2867     The error itself is reported by an error \a domain, the \a error code as well as \a errorString.
2868 
2869     \sa QWebPage::ErrorPageExtensionReturn
2870 */
2871 
2872 /*!
2873     \class QWebPage::ErrorPageExtensionReturn
2874     \since 4.6
2875     \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the
2876     frame for which the error occured.
2877 
2878     \inmodule QtWebKit
2879 
2880     The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are
2881     optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which
2882     is assumed to be UTF-8 if not indicated otherwise.
2883 
2884     The error page is stored in the \a content byte array, as HTML content. In order to convert a
2885     QString to a byte array, the QString::toUtf8() method can be used.
2886 
2887     External objects such as stylesheets or images referenced in the HTML are located relative to
2888     \a baseUrl.
2889 
2890     \sa QWebPage::ErrorPageExtensionOption, QString::toUtf8()
2891 */
2892 
2893 /*!
2894     \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn()
2895 
2896     Constructs a new error page object.
2897 */
2898 
2899 /*!
2900     \class QWebPage::ChooseMultipleFilesExtensionOption
2901     \since 4.5
2902     \brief The ChooseMultipleFilesExtensionOption class describes the option
2903     for the multiple files selection extension.
2904 
2905     \inmodule QtWebKit
2906 
2907     The ChooseMultipleFilesExtensionOption class holds the frame originating the request
2908     and the suggested filenames which might be provided.
2909 
2910     \sa QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn
2911 */
2912 
2913 /*!
2914     \class QWebPage::ChooseMultipleFilesExtensionReturn
2915     \since 4.5
2916     \brief The ChooseMultipleFilesExtensionReturn describes the return value
2917     for the multiple files selection extension.
2918 
2919     \inmodule QtWebKit
2920 
2921     The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user
2922     when the extension is invoked.
2923 
2924     \sa QWebPage::ChooseMultipleFilesExtensionOption
2925 */
2926 
2927 /*!
2928     This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
2929     argument is provided as input to the extension; the output results can be stored in \a output.
2930 
2931     The behavior of this function is determined by \a extension.
2932 
2933     You can call supportsExtension() to check if an extension is supported by the page.
2934 
2935     Returns true if the extension was called successfully; otherwise returns false.
2936 
2937     \sa supportsExtension(), Extension
2938 */
extension(Extension extension,const ExtensionOption * option,ExtensionReturn * output)2939 bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
2940 {
2941 #ifndef QT_NO_FILEDIALOG
2942     if (extension == ChooseMultipleFilesExtension) {
2943         // FIXME: do not ignore suggestedFiles
2944         QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames;
2945         QStringList names = QFileDialog::getOpenFileNames(view(), QString::null);
2946         static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
2947         return true;
2948     }
2949 #endif
2950 
2951     return false;
2952 }
2953 
2954 /*!
2955     This virtual function returns true if the web page supports \a extension; otherwise false is returned.
2956 
2957     \sa extension()
2958 */
supportsExtension(Extension extension) const2959 bool QWebPage::supportsExtension(Extension extension) const
2960 {
2961 #ifndef QT_NO_FILEDIALOG
2962     return extension == ChooseMultipleFilesExtension;
2963 #else
2964     Q_UNUSED(extension);
2965     return false;
2966 #endif
2967 }
2968 
2969 /*!
2970     Finds the specified string, \a subString, in the page, using the given \a options.
2971 
2972     If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
2973     that exist in the page. All subsequent calls will extend the highlight, rather than
2974     replace it, with occurrences of the new string.
2975 
2976     If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
2977     and all subsequent calls will replace the current occurrence with the next one.
2978 
2979     To clear the selection, just pass an empty string.
2980 
2981     Returns true if \a subString was found; otherwise returns false.
2982 */
findText(const QString & subString,FindFlags options)2983 bool QWebPage::findText(const QString &subString, FindFlags options)
2984 {
2985     ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
2986     if (options & FindCaseSensitively)
2987         caseSensitivity = ::TextCaseSensitive;
2988 
2989     if (options & HighlightAllOccurrences) {
2990         if (subString.isEmpty()) {
2991             d->page->unmarkAllTextMatches();
2992             return true;
2993         } else
2994             return d->page->markAllMatchesForText(subString, caseSensitivity, true, 0);
2995     } else {
2996         ::FindDirection direction = ::FindDirectionForward;
2997         if (options & FindBackward)
2998             direction = ::FindDirectionBackward;
2999 
3000         const bool shouldWrap = options & FindWrapsAroundDocument;
3001 
3002         return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
3003     }
3004 }
3005 
3006 /*!
3007     Returns a pointer to the page's settings object.
3008 
3009     \sa QWebSettings::globalSettings()
3010 */
settings() const3011 QWebSettings *QWebPage::settings() const
3012 {
3013     return d->settings;
3014 }
3015 
3016 /*!
3017     This function is called when the web content requests a file name, for example
3018     as a result of the user clicking on a "file upload" button in a HTML form.
3019 
3020     A suggested filename may be provided in \a suggestedFile. The frame originating the
3021     request is provided as \a parentFrame.
3022 */
chooseFile(QWebFrame * parentFrame,const QString & suggestedFile)3023 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
3024 {
3025     Q_UNUSED(parentFrame)
3026 #ifndef QT_NO_FILEDIALOG
3027     return QFileDialog::getOpenFileName(view(), QString::null, suggestedFile);
3028 #else
3029     return QString::null;
3030 #endif
3031 }
3032 
3033 /*!
3034     Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
3035     QWebPage.
3036 
3037     \note It is currently not supported to change the network access manager after the
3038     QWebPage has used it. The results of doing this are undefined.
3039 
3040     \sa networkAccessManager()
3041 */
setNetworkAccessManager(QNetworkAccessManager * manager)3042 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
3043 {
3044     if (manager == d->networkManager)
3045         return;
3046     if (d->networkManager && d->networkManager->parent() == this)
3047         delete d->networkManager;
3048     d->networkManager = manager;
3049 }
3050 
3051 /*!
3052     Returns the QNetworkAccessManager that is responsible for serving network
3053     requests for this QWebPage.
3054 
3055     \sa setNetworkAccessManager()
3056 */
networkAccessManager() const3057 QNetworkAccessManager *QWebPage::networkAccessManager() const
3058 {
3059     if (!d->networkManager) {
3060         QWebPage *that = const_cast<QWebPage *>(this);
3061         that->d->networkManager = new QNetworkAccessManager(that);
3062     }
3063     return d->networkManager;
3064 }
3065 
3066 /*!
3067     Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
3068     QWebPage.
3069 
3070     Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
3071 
3072     \sa pluginFactory()
3073 */
setPluginFactory(QWebPluginFactory * factory)3074 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
3075 {
3076     d->pluginFactory = factory;
3077 }
3078 
3079 /*!
3080     Returns the QWebPluginFactory that is responsible for creating plugins embedded into
3081     this QWebPage. If no plugin factory is installed a null pointer is returned.
3082 
3083     \sa setPluginFactory()
3084 */
pluginFactory() const3085 QWebPluginFactory *QWebPage::pluginFactory() const
3086 {
3087     return d->pluginFactory;
3088 }
3089 
3090 /*!
3091     This function is called when a user agent for HTTP requests is needed. You can reimplement this
3092     function to dynamically return different user agents for different URLs, based on the \a url parameter.
3093 
3094     The default implementation returns the following value:
3095 
3096     "Mozilla/5.0 (%Platform%; %Security%; %Subplatform%; %Locale%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%"
3097 
3098     In this string the following values are replaced at run-time:
3099     \list
3100     \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system.
3101     \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true.
3102     \o %Locale% is replaced with QLocale::name(). The locale is determined from the view of the QWebPage. If no view is set on the QWebPage,
3103     then a default constructed QLocale is used instead.
3104     \o %WebKitVersion% is the version of WebKit the application was compiled against.
3105     \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
3106     \endlist
3107 */
userAgentForUrl(const QUrl & url) const3108 QString QWebPage::userAgentForUrl(const QUrl& url) const
3109 {
3110     Q_UNUSED(url)
3111     QString ua = QLatin1String("Mozilla/5.0 ("
3112 
3113     // Platform
3114 #ifdef Q_WS_MAC
3115     "Macintosh"
3116 #elif defined Q_WS_QWS
3117     "QtEmbedded"
3118 #elif defined Q_WS_WIN
3119     "Windows"
3120 #elif defined Q_WS_X11
3121     "X11"
3122 #elif defined Q_OS_SYMBIAN
3123     "SymbianOS"
3124 #else
3125     "Unknown"
3126 #endif
3127     // Placeholder for Platform Version
3128     "%1; "
3129 
3130     // Placeholder for security strength (N or U)
3131     "%2; "
3132 
3133     // Subplatform"
3134 #ifdef Q_OS_AIX
3135     "AIX"
3136 #elif defined Q_OS_WIN32
3137     "%3"
3138 #elif defined Q_OS_DARWIN
3139 #ifdef __i386__ || __x86_64__
3140     "Intel Mac OS X"
3141 #else
3142     "PPC Mac OS X"
3143 #endif
3144 
3145 #elif defined Q_OS_BSDI
3146     "BSD"
3147 #elif defined Q_OS_BSD4
3148     "BSD Four"
3149 #elif defined Q_OS_CYGWIN
3150     "Cygwin"
3151 #elif defined Q_OS_DGUX
3152     "DG/UX"
3153 #elif defined Q_OS_DYNIX
3154     "DYNIX/ptx"
3155 #elif defined Q_OS_FREEBSD
3156     "FreeBSD"
3157 #elif defined Q_OS_HPUX
3158     "HP-UX"
3159 #elif defined Q_OS_HURD
3160     "GNU Hurd"
3161 #elif defined Q_OS_IRIX
3162     "SGI Irix"
3163 #elif defined Q_OS_LINUX
3164     "Linux"
3165 #elif defined Q_OS_LYNX
3166     "LynxOS"
3167 #elif defined Q_OS_NETBSD
3168     "NetBSD"
3169 #elif defined Q_OS_OS2
3170     "OS/2"
3171 #elif defined Q_OS_OPENBSD
3172     "OpenBSD"
3173 #elif defined Q_OS_OS2EMX
3174     "OS/2"
3175 #elif defined Q_OS_OSF
3176     "HP Tru64 UNIX"
3177 #elif defined Q_OS_QNX6
3178     "QNX RTP Six"
3179 #elif defined Q_OS_QNX
3180     "QNX"
3181 #elif defined Q_OS_RELIANT
3182     "Reliant UNIX"
3183 #elif defined Q_OS_SCO
3184     "SCO OpenServer"
3185 #elif defined Q_OS_SOLARIS
3186     "Sun Solaris"
3187 #elif defined Q_OS_ULTRIX
3188     "DEC Ultrix"
3189 #elif defined Q_WS_S60
3190     "Series60"
3191 #elif defined Q_OS_UNIX
3192     "UNIX BSD/SYSV system"
3193 #elif defined Q_OS_UNIXWARE
3194     "UnixWare Seven, Open UNIX Eight"
3195 #else
3196     "Unknown"
3197 #endif
3198     // Placeholder for SubPlatform Version
3199     "%4; ");
3200 
3201     // Platform Version
3202     QString osVer;
3203 #ifdef Q_OS_SYMBIAN
3204     QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
3205     switch (symbianVersion) {
3206     case QSysInfo::SV_9_2:
3207         osVer = "/9.2";
3208         break;
3209     case QSysInfo::SV_9_3:
3210         osVer = "/9.3";
3211         break;
3212     case QSysInfo::SV_9_4:
3213         osVer = "/9.4";
3214         break;
3215     default:
3216         osVer = "Unknown";
3217     }
3218 #endif
3219     ua = ua.arg(osVer);
3220 
3221     QChar securityStrength(QLatin1Char('N'));
3222 #if !defined(QT_NO_OPENSSL)
3223     // we could check QSslSocket::supportsSsl() here, but this makes
3224     // OpenSSL, certificates etc being loaded in all cases were QWebPage
3225     // is used. This loading is not needed for non-https.
3226     securityStrength = QLatin1Char('U');
3227     // this may lead to a false positive: We indicate SSL since it is
3228     // compiled in even though supportsSsl() might return false
3229 #endif
3230     ua = ua.arg(securityStrength);
3231 
3232 #if defined Q_OS_WIN32
3233     QString ver;
3234     switch (QSysInfo::WindowsVersion) {
3235         case QSysInfo::WV_32s:
3236             ver = "Windows 3.1";
3237             break;
3238         case QSysInfo::WV_95:
3239             ver = "Windows 95";
3240             break;
3241         case QSysInfo::WV_98:
3242             ver = "Windows 98";
3243             break;
3244         case QSysInfo::WV_Me:
3245             ver = "Windows 98; Win 9x 4.90";
3246             break;
3247         case QSysInfo::WV_NT:
3248             ver = "WinNT4.0";
3249             break;
3250         case QSysInfo::WV_2000:
3251             ver = "Windows NT 5.0";
3252             break;
3253         case QSysInfo::WV_XP:
3254             ver = "Windows NT 5.1";
3255             break;
3256         case QSysInfo::WV_2003:
3257             ver = "Windows NT 5.2";
3258             break;
3259         case QSysInfo::WV_VISTA:
3260             ver = "Windows NT 6.0";
3261             break;
3262 #if QT_VERSION > 0x040500
3263         case QSysInfo::WV_WINDOWS7:
3264             ver = "Windows NT 6.1";
3265             break;
3266 #endif
3267         case QSysInfo::WV_CE:
3268             ver = "Windows CE";
3269             break;
3270         case QSysInfo::WV_CENET:
3271             ver = "Windows CE .NET";
3272             break;
3273         case QSysInfo::WV_CE_5:
3274             ver = "Windows CE 5.x";
3275             break;
3276         case QSysInfo::WV_CE_6:
3277             ver = "Windows CE 6.x";
3278             break;
3279     }
3280     ua = QString(ua).arg(ver);
3281 #endif
3282 
3283     // SubPlatform Version
3284     QString subPlatformVer;
3285 #ifdef Q_OS_SYMBIAN
3286     QSysInfo::S60Version s60Version = QSysInfo::s60Version();
3287     switch (s60Version) {
3288     case QSysInfo::SV_S60_3_1:
3289         subPlatformVer = "/3.1";
3290         break;
3291     case QSysInfo::SV_S60_3_2:
3292         subPlatformVer = "/3.2";
3293         break;
3294     case QSysInfo::SV_S60_5_0:
3295         subPlatformVer = "/5.0";
3296         break;
3297     default:
3298         subPlatformVer = " Unknown";
3299     }
3300 #endif
3301     ua = ua.arg(subPlatformVer);
3302 
3303     // Language
3304     QLocale locale;
3305     if (view())
3306         locale = view()->locale();
3307     QString name = locale.name();
3308     name[2] = QLatin1Char('-');
3309     ua.append(name);
3310     ua.append(QLatin1String(") "));
3311 
3312     // webkit/qt version
3313     ua.append(QString(QLatin1String("AppleWebKit/%1 (KHTML, like Gecko) "))
3314                       .arg(QString(qWebKitVersion())));
3315 
3316     // Application name/version
3317     QString appName = QCoreApplication::applicationName();
3318     if (!appName.isEmpty()) {
3319         ua.append(appName);
3320         QString appVer = QCoreApplication::applicationVersion();
3321         if (!appVer.isEmpty())
3322             ua.append(QLatin1Char('/') + appVer);
3323     } else {
3324         // Qt version
3325         ua.append(QLatin1String("Qt/"));
3326         ua.append(QLatin1String(qVersion()));
3327     }
3328 
3329     ua.append(QString(QLatin1String(" Safari/%1"))
3330                       .arg(qWebKitVersion()));
3331 
3332     return ua;
3333 }
3334 
3335 
_q_onLoadProgressChanged(int)3336 void QWebPagePrivate::_q_onLoadProgressChanged(int)
3337 {
3338     m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
3339     m_bytesReceived = page->progress()->totalBytesReceived();
3340 }
3341 
3342 
3343 /*!
3344     Returns the total number of bytes that were received from the network to render the current page,
3345     including extra content such as embedded images.
3346 
3347     \sa bytesReceived()
3348 */
totalBytes() const3349 quint64 QWebPage::totalBytes() const
3350 {
3351     return d->m_totalBytes;
3352 }
3353 
3354 
3355 /*!
3356     Returns the number of bytes that were received from the network to render the current page.
3357 
3358     \sa totalBytes()
3359 */
bytesReceived() const3360 quint64 QWebPage::bytesReceived() const
3361 {
3362     return d->m_bytesReceived;
3363 }
3364 
3365 /*!
3366     \fn void QWebPage::loadStarted()
3367 
3368     This signal is emitted when a new load of the page is started.
3369 
3370     \sa loadFinished()
3371 */
3372 
3373 /*!
3374     \fn void QWebPage::loadProgress(int progress)
3375 
3376     This signal is emitted when the global progress status changes.
3377     The current value is provided by \a progress and scales from 0 to 100,
3378     which is the default range of QProgressBar.
3379     It accumulates changes from all the child frames.
3380 
3381     \sa bytesReceived()
3382 */
3383 
3384 /*!
3385     \fn void QWebPage::loadFinished(bool ok)
3386 
3387     This signal is emitted when a load of the page is finished.
3388     \a ok will indicate whether the load was successful or any error occurred.
3389 
3390     \sa loadStarted()
3391 */
3392 
3393 /*!
3394     \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
3395 
3396     This signal is emitted when the mouse hovers over a link.
3397 
3398     \a link contains the link url.
3399     \a title is the link element's title, if it is specified in the markup.
3400     \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
3401 
3402     When the mouse leaves the link element the signal is emitted with empty parameters.
3403 
3404     \sa linkClicked()
3405 */
3406 
3407 /*!
3408     \fn void QWebPage::statusBarMessage(const QString& text)
3409 
3410     This signal is emitted when the statusbar \a text is changed by the page.
3411 */
3412 
3413 /*!
3414     \fn void QWebPage::frameCreated(QWebFrame *frame)
3415 
3416     This signal is emitted whenever the page creates a new \a frame.
3417 */
3418 
3419 /*!
3420     \fn void QWebPage::selectionChanged()
3421 
3422     This signal is emitted whenever the selection changes.
3423 
3424     \sa selectedText()
3425 */
3426 
3427 /*!
3428     \fn void QWebPage::contentsChanged()
3429     \since 4.5
3430 
3431     This signal is emitted whenever the text in form elements changes
3432     as well as other editable content.
3433 
3434     \sa contentEditable, QWebFrame::toHtml(), QWebFrame::toPlainText()
3435 */
3436 
3437 /*!
3438     \fn void QWebPage::geometryChangeRequested(const QRect& geom)
3439 
3440     This signal is emitted whenever the document wants to change the position and size of the
3441     page to \a geom. This can happen for example through JavaScript.
3442 */
3443 
3444 /*!
3445     \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
3446 
3447     This signal is emitted whenever this QWebPage should be updated and no view was set.
3448     \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
3449     the mainFrame() and call the render(QPainter*, const QRegion&) method with the
3450     \a dirtyRect as the second parameter.
3451 
3452     \sa mainFrame()
3453     \sa view()
3454 */
3455 
3456 /*!
3457     \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
3458 
3459     This signal is emitted whenever the content given by \a rectToScroll needs
3460     to be scrolled \a dx and \a dy downwards and no view was set.
3461 
3462     \sa view()
3463 */
3464 
3465 /*!
3466     \fn void QWebPage::windowCloseRequested()
3467 
3468     This signal is emitted whenever the page requests the web browser window to be closed,
3469     for example through the JavaScript \c{window.close()} call.
3470 */
3471 
3472 /*!
3473     \fn void QWebPage::printRequested(QWebFrame *frame)
3474 
3475     This signal is emitted whenever the page requests the web browser to print \a frame,
3476     for example through the JavaScript \c{window.print()} call.
3477 
3478     \sa QWebFrame::print(), QPrintPreviewDialog
3479 */
3480 
3481 /*!
3482     \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
3483 
3484     This signal is emitted when WebKit cannot handle a link the user navigated to.
3485 
3486     At signal emission time the meta-data of the QNetworkReply \a reply is available.
3487 
3488     \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
3489 
3490     \sa downloadRequested()
3491 */
3492 
3493 /*!
3494     \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
3495 
3496     This signal is emitted when the user decides to download a link. The url of
3497     the link as well as additional meta-information is contained in \a request.
3498 
3499     \sa unsupportedContent()
3500 */
3501 
3502 /*!
3503     \fn void QWebPage::microFocusChanged()
3504 
3505     This signal is emitted when for example the position of the cursor in an editable form
3506     element changes. It is used inform input methods about the new on-screen position where
3507     the user is able to enter text. This signal is usually connected to QWidget's updateMicroFocus()
3508     slot.
3509 */
3510 
3511 /*!
3512     \fn void QWebPage::linkClicked(const QUrl &url)
3513 
3514     This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
3515     property is set to delegate the link handling for the specified \a url.
3516 
3517     By default no links are delegated and are handled by QWebPage instead.
3518 
3519     \sa linkHovered()
3520 */
3521 
3522 /*!
3523     \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
3524 
3525     This signal is emitted whenever the visibility of the toolbar in a web browser
3526     window that hosts QWebPage should be changed to \a visible.
3527 */
3528 
3529 /*!
3530     \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
3531 
3532     This signal is emitted whenever the visibility of the statusbar in a web browser
3533     window that hosts QWebPage should be changed to \a visible.
3534 */
3535 
3536 /*!
3537     \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
3538 
3539     This signal is emitted whenever the visibility of the menubar in a web browser
3540     window that hosts QWebPage should be changed to \a visible.
3541 */
3542 
3543 /*!
3544     \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
3545     \since 4.5
3546 
3547     This signal is emitted whenever the web site shown in \a frame is asking to store data
3548     to the database \a databaseName and the quota allocated to that web site is exceeded.
3549 */
3550 
3551 /*!
3552   \since 4.5
3553   \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
3554 
3555   This signal is emitted shortly before the history of navigated pages
3556   in \a frame is changed, for example when navigating back in the history.
3557 
3558   The provided QWebHistoryItem, \a item, holds the history entry of the frame before
3559   the change.
3560 
3561   A potential use-case for this signal is to store custom data in
3562   the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
3563 */
3564 
3565 /*!
3566   \since 4.5
3567   \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
3568 
3569   This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
3570 */
3571 
3572 /*!
3573   \fn QWebPagePrivate* QWebPage::handle() const
3574   \internal
3575 */
3576 
3577 #include "moc_qwebpage.cpp"
3578