1/*
2 Copyright (C) 2008, 2009, 2012 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
25#include "InitWebKitQt.h"
26#include "InspectorClientWebPage.h"
27#include "PageClientQt.h"
28#include "QGraphicsWidgetPluginImpl.h"
29#include "QWebUndoCommand.h"
30#include "QWidgetPluginImpl.h"
31#include "QtFallbackWebPopup.h"
32#include "QtPlatformPlugin.h"
33#include "UndoStepQt.h"
34#include "WebEventConversion.h"
35
36#include "qwebframe.h"
37#include "qwebframe_p.h"
38#include "qwebhistory.h"
39#include "qwebinspector.h"
40#include "qwebinspector_p.h"
41#include "qwebkitplatformplugin.h"
42#include "qwebpage_p.h"
43#include "qwebsettings.h"
44#include "qwebview.h"
45
46#include <QAction>
47#include <QApplication>
48#include <QBasicTimer>
49#include <QBitArray>
50#include <QClipboard>
51#include <QColorDialog>
52#include <QDesktopWidget>
53#include <QDragEnterEvent>
54#include <QDragLeaveEvent>
55#include <QDragMoveEvent>
56#include <QDropEvent>
57#include <QFileDialog>
58#include <QGestureEvent>
59#include <QInputDialog>
60#include <QLabel>
61#include <QMenu>
62#include <QMessageBox>
63#include <QNetworkAccessManager>
64#include <QNetworkProxy>
65#include <QNetworkRequest>
66#include <QPainter>
67#include <QScreen>
68#include <QSslSocket>
69#include <QStyle>
70#include <QSysInfo>
71#if USE(QT_MOBILITY_SYSTEMINFO)
72#include <qsysteminfo.h>
73#endif
74#include <QSystemTrayIcon>
75#include <QTextCharFormat>
76#include <QToolTip>
77#include <QTouchEvent>
78#include <QUndoStack>
79#include <QUrl>
80#include <QWindow>
81#if defined(Q_WS_X11)
82#include <QX11Info>
83#endif
84
85#if USE(QT_MULTIMEDIA)
86#include "DefaultFullScreenVideoHandler.h"
87#endif
88
89using namespace WebCore;
90
91// Lookup table mapping QWebPage::WebActions to the associated Editor commands
92static const char* editorCommandWebActions[] =
93{
94 0, // OpenLink,
95
96 0, // OpenLinkInNewWindow,
97 0, // OpenFrameInNewWindow,
98
99 0, // DownloadLinkToDisk,
100 0, // CopyLinkToClipboard,
101
102 0, // OpenImageInNewWindow,
103 0, // DownloadImageToDisk,
104 0, // CopyImageToClipboard,
105
106 0, // Back,
107 0, // Forward,
108 0, // Stop,
109 0, // Reload,
110
111 "Cut", // Cut,
112 "Copy", // Copy,
113 "Paste", // Paste,
114
115 "Undo", // Undo,
116 "Redo", // Redo,
117 "MoveForward", // MoveToNextChar,
118 "MoveBackward", // MoveToPreviousChar,
119 "MoveWordForward", // MoveToNextWord,
120 "MoveWordBackward", // MoveToPreviousWord,
121 "MoveDown", // MoveToNextLine,
122 "MoveUp", // MoveToPreviousLine,
123 "MoveToBeginningOfLine", // MoveToStartOfLine,
124 "MoveToEndOfLine", // MoveToEndOfLine,
125 "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
126 "MoveToEndOfParagraph", // MoveToEndOfBlock,
127 "MoveToBeginningOfDocument", // MoveToStartOfDocument,
128 "MoveToEndOfDocument", // MoveToEndOfDocument,
129 "MoveForwardAndModifySelection", // SelectNextChar,
130 "MoveBackwardAndModifySelection", // SelectPreviousChar,
131 "MoveWordForwardAndModifySelection", // SelectNextWord,
132 "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
133 "MoveDownAndModifySelection", // SelectNextLine,
134 "MoveUpAndModifySelection", // SelectPreviousLine,
135 "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
136 "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
137 "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
138 "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
139 "MoveToBeginningOfDocumentAndModifySelection", // SelectStartOfDocument,
140 "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
141 "DeleteWordBackward", // DeleteStartOfWord,
142 "DeleteWordForward", // DeleteEndOfWord,
143
144 0, // SetTextDirectionDefault,
145 0, // SetTextDirectionLeftToRight,
146 0, // SetTextDirectionRightToLeft,
147
148 "ToggleBold", // ToggleBold,
149 "ToggleItalic", // ToggleItalic,
150 "ToggleUnderline", // ToggleUnderline,
151
152 0, // InspectElement,
153
154 "InsertNewline", // InsertParagraphSeparator
155 "InsertLineBreak", // InsertLineSeparator
156
157 "SelectAll", // SelectAll
158 0, // ReloadAndBypassCache,
159
160 "PasteAndMatchStyle", // PasteAndMatchStyle
161 "RemoveFormat", // RemoveFormat
162 "Strikethrough", // ToggleStrikethrough,
163 "Subscript", // ToggleSubscript
164 "Superscript", // ToggleSuperscript
165 "InsertUnorderedList", // InsertUnorderedList
166 "InsertOrderedList", // InsertOrderedList
167 "Indent", // Indent
168 "Outdent", // Outdent,
169
170 "AlignCenter", // AlignCenter,
171 "AlignJustified", // AlignJustified,
172 "AlignLeft", // AlignLeft,
173 "AlignRight", // AlignRight,
174
175 0, // StopScheduledPageRefresh,
176
177 0, // CopyImageUrlToClipboard,
178
179 0, // OpenLinkInThisWindow,
180
181 0, // DownloadMediaToDisk,
182 0, // CopyMediaUrlToClipboard,
183 0, // ToggleMediaControls,
184 0, // ToggleMediaLoop,
185 0, // ToggleMediaPlayPause,
186 0, // ToggleMediaMute,
187 0, // ToggleVideoFullscreen,
188
189 0, // RequestClose,
190
191 "Unselect", // Unselect,
192
193 0 // WebActionCount
194};
195
196// Lookup the appropriate editor command to use for WebAction \a action
197const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
198{
199 if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
200 return editorCommandWebActions[action];
201 return 0;
202}
203
204QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
205 : q(qq)
206#ifndef QT_NO_UNDOSTACK
207 , undoStack(0)
208#endif
209 , linkPolicy(QWebPage::DontDelegateLinks)
210 , m_viewportSize(QSize(0, 0))
211 , useFixedLayout(false)
212 , window(0)
213 , inspectorFrontend(0)
214 , inspector(0)
215 , inspectorIsInternalOnly(false)
216 , m_lastDropAction(Qt::IgnoreAction)
217{
218 WebKit::initializeWebKitWidgets();
219 initializeWebCorePage();
220 memset(actions, 0, sizeof(actions));
221
222#if ENABLE(NOTIFICATIONS)
223 addNotificationPresenterClient();
224#ifndef QT_NO_SYSTEMTRAYICON
225 if (!hasSystemTrayIcon())
226 setSystemTrayIcon(new QSystemTrayIcon);
227#endif // QT_NO_SYSTEMTRAYICON
228#endif // ENABLE(NOTIFICATIONS)
229
230 qRegisterMetaType<QWebFullScreenRequest>();
231 int fullScreenRequestedIndex = q->metaObject()->indexOfMethod("fullScreenRequested(QWebFullScreenRequest)");
232 Q_ASSERT(fullScreenRequestedIndex != -1);
233 m_fullScreenRequested = q->metaObject()->method(fullScreenRequestedIndex);
234}
235
236void QWebPagePrivate::show()
237{
238 if (!view)
239 return;
240 view->window()->show();
241}
242
243void QWebPagePrivate::setFocus()
244{
245 if (!view)
246 return;
247 view->setFocus();
248}
249
250void QWebPagePrivate::unfocus()
251{
252 if (!view)
253 return;
254 view->clearFocus();
255}
256
257void QWebPagePrivate::setWindowRect(const QRect &rect)
258{
259 emit q->geometryChangeRequested(rect);
260}
261
262QSize QWebPagePrivate::viewportSize() const
263{
264 return q->viewportSize();
265}
266
267QWebPageAdapter *QWebPagePrivate::createWindow(bool dialog)
268{
269 QWebPage *newPage = q->createWindow(dialog ? QWebPage::WebModalDialog : QWebPage::WebBrowserWindow);
270 if (!newPage)
271 return 0;
272 // Make sure the main frame exists, as WebCore expects it when returning from this ChromeClient::createWindow()
273 newPage->d->createMainFrame();
274 return newPage->d;
275}
276
277void QWebPagePrivate::consoleMessageReceived(MessageSource source, MessageLevel level, const QString& message, int lineNumber, const QString& sourceID)
278{
279 q->javaScriptConsoleMessage(message, lineNumber, sourceID);
280 emit q->consoleMessageReceived(QWebPage::MessageSource(source), QWebPage::MessageLevel(level), message, lineNumber, sourceID);
281}
282
283void QWebPagePrivate::javaScriptAlert(QWebFrameAdapter* frame, const QString& msg)
284{
285 q->javaScriptAlert(QWebFramePrivate::kit(frame), msg);
286}
287
288bool QWebPagePrivate::javaScriptConfirm(QWebFrameAdapter* frame, const QString& msg)
289{
290 return q->javaScriptConfirm(QWebFramePrivate::kit(frame), msg);
291}
292
293bool QWebPagePrivate::javaScriptPrompt(QWebFrameAdapter *frame, const QString &msg, const QString &defaultValue, QString *result)
294{
295 return q->javaScriptPrompt(QWebFramePrivate::kit(frame), msg, defaultValue, result);
296}
297
298bool QWebPagePrivate::shouldInterruptJavaScript()
299{
300 return q->shouldInterruptJavaScript();
301}
302
303void QWebPagePrivate::printRequested(QWebFrameAdapter *frame)
304{
305 emit q->printRequested(QWebFramePrivate::kit(frame));
306}
307
308void QWebPagePrivate::databaseQuotaExceeded(QWebFrameAdapter* frame, const QString& databaseName)
309{
310 emit q->databaseQuotaExceeded(QWebFramePrivate::kit(frame), databaseName);
311}
312
313void QWebPagePrivate::applicationCacheQuotaExceeded(QWebSecurityOrigin *origin, quint64 defaultOriginQuota, quint64 c)
314{
315 emit q->applicationCacheQuotaExceeded(origin, defaultOriginQuota, c);
316}
317
318void QWebPagePrivate::setToolTip(const QString &tip)
319{
320#ifndef QT_NO_TOOLTIP
321 if (!view)
322 return;
323
324 if (tip.isEmpty()) {
325 view->setToolTip(QString());
326 QToolTip::hideText();
327 } else {
328 QString dtip = QLatin1String("<p>") + QString(tip).toHtmlEscaped() + QLatin1String("</p>");
329 view->setToolTip(dtip);
330 }
331#else
332 Q_UNUSED(tip);
333#endif
334}
335
336#if USE(QT_MULTIMEDIA)
337QWebFullScreenVideoHandler *QWebPagePrivate::createFullScreenVideoHandler()
338{
339 return new WebKit::DefaultFullScreenVideoHandler;
340}
341#endif
342
343QWebFrameAdapter& QWebPagePrivate::mainFrameAdapter()
344{
345 return *q->mainFrame()->d;
346}
347
348QStringList QWebPagePrivate::chooseFiles(QWebFrameAdapter *frame, bool allowMultiple, const QStringList &suggestedFileNames)
349{
350 if (allowMultiple && q->supportsExtension(QWebPage::ChooseMultipleFilesExtension)) {
351 QWebPage::ChooseMultipleFilesExtensionOption option;
352 option.parentFrame = QWebFramePrivate::kit(frame);
353 option.suggestedFileNames = suggestedFileNames;
354
355 QWebPage::ChooseMultipleFilesExtensionReturn output;
356 q->extension(QWebPage::ChooseMultipleFilesExtension, &option, &output);
357
358 return output.fileNames;
359 }
360 // Single file
361 QStringList result;
362 QString suggestedFile;
363 if (!suggestedFileNames.isEmpty())
364 suggestedFile = suggestedFileNames.first();
365 QString file = q->chooseFile(QWebFramePrivate::kit(frame), suggestedFile);
366 if (!file.isEmpty())
367 result << file;
368 return result;
369}
370
371bool QWebPagePrivate::acceptNavigationRequest(QWebFrameAdapter *frameAdapter, const QNetworkRequest &request, int type)
372{
373 QWebFrame *frame = frameAdapter ? QWebFramePrivate::kit(frameAdapter): 0;
374 if (insideOpenCall
375 && frame == mainFrame.data())
376 return true;
377 return q->acceptNavigationRequest(frame, request, QWebPage::NavigationType(type));
378}
379
380void QWebPagePrivate::emitRestoreFrameStateRequested(QWebFrameAdapter *frame)
381{
382 emit q->restoreFrameStateRequested(QWebFramePrivate::kit(frame));
383}
384
385void QWebPagePrivate::emitSaveFrameStateRequested(QWebFrameAdapter *frame, QWebHistoryItem *item)
386{
387 emit q->saveFrameStateRequested(QWebFramePrivate::kit(frame), item);
388}
389
390void QWebPagePrivate::emitDownloadRequested(const QNetworkRequest &request)
391{
392 emit q->downloadRequested(request);
393}
394
395void QWebPagePrivate::emitFrameCreated(QWebFrameAdapter *frame)
396{
397 emit q->frameCreated(QWebFramePrivate::kit(frame));
398}
399
400bool QWebPagePrivate::errorPageExtension(QWebPageAdapter::ErrorPageOption *opt, QWebPageAdapter::ErrorPageReturn *out)
401{
402 QWebPage::ErrorPageExtensionOption option;
403 if (opt->domain == QLatin1String("QtNetwork"))
404 option.domain = QWebPage::QtNetwork;
405 else if (opt->domain == QLatin1String("HTTP"))
406 option.domain = QWebPage::Http;
407 else if (opt->domain == QLatin1String("WebKit") || opt->domain == QLatin1String("WebKitErrorDomain"))
408 option.domain = QWebPage::WebKit;
409 else
410 return false;
411 option.url = opt->url;
412 option.frame = QWebFramePrivate::kit(opt->frame);
413 option.error = opt->error;
414 option.errorString = opt->errorString;
415 QWebPage::ErrorPageExtensionReturn output;
416 if (!q->extension(QWebPage::ErrorPageExtension, &option, &output))
417 return false;
418 out->baseUrl = output.baseUrl;
419 out->content = output.content;
420 out->contentType = output.contentType;
421 out->encoding = output.encoding;
422 return true;
423}
424
425QtPluginWidgetAdapter *QWebPagePrivate::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
426{
427 QObject *widget = q->createPlugin(classid, url, paramNames, paramValues);
428 return adapterForWidget(widget);
429}
430
431QtPluginWidgetAdapter *QWebPagePrivate::adapterForWidget(QObject *object) const
432{
433 if (QWidget *widget = qobject_cast<QWidget*>(object))
434 return new QWidgetPluginImpl(widget);
435#ifndef QT_NO_GRAPHICSVIEW
436 if (QGraphicsWidget *widget = qobject_cast<QGraphicsWidget*>(object))
437 return new QGraphicsWidgetPluginImpl(widget);
438#endif
439 return 0;
440}
441
442void QWebPagePrivate::createMainFrame()
443{
444 if (!mainFrame) {
445 mainFrame = new QWebFrame(q);
446 emit q->frameCreated(mainFrame.data());
447 }
448}
449
450#define MAP_WEB_ACTION_FROM_ADAPTER_EQUIVALENT(Name, Value) \
451 case QWebPageAdapter::Name: return QWebPage::Name
452
453static QWebPage::WebAction webActionForAdapterMenuAction(QWebPageAdapter::MenuAction action)
454{
455 switch (action) {
456 FOR_EACH_MAPPED_MENU_ACTION(MAP_WEB_ACTION_FROM_ADAPTER_EQUIVALENT, SEMICOLON_SEPARATOR);
457 case QWebPageAdapter::InspectElement: return QWebPage::InspectElement;
458 default:
459 Q_UNREACHABLE();
460 break;
461 }
462 return QWebPage::NoWebAction;
463}
464
465#define MAP_ADAPTER_ACTION_FROM_WEBACTION_EQUIVALENT(Name, Value) \
466 case QWebPage::Name: return QWebPageAdapter::Name
467
468static QWebPageAdapter::MenuAction adapterMenuActionForWebAction(QWebPage::WebAction action)
469{
470 switch (action) {
471 FOR_EACH_MAPPED_MENU_ACTION(MAP_ADAPTER_ACTION_FROM_WEBACTION_EQUIVALENT, SEMICOLON_SEPARATOR);
472 case QWebPage::InspectElement: return QWebPageAdapter::InspectElement;
473 default:
474 Q_UNREACHABLE();
475 break;
476 }
477 return QWebPageAdapter::NoAction;
478}
479
480#ifndef QT_NO_CONTEXTMENU
481typedef QWebPageAdapter::MenuItemDescription MenuItem;
482QMenu *createContextMenu(QWebPage* page, const QList<MenuItem>& items, QBitArray *visitedWebActions)
483{
484 if (items.isEmpty())
485 return 0;
486
487 QMenu* menu = new QMenu(page->view());
488 for (int i = 0; i < items.count(); ++i) {
489 const MenuItem &item = items.at(i);
490 switch (item.type) {
491 case MenuItem::NoType:
492 Q_UNREACHABLE();
493 break;
494 case MenuItem::Action: {
495 QAction* a = nullptr;
496 if (item.action < QWebPageAdapter::ActionCount) {
497 QWebPage::WebAction action = webActionForAdapterMenuAction(static_cast<QWebPageAdapter::MenuAction>(item.action));
498 a = page->action(action);
499 if (a)
500 visitedWebActions->setBit(action);
501 } else {
502 a = page->customAction(item.action);
503 }
504 if (a) {
505 a->setText(item.title);
506 a->setEnabled(item.traits & MenuItem::Enabled);
507 a->setCheckable(item.traits & MenuItem::Checkable);
508 a->setChecked(item.traits & MenuItem::Checked);
509
510 menu->addAction(a);
511 }
512 break;
513 }
514 case MenuItem::Separator:
515 menu->addSeparator();
516 break;
517 case MenuItem::SubMenu: {
518 QMenu *subMenu = createContextMenu(page, item.subMenu, visitedWebActions);
519 Q_ASSERT(subMenu);
520
521 bool anyEnabledAction = false;
522
523 QList<QAction *> actions = subMenu->actions();
524 for (int i = 0; i < actions.count(); ++i) {
525 if (actions.at(i)->isVisible())
526 anyEnabledAction |= actions.at(i)->isEnabled();
527 }
528
529 // don't show sub-menus with just disabled actions
530 if (anyEnabledAction) {
531 subMenu->setTitle(item.title);
532 menu->addAction(subMenu->menuAction());
533 } else
534 delete subMenu;
535 break;
536 }
537 }
538 }
539 return menu;
540}
541#endif // QT_NO_CONTEXTMENU
542
543void QWebPagePrivate::createAndSetCurrentContextMenu(const QList<MenuItemDescription>& items, QBitArray* visitedWebActions)
544{
545#ifndef QT_NO_CONTEXTMENU
546 delete currentContextMenu.data();
547
548 currentContextMenu = createContextMenu(q, items, visitedWebActions);
549#else
550 Q_UNUSED(menuDescription);
551 Q_UNUSED(visitedWebActions);
552#endif // QT_NO_CONTEXTMENU
553}
554
555#ifndef QT_NO_ACTION
556void QWebPagePrivate::_q_webActionTriggered(bool checked)
557{
558 QAction *a = qobject_cast<QAction *>(q->sender());
559 if (!a)
560 return;
561 QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
562 q->triggerAction(action, checked);
563}
564
565void QWebPagePrivate::_q_customActionTriggered(bool checked)
566{
567 Q_UNUSED(checked);
568 QAction* a = qobject_cast<QAction*>(q->sender());
569 if (!a)
570 return;
571 int action = a->data().toInt();
572 triggerCustomAction(action, a->text());
573}
574#endif // QT_NO_ACTION
575
576void QWebPagePrivate::updateAction(QWebPage::WebAction action)
577{
578#ifdef QT_NO_ACTION
579 Q_UNUSED(action)
580#else
581 QAction *a = actions[action];
582 if (!a || !mainFrame)
583 return;
584
585 bool enabled = a->isEnabled();
586 bool checked = a->isChecked();
587
588 QWebPageAdapter::MenuAction mappedAction = QWebPageAdapter::NoAction;
589 const char* commandName = 0;
590
591 switch (action) {
592 case QWebPage::Back:
593 case QWebPage::Forward:
594 case QWebPage::Stop:
595 case QWebPage::Reload:
596 case QWebPage::SetTextDirectionDefault:
597 case QWebPage::SetTextDirectionLeftToRight:
598 case QWebPage::SetTextDirectionRightToLeft:
599 mappedAction = adapterMenuActionForWebAction(action);
600 break;
601 case QWebPage::ReloadAndBypassCache: // Manual mapping
602 mappedAction = QWebPageAdapter::Reload;
603 break;
604#ifndef QT_NO_UNDOSTACK
605 case QWebPage::Undo:
606 case QWebPage::Redo:
607 // those two are handled by QUndoStack
608 break;
609#endif // QT_NO_UNDOSTACK
610 case QWebPage::SelectAll: // editor command is always enabled
611 break;
612 default: {
613 // see if it's an editor command
614 commandName = editorCommandForWebActions(action);
615 break;
616 }
617 }
618 if (mappedAction != QWebPageAdapter::NoAction || commandName)
619 updateActionInternal(mappedAction, commandName, &enabled, &checked);
620
621 a->setEnabled(enabled);
622
623 if (a->isCheckable())
624 a->setChecked(checked);
625#endif // QT_NO_ACTION
626}
627
628void QWebPagePrivate::updateNavigationActions()
629{
630 updateAction(QWebPage::Back);
631 updateAction(QWebPage::Forward);
632 updateAction(QWebPage::Stop);
633 updateAction(QWebPage::Reload);
634 updateAction(QWebPage::ReloadAndBypassCache);
635}
636
637void QWebPagePrivate::clearCustomActions()
638{
639 qDeleteAll(customActions);
640 customActions.clear();
641}
642
643QObject *QWebPagePrivate::inspectorHandle()
644{
645 return getOrCreateInspector();
646}
647
648void QWebPagePrivate::setInspectorFrontend(QObject* frontend)
649{
650 inspectorFrontend = qobject_cast<QWidget*>(frontend);
651 if (inspector)
652 inspector->d->setFrontend(frontend);
653}
654
655void QWebPagePrivate::setInspectorWindowTitle(const QString& title)
656{
657 if (inspector)
658 inspector->setWindowTitle(title);
659}
660
661void QWebPagePrivate::createWebInspector(QObject** inspectorView, QWebPageAdapter** inspectorPage)
662{
663 QWebPage* page = new WebKit::InspectorClientWebPage;
664 *inspectorView = page->view();
665 *inspectorPage = page->d;
666
667 // FIXME: Find out what's going on with Settings
668 page->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, false);
669
670 // We treat "qrc:" scheme as local, but by default local content is not allowed to use
671 // LocalStorage which is required for Inspector to work.
672 // See https://bugs.webkit.org/show_bug.cgi?id=155265
673 // Alternatively we can make "qrc:" scheme non-local like GTK port does:
674 // https://bugs.webkit.org/show_bug.cgi?id=155497
675 page->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
676}
677
678#ifndef QT_NO_MENU
679static QStringList iterateContextMenu(QMenu* menu)
680{
681 if (!menu)
682 return QStringList();
683
684 QStringList items;
685 QList<QAction *> actions = menu->actions();
686 for (int i = 0; i < actions.count(); ++i) {
687 if (actions.at(i)->isSeparator())
688 items << QLatin1String("<separator>");
689 else
690 items << actions.at(i)->text();
691 if (actions.at(i)->menu())
692 items << iterateContextMenu(actions.at(i)->menu());
693 }
694 return items;
695}
696#endif
697
698QStringList QWebPagePrivate::menuActionsAsText()
699{
700#ifndef QT_NO_MENU
701 return iterateContextMenu(currentContextMenu.data());
702#else
703 return QStringList();
704#endif
705}
706
707void QWebPagePrivate::emitViewportChangeRequested()
708{
709 emit q->viewportChangeRequested();
710}
711
712void QWebPagePrivate::updateEditorActions()
713{
714 updateAction(QWebPage::Cut);
715 updateAction(QWebPage::Copy);
716 updateAction(QWebPage::Paste);
717 updateAction(QWebPage::MoveToNextChar);
718 updateAction(QWebPage::MoveToPreviousChar);
719 updateAction(QWebPage::MoveToNextWord);
720 updateAction(QWebPage::MoveToPreviousWord);
721 updateAction(QWebPage::MoveToNextLine);
722 updateAction(QWebPage::MoveToPreviousLine);
723 updateAction(QWebPage::MoveToStartOfLine);
724 updateAction(QWebPage::MoveToEndOfLine);
725 updateAction(QWebPage::MoveToStartOfBlock);
726 updateAction(QWebPage::MoveToEndOfBlock);
727 updateAction(QWebPage::MoveToStartOfDocument);
728 updateAction(QWebPage::MoveToEndOfDocument);
729 updateAction(QWebPage::SelectNextChar);
730 updateAction(QWebPage::SelectPreviousChar);
731 updateAction(QWebPage::SelectNextWord);
732 updateAction(QWebPage::SelectPreviousWord);
733 updateAction(QWebPage::SelectNextLine);
734 updateAction(QWebPage::SelectPreviousLine);
735 updateAction(QWebPage::SelectStartOfLine);
736 updateAction(QWebPage::SelectEndOfLine);
737 updateAction(QWebPage::SelectStartOfBlock);
738 updateAction(QWebPage::SelectEndOfBlock);
739 updateAction(QWebPage::SelectStartOfDocument);
740 updateAction(QWebPage::SelectEndOfDocument);
741 updateAction(QWebPage::DeleteStartOfWord);
742 updateAction(QWebPage::DeleteEndOfWord);
743 updateAction(QWebPage::SetTextDirectionDefault);
744 updateAction(QWebPage::SetTextDirectionLeftToRight);
745 updateAction(QWebPage::SetTextDirectionRightToLeft);
746 updateAction(QWebPage::ToggleBold);
747 updateAction(QWebPage::ToggleItalic);
748 updateAction(QWebPage::ToggleUnderline);
749 updateAction(QWebPage::InsertParagraphSeparator);
750 updateAction(QWebPage::InsertLineSeparator);
751 updateAction(QWebPage::PasteAndMatchStyle);
752 updateAction(QWebPage::RemoveFormat);
753 updateAction(QWebPage::ToggleStrikethrough);
754 updateAction(QWebPage::ToggleSubscript);
755 updateAction(QWebPage::ToggleSuperscript);
756 updateAction(QWebPage::InsertUnorderedList);
757 updateAction(QWebPage::InsertOrderedList);
758 updateAction(QWebPage::Indent);
759 updateAction(QWebPage::Outdent);
760 updateAction(QWebPage::AlignCenter);
761 updateAction(QWebPage::AlignJustified);
762 updateAction(QWebPage::AlignLeft);
763 updateAction(QWebPage::AlignRight);
764 updateAction(QWebPage::Unselect);
765}
766
767void QWebPagePrivate::timerEvent(QTimerEvent *ev)
768{
769 int timerId = ev->timerId();
770 if (timerId == tripleClickTimer.timerId())
771 tripleClickTimer.stop();
772 else
773 q->timerEvent(ev);
774}
775
776bool QWebPagePrivate::requestSoftwareInputPanel() const
777{
778 return QStyle::RequestSoftwareInputPanel(client->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel)) == QStyle::RSIP_OnMouseClick;
779}
780
781#ifndef QT_NO_CONTEXTMENU
782void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
783{
784 QMenu *menu = q->createStandardContextMenu();
785 if (menu) {
786 menu->exec(globalPos);
787 delete menu;
788 }
789}
790#endif // QT_NO_CONTEXTMENU
791
792/*!
793 \since 4.5
794 This function creates the standard context menu which is shown when
795 the user clicks on the web page with the right mouse button. It is
796 called from the default contextMenuEvent() handler. The popup menu's
797 ownership is transferred to the caller.
798 */
799QMenu *QWebPage::createStandardContextMenu()
800{
801#ifndef QT_NO_CONTEXTMENU
802 QMenu* menu = d->currentContextMenu.data();
803 d->currentContextMenu = 0;
804 return menu;
805#else
806 return 0;
807#endif
808}
809
810#ifndef QT_NO_SHORTCUT
811QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
812{
813 static struct {
814 QKeySequence::StandardKey standardKey;
815 QWebPage::WebAction action;
816 } editorActions[] = {
817 { QKeySequence::Cut, QWebPage::Cut },
818 { QKeySequence::Copy, QWebPage::Copy },
819 { QKeySequence::Paste, QWebPage::Paste },
820 { QKeySequence::Undo, QWebPage::Undo },
821 { QKeySequence::Redo, QWebPage::Redo },
822 { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
823 { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
824 { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
825 { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
826 { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
827 { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
828 { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
829 { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
830 { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
831 { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
832 { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
833 { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
834 { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
835 { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
836 { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
837 { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
838 { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
839 { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
840 { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
841 { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
842 { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
843 { QKeySequence::SelectEndOfBlock, QWebPage::SelectEndOfBlock },
844 { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
845 { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
846 { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
847 { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
848 { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
849 { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
850 { QKeySequence::SelectAll, QWebPage::SelectAll },
851 { QKeySequence::Deselect, QWebPage::Unselect },
852 { QKeySequence::UnknownKey, QWebPage::NoWebAction }
853 };
854
855 for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
856 if (event == editorActions[i].standardKey)
857 return editorActions[i].action;
858
859 return QWebPage::NoWebAction;
860}
861#endif // QT_NO_SHORTCUT
862
863void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
864{
865 // we forward the key event to WebCore first to handle potential DOM
866 // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
867 // to trigger editor commands via triggerAction().
868 bool handled = handleKeyEvent(ev);
869
870 if (!handled)
871 handled = handleScrolling(ev);
872
873 if (!handled) {
874 handled = true;
875 switch (ev->key()) {
876 case Qt::Key_Back:
877 q->triggerAction(QWebPage::Back);
878 break;
879 case Qt::Key_Forward:
880 q->triggerAction(QWebPage::Forward);
881 break;
882 case Qt::Key_Stop:
883 q->triggerAction(QWebPage::Stop);
884 break;
885 case Qt::Key_Refresh:
886 q->triggerAction(QWebPage::Reload);
887 break;
888 default:
889 handled = false;
890 break;
891 }
892 }
893
894 ev->setAccepted(handled);
895}
896
897void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
898{
899 if (ev->isAutoRepeat()) {
900 ev->setAccepted(true);
901 return;
902 }
903
904 bool handled = handleKeyEvent(ev);
905 ev->setAccepted(handled);
906}
907
908template<class T>
909void QWebPagePrivate::dragEnterEvent(T* ev)
910{
911#if ENABLE(DRAG_SUPPORT)
912 Qt::DropAction action = dragEntered(ev->mimeData(), QPointF(ev->pos()).toPoint(), ev->possibleActions());
913 ev->setDropAction(action);
914 ev->acceptProposedAction();
915#endif
916}
917
918template<class T>
919void QWebPagePrivate::dragMoveEvent(T *ev)
920{
921#if ENABLE(DRAG_SUPPORT)
922 m_lastDropAction = dragUpdated(ev->mimeData(), QPointF(ev->pos()).toPoint(), ev->possibleActions());
923 ev->setDropAction(m_lastDropAction);
924 if (m_lastDropAction != Qt::IgnoreAction)
925 ev->accept();
926#endif
927}
928
929template<class T>
930void QWebPagePrivate::dropEvent(T *ev)
931{
932#if ENABLE(DRAG_SUPPORT)
933 if (performDrag(ev->mimeData(), QPointF(ev->pos()).toPoint(), ev->possibleActions())) {
934 ev->setDropAction(m_lastDropAction);
935 ev->accept();
936 }
937#endif
938}
939
940void QWebPagePrivate::leaveEvent(QEvent*)
941{
942 // If a mouse button is pressed we will continue to receive mouse events after leaving the window.
943 if (mousePressed)
944 return;
945
946 // Fake a mouse move event just outside of the widget, since all
947 // the interesting mouse-out behavior like invalidating scrollbars
948 // is handled by the WebKit event handler's mouseMoved function.
949 QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
950 mouseMoveEvent(&fakeEvent);
951}
952
953/*!
954 \property QWebPage::palette
955 \brief the page's palette
956
957 The base brush of the palette is used to draw the background of the main frame.
958
959 By default, this property contains the application's default palette.
960*/
961void QWebPage::setPalette(const QPalette &pal)
962{
963 d->palette = pal;
964 if (!d->mainFrame || !d->mainFrame.data()->d->hasView())
965 return;
966
967 QBrush brush = pal.brush(QPalette::Base);
968 QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
969 d->mainFrame.data()->d->updateBackgroundRecursively(backgroundColor);
970}
971
972QPalette QWebPage::palette() const
973{
974 return d->palette;
975}
976
977void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
978{
979 if (handleShortcutOverrideEvent(event)) {
980 if (event->isAccepted())
981 return;
982#ifndef QT_NO_SHORTCUT
983 else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
984 event->accept();
985#endif
986 }
987}
988
989bool QWebPagePrivate::gestureEvent(QGestureEvent* event)
990{
991 QWebFrameAdapter* frame = mainFrame.data()->d;
992 if (!frame->hasView())
993 return false;
994 // QGestureEvents can contain updates for multiple gestures.
995 bool handled = false;
996#if ENABLE(QT_GESTURE_EVENTS)
997 // QGestureEvent lives in Widgets, we'll need a dummy struct to mule the info it contains to the "other side"
998 QGestureEventFacade gestureFacade;
999
1000 QGesture* gesture = event->gesture(Qt::TapGesture);
1001 // Beware that gestures send by DumpRenderTree will have state Qt::NoGesture,
1002 // due to not originating from a GestureRecognizer.
1003 if (gesture && (gesture->state() == Qt::GestureStarted || gesture->state() == Qt::NoGesture)) {
1004 gestureFacade.type = Qt::TapGesture;
1005 QPointF globalPos = static_cast<const QTapGesture*>(gesture)->position();
1006 gestureFacade.globalPos = globalPos.toPoint();
1007 gestureFacade.pos = event->widget()->mapFromGlobal(globalPos.toPoint());
1008 frame->handleGestureEvent(&gestureFacade);
1009 handled = true;
1010 }
1011 gesture = event->gesture(Qt::TapAndHoldGesture);
1012 if (gesture && (gesture->state() == Qt::GestureStarted || gesture->state() == Qt::NoGesture)) {
1013 gestureFacade.type = Qt::TapAndHoldGesture;
1014 QPointF globalPos = static_cast<const QTapAndHoldGesture*>(gesture)->position();
1015 gestureFacade.globalPos = globalPos.toPoint();
1016 gestureFacade.pos = event->widget()->mapFromGlobal(globalPos.toPoint());
1017 frame->handleGestureEvent(&gestureFacade);
1018 handled = true;
1019 }
1020#endif // ENABLE(QT_GESTURE_EVENTS)
1021
1022 event->setAccepted(handled);
1023 return handled;
1024}
1025
1026/*!
1027 This method is used by the input method to query a set of properties of the page
1028 to be able to support complex input method operations as support for surrounding
1029 text and reconversions.
1030
1031 \a property specifies which property is queried.
1032
1033 \sa QWidget::inputMethodEvent(), QInputMethodEvent
1034*/
1035QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1036{
1037 return d->inputMethodQuery(property);
1038}
1039
1040/*!
1041 \internal
1042*/
1043void QWebPagePrivate::setInspector(QWebInspector* insp)
1044{
1045 if (inspector)
1046 inspector->d->setFrontend(0);
1047
1048 inspector = insp;
1049
1050 // Give inspector frontend web view if previously created
1051 if (inspector && inspectorFrontend)
1052 inspector->d->setFrontend(inspectorFrontend);
1053}
1054
1055/*!
1056 \internal
1057 Returns the inspector and creates it if it wasn't created yet.
1058 The instance created here will not be available through QWebPage's API.
1059*/
1060QWebInspector* QWebPagePrivate::getOrCreateInspector()
1061{
1062 if (!inspector) {
1063 QWebInspector* insp = new QWebInspector;
1064 insp->setPage(q);
1065 inspectorIsInternalOnly = true;
1066
1067 Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1068 }
1069 return inspector;
1070}
1071
1072/*!
1073 \enum QWebPage::FindFlag
1074
1075 This enum describes the options available to the findText() function. The options
1076 can be OR-ed together from the following list:
1077
1078 \value FindBackward Searches backwards instead of forwards.
1079 \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1080 changes the behaviour to a case sensitive find operation.
1081 \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1082 was reached and the text was not found.
1083 \value HighlightAllOccurrences Highlights all existing occurrences of a specific string.
1084 (This value was introduced in 4.6.)
1085 \value FindAtWordBeginningsOnly Searches for the sub-string only at the beginnings of words.
1086 (This value was introduced in 5.2.)
1087 \value TreatMedialCapitalAsWordBeginning Treats a capital letter occurring anywhere in the middle of a word
1088 as the beginning of a new word.
1089 (This value was introduced in 5.2.)
1090 \value FindBeginsInSelection Begin searching inside the text selection first.
1091 (This value was introduced in 5.2.)
1092*/
1093
1094/*!
1095 \enum QWebPage::VisibilityState
1096
1097 This enum defines visibility states that a webpage can take.
1098
1099 \value VisibilityStateVisible The webpage is at least partially visible at on at least one screen.
1100 \value VisibilityStateHidden The webpage is not visible at all on any screen.
1101 \value VisibilityStatePrerender The webpage is loaded off-screen and is not visible.
1102 \value VisibilityStateUnloaded The webpage is unloading its content.
1103 More information about this values can be found at \l{ http://www.w3.org/TR/page-visibility/#dom-document-visibilitystate}{W3C Recommendation: Page Visibility: visibilityState attribute}.
1104
1105 \sa QWebPage::visibilityState
1106*/
1107
1108/*!
1109 \enum QWebPage::LinkDelegationPolicy
1110
1111 This enum defines the delegation policies a webpage can have when activating links and emitting
1112 the linkClicked() signal.
1113
1114 \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1115 \value DelegateExternalLinks When activating links that point to documents not stored on the
1116 local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1117 \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1118
1119 \sa QWebPage::linkDelegationPolicy
1120*/
1121
1122/*!
1123 \enum QWebPage::NavigationType
1124
1125 This enum describes the types of navigation available when browsing through hyperlinked
1126 documents.
1127
1128 \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1129 \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1130 \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1131 \value NavigationTypeReload The user activated the reload action.
1132 \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1133 \value NavigationTypeOther A navigation to another document using a method not listed above.
1134
1135 \sa acceptNavigationRequest()
1136*/
1137
1138/*!
1139 \enum QWebPage::WebAction
1140
1141 This enum describes the types of action which can be performed on the web page.
1142
1143 Actions only have an effect when they are applicable. The availability of
1144 actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1145 action returned by action().
1146
1147 One method of enabling the text editing, cursor movement, and text selection actions
1148 is by setting \l contentEditable to true.
1149
1150 \value NoWebAction No action is triggered.
1151 \value OpenLink Open the current link.
1152 \value OpenLinkInNewWindow Open the current link in a new window.
1153 \value OpenLinkInThisWindow Open the current link without opening a new window. Used on links that would default to opening in another frame or a new window. (Added in Qt 5.0)
1154 \value OpenFrameInNewWindow Replicate the current frame in a new window.
1155 \value DownloadLinkToDisk Download the current link to the disk.
1156 \value CopyLinkToClipboard Copy the current link to the clipboard.
1157 \value OpenImageInNewWindow Open the highlighted image in a new window.
1158 \value DownloadImageToDisk Download the highlighted image to the disk.
1159 \value CopyImageToClipboard Copy the highlighted image to the clipboard. (Added in Qt 4.8)
1160 \value CopyImageUrlToClipboard Copy the highlighted image's URL to the clipboard.
1161 \value Back Navigate back in the history of navigated links.
1162 \value Forward Navigate forward in the history of navigated links.
1163 \value Stop Stop loading the current page.
1164 \value StopScheduledPageRefresh Stop all pending page refresh/redirect requests. (Added in Qt 4.7)
1165 \value Reload Reload the current page.
1166 \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1167 \value Cut Cut the content currently selected into the clipboard.
1168 \value Copy Copy the content currently selected into the clipboard.
1169 \value Paste Paste content from the clipboard.
1170 \value Undo Undo the last editing action.
1171 \value Redo Redo the last editing action.
1172 \value MoveToNextChar Move the cursor to the next character.
1173 \value MoveToPreviousChar Move the cursor to the previous character.
1174 \value MoveToNextWord Move the cursor to the next word.
1175 \value MoveToPreviousWord Move the cursor to the previous word.
1176 \value MoveToNextLine Move the cursor to the next line.
1177 \value MoveToPreviousLine Move the cursor to the previous line.
1178 \value MoveToStartOfLine Move the cursor to the start of the line.
1179 \value MoveToEndOfLine Move the cursor to the end of the line.
1180 \value MoveToStartOfBlock Move the cursor to the start of the block.
1181 \value MoveToEndOfBlock Move the cursor to the end of the block.
1182 \value MoveToStartOfDocument Move the cursor to the start of the document.
1183 \value MoveToEndOfDocument Move the cursor to the end of the document.
1184 \value SelectNextChar Select to the next character.
1185 \value SelectPreviousChar Select to the previous character.
1186 \value SelectNextWord Select to the next word.
1187 \value SelectPreviousWord Select to the previous word.
1188 \value SelectNextLine Select to the next line.
1189 \value SelectPreviousLine Select to the previous line.
1190 \value SelectStartOfLine Select to the start of the line.
1191 \value SelectEndOfLine Select to the end of the line.
1192 \value SelectStartOfBlock Select to the start of the block.
1193 \value SelectEndOfBlock Select to the end of the block.
1194 \value SelectStartOfDocument Select to the start of the document.
1195 \value SelectEndOfDocument Select to the end of the document.
1196 \value DeleteStartOfWord Delete to the start of the word.
1197 \value DeleteEndOfWord Delete to the end of the word.
1198 \value SetTextDirectionDefault Set the text direction to the default direction.
1199 \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1200 \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1201 \value ToggleBold Toggle the formatting between bold and normal weight.
1202 \value ToggleItalic Toggle the formatting between italic and normal style.
1203 \value ToggleUnderline Toggle underlining.
1204 \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1205 \value InsertParagraphSeparator Insert a new paragraph.
1206 \value InsertLineSeparator Insert a new line.
1207 \value SelectAll Selects all content.
1208 \value PasteAndMatchStyle Paste content from the clipboard with current style. (Added in Qt 4.6)
1209 \value RemoveFormat Removes formatting and style. (Added in Qt 4.6)
1210 \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style. (Added in Qt 4.6)
1211 \value ToggleSubscript Toggle the formatting between subscript and baseline. (Added in Qt 4.6)
1212 \value ToggleSuperscript Toggle the formatting between supercript and baseline. (Added in Qt 4.6)
1213 \value InsertUnorderedList Toggles the selection between an ordered list and a normal block. (Added in Qt 4.6)
1214 \value InsertOrderedList Toggles the selection between an ordered list and a normal block. (Added in Qt 4.6)
1215 \value Indent Increases the indentation of the currently selected format block by one increment. (Added in Qt 4.6)
1216 \value Outdent Decreases the indentation of the currently selected format block by one increment. (Added in Qt 4.6)
1217 \value AlignCenter Applies center alignment to content. (Added in Qt 4.6)
1218 \value AlignJustified Applies full justification to content. (Added in Qt 4.6)
1219 \value AlignLeft Applies left justification to content. (Added in Qt 4.6)
1220 \value AlignRight Applies right justification to content. (Added in Qt 4.6)
1221 \value DownloadMediaToDisk Download the hovered audio or video to the disk. (Added in Qt 5.2)
1222 \value CopyMediaUrlToClipboard Copy the hovered audio or video's URL to the clipboard. (Added in Qt 5.2)
1223 \value ToggleMediaControls Toggles between showing and hiding the controls for the hovered audio or video element. (Added in Qt 5.2)
1224 \value ToggleMediaLoop Toggles whether the hovered audio or video should loop on completetion or not. (Added in Qt 5.2)
1225 \value ToggleMediaPlayPause Toggles the play/pause state of the hovered audio or video element. (Added in Qt 5.2)
1226 \value ToggleMediaMute Mutes or unmutes the hovered audio or video element. (Added in Qt 5.2)
1227 \value ToggleVideoFullscreen Switches the hovered video element into or out of fullscreen mode. (Added in Qt 5.2)
1228 \value RequestClose Request to close the web page. If defined, the window.onbeforeunload handler is run, and the user can confirm or reject to close the page. If the close request is confirmed, windowCloseRequested is emitted. (Added in ?)
1229 \value Unselect Deselects existing selection. (Added in QtWebKit 5.9)
1230
1231 \omitvalue WebActionCount
1232
1233*/
1234
1235/*!
1236 \enum QWebPage::WebWindowType
1237
1238 This enum describes the types of window that can be created by the createWindow() function.
1239
1240 \value WebBrowserWindow The window is a regular web browser window.
1241 \value WebModalDialog The window acts as modal dialog.
1242*/
1243
1244/*!
1245 \enum QWebPage::PermissionPolicy
1246
1247 This enum describes the permission policies that the user may set for data or device access.
1248
1249 \value PermissionUnknown It is unknown whether the user grants or denies permission.
1250 \value PermissionGrantedByUser The user has granted permission.
1251 \value PermissionDeniedByUser The user has denied permission.
1252
1253 \sa featurePermissionRequested(), featurePermissionRequestCanceled(), setFeaturePermission(), Feature
1254*/
1255
1256/*!
1257 \enum QWebPage::Feature
1258
1259 This enum describes the platform feature access categories that the user may be asked to grant or deny access to.
1260
1261 \value Notifications Access to notifications
1262 \value Geolocation Access to location hardware or service
1263
1264 \sa featurePermissionRequested(), featurePermissionRequestCanceled(), setFeaturePermission(), PermissionPolicy
1265
1266*/
1267
1268/*!
1269 \fn void QWebPage::featurePermissionRequested(QWebFrame* frame, QWebPage::Feature feature);
1270
1271 This is signal is emitted when the given \a frame requests to make use of
1272 the resource or device identified by \a feature.
1273
1274 \sa featurePermissionRequestCanceled(), setFeaturePermission()
1275*/
1276
1277/*!
1278 \fn void QWebPage::featurePermissionRequestCanceled(QWebFrame* frame, QWebPage::Feature feature);
1279
1280 This is signal is emitted when the given \a frame cancels a previously issued
1281 request to make use of \a feature.
1282
1283 \sa featurePermissionRequested(), setFeaturePermission()
1284
1285*/
1286
1287/*!
1288 \class QWebPage::ViewportAttributes
1289 \since 4.7
1290 \brief The QWebPage::ViewportAttributes class describes hints that can be applied to a viewport.
1291
1292 QWebPage::ViewportAttributes provides a description of a viewport, such as viewport geometry,
1293 initial scale factor with limits, plus information about whether a user should be able
1294 to scale the contents in the viewport or not, ie. by zooming.
1295
1296 ViewportAttributes can be set by a web author using the viewport meta tag extension, documented
1297 at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
1298
1299 All values might not be set, as such when dealing with the hints, the developer needs to
1300 check whether the values are valid. Negative values denote an invalid qreal value.
1301
1302 \inmodule QtWebKit
1303*/
1304
1305/*!
1306 Constructs an empty QWebPage::ViewportAttributes.
1307*/
1308QWebPage::ViewportAttributes::ViewportAttributes()
1309 : d(0)
1310 , m_initialScaleFactor(-1.0)
1311 , m_minimumScaleFactor(-1.0)
1312 , m_maximumScaleFactor(-1.0)
1313 , m_devicePixelRatio(-1.0)
1314 , m_isUserScalable(true)
1315 , m_isValid(false)
1316{
1317
1318}
1319
1320/*!
1321 Constructs a QWebPage::ViewportAttributes which is a copy from \a other .
1322*/
1323QWebPage::ViewportAttributes::ViewportAttributes(const QWebPage::ViewportAttributes& other)
1324 : d(other.d)
1325 , m_initialScaleFactor(other.m_initialScaleFactor)
1326 , m_minimumScaleFactor(other.m_minimumScaleFactor)
1327 , m_maximumScaleFactor(other.m_maximumScaleFactor)
1328 , m_devicePixelRatio(other.m_devicePixelRatio)
1329 , m_isUserScalable(other.m_isUserScalable)
1330 , m_isValid(other.m_isValid)
1331 , m_size(other.m_size)
1332{
1333
1334}
1335
1336/*!
1337 Destroys the QWebPage::ViewportAttributes.
1338*/
1339QWebPage::ViewportAttributes::~ViewportAttributes()
1340{
1341
1342}
1343
1344/*!
1345 Assigns the given QWebPage::ViewportAttributes to this viewport hints and returns a
1346 reference to this.
1347*/
1348QWebPage::ViewportAttributes& QWebPage::ViewportAttributes::operator=(const QWebPage::ViewportAttributes& other)
1349{
1350 if (this != &other) {
1351 d = other.d;
1352 m_initialScaleFactor = other.m_initialScaleFactor;
1353 m_minimumScaleFactor = other.m_minimumScaleFactor;
1354 m_maximumScaleFactor = other.m_maximumScaleFactor;
1355 m_isUserScalable = other.m_isUserScalable;
1356 m_isValid = other.m_isValid;
1357 m_size = other.m_size;
1358 }
1359
1360 return *this;
1361}
1362
1363/*! \fn inline bool QWebPage::ViewportAttributes::isValid() const
1364 Returns whether this is a valid ViewportAttributes or not.
1365
1366 An invalid ViewportAttributes will have an empty QSize, negative values for scale factors and
1367 true for the boolean isUserScalable.
1368*/
1369
1370/*! \fn inline QSize QWebPage::ViewportAttributes::size() const
1371 Returns the size of the viewport.
1372*/
1373
1374/*! \fn inline qreal QWebPage::ViewportAttributes::initialScaleFactor() const
1375 Returns the initial scale of the viewport as a multiplier.
1376*/
1377
1378/*! \fn inline qreal QWebPage::ViewportAttributes::minimumScaleFactor() const
1379 Returns the minimum scale value of the viewport as a multiplier.
1380*/
1381
1382/*! \fn inline qreal QWebPage::ViewportAttributes::maximumScaleFactor() const
1383 Returns the maximum scale value of the viewport as a multiplier.
1384*/
1385
1386/*! \fn inline bool QWebPage::ViewportAttributes::isUserScalable() const
1387 Determines whether or not the scale can be modified by the user.
1388*/
1389
1390
1391/*!
1392 \class QWebPage
1393 \since 4.4
1394 \brief The QWebPage class provides an object to view and edit web documents.
1395
1396 \inmodule QtWebKit
1397
1398 QWebPage holds a main frame responsible for web content, settings, the history
1399 of navigated links and actions. This class can be used, together with QWebFrame,
1400 to provide functionality like QWebView in a widget-less environment.
1401
1402 QWebPage's API is very similar to QWebView, as you are still provided with
1403 common functions like action() (known as
1404 \l{QWebView::pageAction()}{pageAction}() in QWebView), triggerAction(),
1405 findText() and settings(). More QWebView-like functions can be found in the
1406 main frame of QWebPage, obtained via the mainFrame() function. For example,
1407 the \l{QWebFrame::load()}{load}(), \l{QWebFrame::setUrl()}{setUrl}() and
1408 \l{QWebFrame::setHtml()}{setHtml}() functions for QWebPage can be accessed
1409 using QWebFrame.
1410
1411 The loadStarted() signal is emitted when the page begins to load.The
1412 loadProgress() signal, on the other hand, is emitted whenever an element
1413 of the web page completes loading, such as an embedded image, a script,
1414 etc. Finally, the loadFinished() signal is emitted when the page contents
1415 are loaded completely, independent of script execution or page rendering.
1416 Its argument, either true or false, indicates whether or not the load
1417 operation succeeded.
1418
1419 \section1 Using QWebPage in a Widget-less Environment
1420
1421 Before you begin painting a QWebPage object, you need to set the size of
1422 the viewport by calling setViewportSize(). Then, you invoke the main
1423 frame's render function (QWebFrame::render()). An example of this
1424 is shown in the code snippet below.
1425
1426 Suppose we have a \c Thumbnail class as follows:
1427
1428 \snippet webkitsnippets/webpage/main.cpp 0
1429
1430 The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1431 object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1432 \c render().
1433
1434 \snippet webkitsnippets/webpage/main.cpp 1
1435
1436 The \c render() function shows how we can paint a thumbnail using a
1437 QWebPage object.
1438
1439 \snippet webkitsnippets/webpage/main.cpp 2
1440
1441 We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1442 then we instantiate a QImage object, \c image, with the same size as our
1443 \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1444 as a parameter to \c painter. Next, we render the contents of the main
1445 frame and its subframes into \c painter. Finally, we save the scaled image.
1446
1447 \sa QWebFrame
1448*/
1449
1450/*!
1451 Constructs an empty QWebPage with parent \a parent.
1452*/
1453QWebPage::QWebPage(QObject *parent)
1454 : QObject(parent)
1455 , d(new QWebPagePrivate(this))
1456{
1457 setView(qobject_cast<QWidget*>(parent));
1458
1459 connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1460#ifndef NDEBUG
1461 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1462#endif
1463}
1464
1465/*!
1466 Destroys the web page.
1467*/
1468QWebPage::~QWebPage()
1469{
1470 delete d;
1471}
1472
1473/*!
1474 Returns the main frame of the page.
1475
1476 The main frame provides access to the hierarchy of sub-frames and is also needed if you
1477 want to explicitly render a web page into a given painter.
1478
1479 \sa currentFrame()
1480*/
1481QWebFrame *QWebPage::mainFrame() const
1482{
1483 d->createMainFrame();
1484 return d->mainFrame.data();
1485}
1486
1487/*!
1488 Returns the frame currently active.
1489
1490 \sa mainFrame(), frameCreated()
1491*/
1492QWebFrame *QWebPage::currentFrame() const
1493{
1494 d->createMainFrame();
1495 return qobject_cast<QWebFrame*>(d->currentFrame());
1496}
1497
1498
1499/*!
1500 \since 4.6
1501
1502 Returns the frame at the given point \a pos, or 0 if there is no frame at
1503 that position.
1504
1505 \sa mainFrame(), currentFrame()
1506*/
1507QWebFrame* QWebPage::frameAt(const QPoint& pos) const
1508{
1509 QWebFrame* webFrame = mainFrame();
1510 if (!webFrame->geometry().contains(pos))
1511 return 0;
1512 QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
1513 return hitTestResult.frame();
1514}
1515
1516/*!
1517 Returns a pointer to the view's history of navigated web pages.
1518*/
1519QWebHistory *QWebPage::history() const
1520{
1521 d->createMainFrame();
1522 return &d->history;
1523}
1524
1525/*!
1526 Sets the \a view that is associated with the web page.
1527
1528 \sa view()
1529*/
1530void QWebPage::setView(QWidget* view)
1531{
1532 if (this->view() == view)
1533 return;
1534
1535 d->view = view;
1536 setViewportSize(view ? view->size() : QSize(0, 0));
1537
1538 // If we have no client, we install a special client delegating
1539 // the responsibility to the QWidget. This is the code path
1540 // handling a.o. the "legacy" QWebView.
1541 //
1542 // If such a special delegate already exist, we substitute the view.
1543
1544 if (d->client) {
1545 if (d->client->isQWidgetClient())
1546 static_cast<PageClientQWidget*>(d->client.data())->view = view;
1547 return;
1548 }
1549
1550 if (view)
1551 d->client.reset(new PageClientQWidget(view, this));
1552}
1553
1554/*!
1555 Returns the view widget that is associated with the web page.
1556
1557 \sa setView()
1558*/
1559QWidget *QWebPage::view() const
1560{
1561 return d->view.data();
1562}
1563
1564/*!
1565 This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
1566
1567 For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
1568
1569 The default implementation prints nothing.
1570*/
1571void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
1572{
1573 Q_UNUSED(sourceID);
1574
1575 // Catch plugin logDestroy message for LayoutTests/plugins/open-and-close-window-with-plugin.html
1576 // At this point DRT's WebPage has already been destroyed
1577 if (QWebPageAdapter::drtRun) {
1578 if (message == QLatin1String("PLUGIN: NPP_Destroy")) {
1579 fprintf(stdout, "CONSOLE MESSAGE: ");
1580 if (lineNumber)
1581 fprintf(stdout, "line %d: ", lineNumber);
1582 fprintf(stdout, "%s\n", message.toUtf8().constData());
1583 }
1584 }
1585}
1586
1587/*!
1588 This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
1589 the message \a msg.
1590
1591 The default implementation shows the message, \a msg, with QMessageBox::information.
1592*/
1593void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
1594{
1595 Q_UNUSED(frame);
1596#ifndef QT_NO_MESSAGEBOX
1597 QMessageBox box(view());
1598 box.setWindowTitle(tr("JavaScript Alert - %1").arg(mainFrame()->url().host()));
1599 box.setTextFormat(Qt::PlainText);
1600 box.setText(msg);
1601 box.setStandardButtons(QMessageBox::Ok);
1602 box.exec();
1603#endif
1604}
1605
1606/*!
1607 This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
1608 with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
1609
1610 The default implementation executes the query using QMessageBox::information with QMessageBox::Ok and QMessageBox::Cancel buttons.
1611*/
1612bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
1613{
1614 Q_UNUSED(frame);
1615#ifdef QT_NO_MESSAGEBOX
1616 return true;
1617#else
1618 QMessageBox box(view());
1619 box.setWindowTitle(tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()));
1620 box.setTextFormat(Qt::PlainText);
1621 box.setText(msg);
1622 box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
1623 return QMessageBox::Ok == box.exec();
1624#endif
1625}
1626
1627/*!
1628 This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
1629 The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
1630
1631 If the prompt was cancelled by the user the implementation should return false; otherwise the
1632 result should be written to \a result and true should be returned. If the prompt was not cancelled by the
1633 user, the implementation should return true and the result string must not be null.
1634
1635 The default implementation uses QInputDialog::getText().
1636*/
1637bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
1638{
1639 Q_UNUSED(frame);
1640 bool ok = false;
1641#ifndef QT_NO_INPUTDIALOG
1642
1643 QInputDialog dlg(view());
1644 dlg.setWindowTitle(tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()));
1645
1646 // Hack to force the dialog's QLabel into plain text mode
1647 // prevents https://bugs.webkit.org/show_bug.cgi?id=34429
1648 QLabel* label = dlg.findChild<QLabel*>();
1649 if (label)
1650 label->setTextFormat(Qt::PlainText);
1651
1652 // double the &'s because single & will underline the following character
1653 // (Accelerator mnemonics)
1654 QString escMsg(msg);
1655 escMsg.replace(QChar::fromLatin1('&'), QLatin1String("&&"));
1656 dlg.setLabelText(escMsg);
1657
1658 dlg.setTextEchoMode(QLineEdit::Normal);
1659 dlg.setTextValue(defaultValue);
1660
1661 ok = !!dlg.exec();
1662
1663 if (ok && result)
1664 *result = dlg.textValue();
1665#endif
1666 return ok;
1667}
1668
1669/*!
1670 \fn bool QWebPage::shouldInterruptJavaScript()
1671 \since 4.6
1672 This function is called when a JavaScript program is running for a long period of time.
1673
1674 If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
1675
1676 The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
1677*/
1678bool QWebPage::shouldInterruptJavaScript()
1679{
1680#ifdef QT_NO_MESSAGEBOX
1681 return false;
1682#else
1683 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);
1684#endif
1685}
1686
1687/*!
1688 \fn void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy)
1689
1690 Sets the permission for the given \a frame to use \a feature to \a policy.
1691
1692 \sa featurePermissionRequested(), featurePermissionRequestCanceled()
1693*/
1694void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy)
1695{
1696#if !ENABLE(NOTIFICATIONS) && !ENABLE(GEOLOCATION)
1697 Q_UNUSED(frame);
1698 Q_UNUSED(policy);
1699#endif
1700 switch (feature) {
1701 case Notifications:
1702#if ENABLE(NOTIFICATIONS)
1703 if (policy != PermissionUnknown)
1704 d->setNotificationsAllowedForFrame(frame->d, (policy == PermissionGrantedByUser));
1705#endif
1706 break;
1707 case Geolocation:
1708#if ENABLE(GEOLOCATION) && HAVE(QTPOSITIONING)
1709 if (policy != PermissionUnknown)
1710 d->setGeolocationEnabledForFrame(frame->d, (policy == PermissionGrantedByUser));
1711#endif
1712 break;
1713
1714 default:
1715 break;
1716 }
1717}
1718
1719/*!
1720 This function is called whenever WebKit wants to create a new window of the given \a type, for
1721 example when a JavaScript program requests to open a document in a new window.
1722
1723 If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
1724
1725 If the view associated with the web page is a QWebView object, then the default implementation forwards
1726 the request to QWebView's createWindow() function; otherwise it returns a null pointer.
1727
1728 If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
1729
1730 \note In the cases when the window creation is being triggered by JavaScript, apart from
1731 reimplementing this method application must also set the JavaScriptCanOpenWindows attribute
1732 of QWebSettings to true in order for it to get called.
1733
1734 \sa acceptNavigationRequest(), QWebView::createWindow()
1735*/
1736QWebPage *QWebPage::createWindow(WebWindowType type)
1737{
1738 QWebView *webView = qobject_cast<QWebView*>(view());
1739 if (webView) {
1740 QWebView *newView = webView->createWindow(type);
1741 if (newView)
1742 return newView->page();
1743 }
1744 return 0;
1745}
1746
1747/*!
1748 This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is
1749 called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues
1750 correspond to the HTML object element attributes and child elements to configure the embeddable object.
1751*/
1752QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
1753{
1754 Q_UNUSED(classid);
1755 Q_UNUSED(url);
1756 Q_UNUSED(paramNames);
1757 Q_UNUSED(paramValues);
1758 return 0;
1759}
1760
1761/*!
1762 * Returns the list of all content types supported by QWebPage.
1763 */
1764QStringList QWebPage::supportedContentTypes() const
1765{
1766 return d->supportedContentTypes();
1767}
1768
1769/*!
1770 * Returns true if QWebPage can handle the given \a mimeType; otherwise, returns false.
1771 */
1772bool QWebPage::supportsContentType(const QString& mimeType) const
1773{
1774 return d->supportsContentType(mimeType);
1775}
1776
1777static void collectChildFrames(QWebFrame* frame, QList<QWebFrame*>& list)
1778{
1779 list << frame->childFrames();
1780 QListIterator<QWebFrame*> it(frame->childFrames());
1781 while (it.hasNext())
1782 collectChildFrames(it.next(), list);
1783}
1784
1785/*!
1786 This function can be called to trigger the specified \a action.
1787 It is also called by Qt WebKit if the user triggers the action, for example
1788 through a context menu item.
1789
1790 If \a action is a checkable action then \a checked specified whether the action
1791 is toggled or not.
1792
1793 \sa action()
1794*/
1795void QWebPage::triggerAction(WebAction action, bool)
1796{
1797 const char *command = 0;
1798 QWebPageAdapter::MenuAction mappedAction = QWebPageAdapter::NoAction;
1799 QWebHitTestResultPrivate* hitTestResult = d->hitTestResult.d;
1800
1801 switch (action) {
1802 case OpenLink:
1803 case OpenLinkInNewWindow:
1804 case OpenLinkInThisWindow:
1805 case OpenFrameInNewWindow:
1806 case CopyLinkToClipboard:
1807 case OpenImageInNewWindow:
1808 case DownloadImageToDisk:
1809 case DownloadLinkToDisk:
1810 case Back:
1811 case Forward:
1812 case Stop:
1813 case Reload:
1814 case SetTextDirectionDefault:
1815 case SetTextDirectionLeftToRight:
1816 case SetTextDirectionRightToLeft:
1817 case DownloadMediaToDisk:
1818 case ToggleMediaControls:
1819 case ToggleMediaLoop:
1820 case ToggleMediaPlayPause:
1821 case ToggleMediaMute:
1822 case ToggleVideoFullscreen:
1823 mappedAction = adapterMenuActionForWebAction(action);
1824 break;
1825 case ReloadAndBypassCache: // Manual mapping
1826 mappedAction = QWebPageAdapter::Reload;
1827 break;
1828#ifndef QT_NO_CLIPBOARD
1829 case CopyImageToClipboard:
1830 QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
1831 break;
1832 case CopyImageUrlToClipboard:
1833 QApplication::clipboard()->setText(d->hitTestResult.imageUrl().toString());
1834 break;
1835 case CopyMediaUrlToClipboard:
1836 QApplication::clipboard()->setText(d->hitTestResult.mediaUrl().toString());
1837 break;
1838#endif
1839 case InspectElement: {
1840 if (!d->hitTestResult.isNull()) {
1841 d->getOrCreateInspector(); // Make sure the inspector is created
1842 d->inspector->show(); // The inspector is expected to be shown on inspection
1843 mappedAction = QWebPageAdapter::InspectElement;
1844 }
1845 break;
1846 }
1847 case StopScheduledPageRefresh: {
1848 QWebFrame* topFrame = mainFrame();
1849 topFrame->d->cancelLoad();
1850 QList<QWebFrame*> childFrames;
1851 collectChildFrames(topFrame, childFrames);
1852 QListIterator<QWebFrame*> it(childFrames);
1853 while (it.hasNext())
1854 it.next()->d->cancelLoad();
1855 break;
1856 }
1857 case RequestClose: {
1858 bool success = d->tryClosePage();
1859 if (success)
1860 emit windowCloseRequested();
1861 break;
1862 }
1863 default:
1864 command = QWebPagePrivate::editorCommandForWebActions(action);
1865 break;
1866 }
1867 if (command || mappedAction != QWebPageAdapter::NoAction)
1868 d->triggerAction(mappedAction, hitTestResult, command, /*endToEndReload*/ action == ReloadAndBypassCache);
1869}
1870
1871
1872QColor QWebPagePrivate::colorSelectionRequested(const QColor &selectedColor)
1873{
1874 QColor ret = selectedColor;
1875#ifndef QT_NO_COLORDIALOG
1876 ret = QColorDialog::getColor(selectedColor, q->view());
1877 if (!ret.isValid())
1878 ret = selectedColor;
1879#endif
1880 return ret;
1881}
1882
1883std::unique_ptr<QWebSelectMethod> QWebPagePrivate::createSelectPopup()
1884{
1885 return std::make_unique<QtFallbackWebPopup>(this);
1886}
1887
1888QRect QWebPagePrivate::viewRectRelativeToWindow()
1889{
1890
1891 QWidget* ownerWidget= client.isNull() ? 0 : qobject_cast<QWidget*>(client->ownerWidget());
1892 if (!ownerWidget)
1893 return QRect();
1894 QWidget* topLevelWidget = ownerWidget->window();
1895
1896 QPoint topLeftCorner = ownerWidget->mapFrom(topLevelWidget, QPoint(0, 0));
1897 return QRect(topLeftCorner, ownerWidget->size());
1898}
1899
1900void QWebPagePrivate::geolocationPermissionRequested(QWebFrameAdapter* frame)
1901{
1902 emit q->featurePermissionRequested(QWebFramePrivate::kit(frame), QWebPage::Geolocation);
1903}
1904
1905void QWebPagePrivate::geolocationPermissionRequestCancelled(QWebFrameAdapter* frame)
1906{
1907 emit q->featurePermissionRequestCanceled(QWebFramePrivate::kit(frame), QWebPage::Geolocation);
1908}
1909
1910void QWebPagePrivate::notificationsPermissionRequested(QWebFrameAdapter* frame)
1911{
1912 emit q->featurePermissionRequested(QWebFramePrivate::kit(frame), QWebPage::Notifications);
1913}
1914
1915void QWebPagePrivate::notificationsPermissionRequestCancelled(QWebFrameAdapter* frame)
1916{
1917 emit q->featurePermissionRequestCanceled(QWebFramePrivate::kit(frame), QWebPage::Notifications);
1918}
1919
1920void QWebPagePrivate::respondToChangedContents()
1921{
1922 updateEditorActions();
1923
1924 emit q->contentsChanged();
1925}
1926
1927void QWebPagePrivate::respondToChangedSelection()
1928{
1929 updateEditorActions();
1930 emit q->selectionChanged();
1931}
1932
1933void QWebPagePrivate::microFocusChanged()
1934{
1935 emit q->microFocusChanged();
1936}
1937
1938void QWebPagePrivate::triggerCopyAction()
1939{
1940 q->triggerAction(QWebPage::Copy);
1941}
1942
1943void QWebPagePrivate::triggerActionForKeyEvent(QKeyEvent* event)
1944{
1945 QWebPage::WebAction action = editorActionForKeyEvent(event);
1946 q->triggerAction(action);
1947}
1948
1949void QWebPagePrivate::clearUndoStack()
1950{
1951#ifndef QT_NO_UNDOSTACK
1952 if (undoStack)
1953 undoStack->clear();
1954#endif
1955}
1956
1957bool QWebPagePrivate::canUndo() const
1958{
1959#ifndef QT_NO_UNDOSTACK
1960 if (!undoStack)
1961 return false;
1962 return undoStack->canUndo();
1963#else
1964 return false;
1965#endif
1966}
1967
1968bool QWebPagePrivate::canRedo() const
1969{
1970#ifndef QT_NO_UNDOSTACK
1971 if (!undoStack)
1972 return false;
1973 return undoStack->canRedo();
1974#else
1975 return false;
1976#endif
1977}
1978
1979void QWebPagePrivate::undo()
1980{
1981#ifndef QT_NO_UNDOSTACK
1982 if (undoStack)
1983 undoStack->undo();
1984#endif
1985}
1986
1987void QWebPagePrivate::redo()
1988{
1989#ifndef QT_NO_UNDOSTACK
1990 if (undoStack)
1991 undoStack->redo();
1992#endif
1993}
1994
1995void QWebPagePrivate::createUndoStep(QSharedPointer<UndoStepQt> step)
1996{
1997#ifndef QT_NO_UNDOSTACK
1998 // Call undoStack() getter first to ensure stack is created
1999 // if it doesn't exist yet.
2000 q->undoStack()->push(new QWebUndoCommand(step));
2001#endif
2002}
2003
2004const char *QWebPagePrivate::editorCommandForKeyEvent(QKeyEvent* event)
2005{
2006 QWebPage::WebAction action = editorActionForKeyEvent(event);
2007 return editorCommandForWebActions(action);
2008}
2009
2010QSize QWebPage::viewportSize() const
2011{
2012 if (d->mainFrame && d->mainFrame.data()->d->hasView())
2013 return d->mainFrame.data()->d->frameRect().size();
2014
2015 return d->m_viewportSize;
2016}
2017
2018/*!
2019 \property QWebPage::viewportSize
2020 \brief the size of the viewport
2021
2022 The size affects for example the visibility of scrollbars
2023 if the document is larger than the viewport.
2024
2025 By default, for a newly-created Web page, this property contains a size with
2026 zero width and height.
2027
2028 \sa QWebFrame::render(), preferredContentsSize
2029*/
2030void QWebPage::setViewportSize(const QSize &size) const
2031{
2032 d->m_viewportSize = size;
2033
2034 d->updateWindow();
2035
2036 QWebFrameAdapter& mainFrame = d->mainFrameAdapter();
2037 if (!mainFrame.hasView())
2038 return;
2039
2040 mainFrame.setViewportSize(size);
2041}
2042
2043void QWebPagePrivate::updateWindow()
2044{
2045 QWindow* _window = 0;
2046 if (view && view->window())
2047 _window = view->window()->windowHandle();
2048
2049 if (window == _window)
2050 return;
2051
2052 if (window)
2053 QObject::disconnect(window, SIGNAL(screenChanged(QScreen*)), q, SLOT(_q_updateScreen(QScreen*)));
2054 window = _window;
2055 if (window) {
2056 QObject::connect(window, SIGNAL(screenChanged(QScreen*)), q, SLOT(_q_updateScreen(QScreen*)));
2057 _q_updateScreen(window->screen());
2058 }
2059}
2060
2061void QWebPagePrivate::_q_updateScreen(QScreen* screen)
2062{
2063 if (screen && !m_customDevicePixelRatioIsSet)
2064 setDevicePixelRatio(screen->devicePixelRatio());
2065}
2066
2067void QWebPage::setDevicePixelRatio(qreal ratio)
2068{
2069 d->setDevicePixelRatio(ratio);
2070 d->m_customDevicePixelRatioIsSet = true;
2071}
2072
2073qreal QWebPage::devicePixelRatio() const
2074{
2075 return d->devicePixelRatio();
2076}
2077
2078void QWebPage::resetDevicePixelRatio()
2079{
2080 d->m_customDevicePixelRatioIsSet = false;
2081 d->updateWindow();
2082}
2083
2084static int getintenv(const char* variable)
2085{
2086 bool ok;
2087 int value = qgetenv(variable).toInt(&ok);
2088 return (ok) ? value : -1;
2089}
2090
2091static QSize queryDeviceSizeForScreenContainingWidget(const QWidget* widget)
2092{
2093 QDesktopWidget* desktop = QApplication::desktop();
2094 if (!desktop)
2095 return QSize();
2096
2097 QSize size;
2098
2099 if (widget) {
2100 // Returns the available geometry of the screen which contains widget.
2101 // NOTE: this must be the the full screen size including any fixed status areas etc.
2102 size = desktop->availableGeometry(widget).size();
2103 } else
2104 size = desktop->availableGeometry().size();
2105
2106 // This must be in portrait mode, adjust if not.
2107 if (size.width() > size.height()) {
2108 int width = size.width();
2109 size.setWidth(size.height());
2110 size.setHeight(width);
2111 }
2112
2113 return size;
2114}
2115
2116/*!
2117 Computes the optimal viewport configuration given the \a availableSize, when
2118 user interface components are disregarded.
2119
2120 The configuration is also dependent on the device screen size which is obtained
2121 automatically. For testing purposes the size can be overridden by setting two
2122 environment variables QTWEBKIT_DEVICE_WIDTH and QTWEBKIT_DEVICE_HEIGHT, which
2123 both needs to be set.
2124
2125 The ViewportAttributes includes a pixel density ratio, which will also be exposed to
2126 the web author though the -webkit-pixel-ratio media feature. This is the ratio
2127 between 1 density-independent pixel (DPI) and physical pixels.
2128
2129 A density-independent pixel is equivalent to one physical pixel on a 160 DPI screen,
2130 so on our platform assumes that as the baseline density.
2131
2132 The conversion of DIP units to screen pixels is quite simple:
2133
2134 pixels = DIPs * (density / 160).
2135
2136 Thus, on a 240 DPI screen, 1 DIPs would equal 1.5 physical pixels.
2137
2138 An invalid instance will be returned in the case an empty size is passed to the
2139 method.
2140
2141 \note The density is automatically obtained from the DPI of the screen where the page
2142 is being shown, but as many X11 servers are reporting wrong DPI, it is possible to
2143 override it using QX11Info::setAppDpiY().
2144*/
2145
2146QWebPage::ViewportAttributes QWebPage::viewportAttributesForSize(const QSize& availableSize) const
2147{
2148 ViewportAttributes result;
2149
2150 if (availableSize.isEmpty())
2151 return result; // Returns an invalid instance.
2152
2153 QSize deviceSize(getintenv("QTWEBKIT_DEVICE_WIDTH"), getintenv("QTWEBKIT_DEVICE_HEIGHT"));
2154
2155 // Both environment variables need to be set - or they will be ignored.
2156 if (deviceSize.isNull())
2157 deviceSize = queryDeviceSizeForScreenContainingWidget(view());
2158 QWebPageAdapter::ViewportAttributes attr = d->viewportAttributesForSize(availableSize, deviceSize);
2159
2160 result.m_isValid = true;
2161 result.m_size = attr.size;
2162 result.m_initialScaleFactor = attr.initialScaleFactor;
2163 result.m_minimumScaleFactor = attr.minimumScaleFactor;
2164 result.m_maximumScaleFactor = attr.maximumScaleFactor;
2165 result.m_devicePixelRatio = attr.devicePixelRatio;
2166 result.m_isUserScalable = attr.isUserScalable;
2167
2168 return result;
2169}
2170
2171QSize QWebPage::preferredContentsSize() const
2172{
2173 QWebFrameAdapter* mainFrame = d->mainFrame ? d->mainFrame->d : 0;
2174 QSize customSize;
2175 if (mainFrame && mainFrame->hasView())
2176 customSize = mainFrame->customLayoutSize();
2177
2178 return customSize.isNull() ? d->fixedLayoutSize : customSize;
2179}
2180
2181/*!
2182 \property QWebPage::preferredContentsSize
2183 \since 4.6
2184 \brief a custom size used for laying out the page contents.
2185
2186 By default all pages are laid out using the viewport of the page as the base.
2187
2188 As pages mostly are designed for desktop usage, they often do not layout properly
2189 on small devices as the contents require a certain view width. For this reason
2190 it is common to use a different layout size and then scale the contents to fit
2191 within the actual view.
2192
2193 If this property is set to a valid size, this size is used for all layout needs
2194 instead of the size of the viewport.
2195
2196 Setting an invalid size, makes the page fall back to using the viewport size for layout.
2197
2198 \sa viewportSize
2199*/
2200void QWebPage::setPreferredContentsSize(const QSize& size) const
2201{
2202 // FIXME: Rename this method to setCustomLayoutSize
2203
2204 d->fixedLayoutSize = size;
2205
2206 QWebFrameAdapter& mainFrame = d->mainFrameAdapter();
2207 if (!mainFrame.hasView())
2208 return;
2209
2210 mainFrame.setCustomLayoutSize(size);
2211}
2212
2213/*
2214 This function is to be called after any (animated) scroll/pan has ended, in the case the application handles the
2215 scrolling/panning of the web contents. This is commonly used in combination with tiling where is it common for
2216 the application to pan the actual view, which then resizes itself to the size of the contents.
2217
2218 \note Calling this function makes WebKit stop trying to calculate the visibleContentRect. To turn that on
2219 again, call this method with an empty rect.
2220
2221 \sa QGraphicsWebView::resizesToContents, QWebSettings::TiledBackingStoreEnabled
2222*/
2223void QWebPage::setActualVisibleContentRect(const QRect& rect) const
2224{
2225 QWebFrameAdapter& mainFrame = d->mainFrameAdapter();
2226 if (!mainFrame.hasView())
2227 return;
2228
2229 mainFrame.setFixedVisibleContentRect(rect);
2230}
2231
2232/*!
2233 \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2234
2235 This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
2236 the specified navigation type \a type.
2237
2238 If \a frame is a null pointer then navigation to a new window is requested. If the request is
2239 accepted createWindow() will be called.
2240
2241 The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
2242 to let QWebPage handle the navigation itself.
2243
2244 \sa createWindow()
2245*/
2246bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2247{
2248 Q_UNUSED(frame);
2249 if (type == NavigationTypeLinkClicked) {
2250 switch (d->linkPolicy) {
2251 case DontDelegateLinks:
2252 return true;
2253
2254 case DelegateExternalLinks:
2255 if (request.url().scheme().isEmpty() && QWebPageAdapter::treatSchemeAsLocal(frame->baseUrl().scheme()))
2256 return true;
2257 if (QWebPageAdapter::treatSchemeAsLocal(request.url().scheme()))
2258 return true;
2259 emit linkClicked(request.url());
2260 return false;
2261
2262 case DelegateAllLinks:
2263 emit linkClicked(request.url());
2264 return false;
2265 }
2266 }
2267 return true;
2268}
2269
2270/*!
2271 \property QWebPage::hasSelection
2272 \brief whether this page contains selected content or not.
2273
2274 \sa selectionChanged()
2275*/
2276bool QWebPage::hasSelection() const
2277{
2278 d->createMainFrame();
2279 return d->hasSelection();
2280}
2281
2282/*!
2283 \property QWebPage::selectedText
2284 \brief the text currently selected
2285
2286 By default, this property contains an empty string.
2287
2288 \sa selectionChanged(), selectedHtml()
2289*/
2290QString QWebPage::selectedText() const
2291{
2292 d->createMainFrame();
2293 return d->selectedText();
2294}
2295
2296/*!
2297 \since 4.8
2298 \property QWebPage::selectedHtml
2299 \brief the HTML currently selected
2300
2301 By default, this property contains an empty string.
2302
2303 \sa selectionChanged(), selectedText()
2304*/
2305QString QWebPage::selectedHtml() const
2306{
2307 d->createMainFrame();
2308 return d->selectedHtml();
2309}
2310
2311#ifndef QT_NO_ACTION
2312/*!
2313 Returns a QAction for the specified WebAction \a action.
2314
2315 The action is owned by the QWebPage but you can customize the look by
2316 changing its properties.
2317
2318 QWebPage also takes care of implementing the action, so that upon
2319 triggering the corresponding action is performed on the page.
2320
2321 \sa triggerAction()
2322*/
2323QAction *QWebPage::action(WebAction action) const
2324{
2325 if (action == QWebPage::NoWebAction)
2326 return 0;
2327 if (d->actions[action])
2328 return d->actions[action];
2329
2330 QString text;
2331 QIcon icon;
2332 QStyle *style = d->client ? d->client->style() : qApp->style();
2333 bool checkable = false;
2334 QWebPageAdapter::MenuAction mappedAction = QWebPageAdapter::NoAction;
2335
2336 switch (action) {
2337 // to be fetched from LocalizedStringsQt via the page adapter
2338 case OpenLink:
2339 case OpenLinkInNewWindow:
2340 case OpenFrameInNewWindow:
2341 case OpenLinkInThisWindow:
2342 case DownloadLinkToDisk:
2343 case CopyLinkToClipboard:
2344 case OpenImageInNewWindow:
2345 case DownloadImageToDisk:
2346 case CopyImageToClipboard:
2347 case CopyImageUrlToClipboard:
2348 case Cut:
2349 case Copy:
2350 case Paste:
2351 case SelectAll:
2352 case SetTextDirectionDefault:
2353 case SetTextDirectionLeftToRight:
2354 case SetTextDirectionRightToLeft:
2355 case ToggleBold:
2356 case ToggleItalic:
2357 case ToggleUnderline:
2358 case DownloadMediaToDisk:
2359 case CopyMediaUrlToClipboard:
2360 case ToggleMediaControls:
2361 case ToggleMediaLoop:
2362 case ToggleMediaPlayPause:
2363 case ToggleMediaMute:
2364 case ToggleVideoFullscreen:
2365 mappedAction = adapterMenuActionForWebAction(action);
2366 break;
2367 case InspectElement:
2368 mappedAction = QWebPageAdapter::InspectElement;
2369 break;
2370
2371 // icon needed as well, map by hand.
2372 case Back:
2373 mappedAction = QWebPageAdapter::Back;
2374 icon = style->standardIcon(QStyle::SP_ArrowBack);
2375 break;
2376 case Forward:
2377 mappedAction = QWebPageAdapter::Forward;
2378 icon = style->standardIcon(QStyle::SP_ArrowForward);
2379 break;
2380 case Stop:
2381 mappedAction = QWebPageAdapter::Stop;
2382 icon = style->standardIcon(QStyle::SP_BrowserStop);
2383 break;
2384 case Reload:
2385 mappedAction = QWebPageAdapter::Reload;
2386 icon = style->standardIcon(QStyle::SP_BrowserReload);
2387 break;
2388
2389#ifndef QT_NO_UNDOSTACK
2390 case Undo: {
2391 QAction *a = undoStack()->createUndoAction(d->q);
2392 d->actions[action] = a;
2393 return a;
2394 }
2395 case Redo: {
2396 QAction *a = undoStack()->createRedoAction(d->q);
2397 d->actions[action] = a;
2398 return a;
2399 }
2400#endif // QT_NO_UNDOSTACK
2401 // in place l10n
2402 case MoveToNextChar:
2403 text = tr("Move the cursor to the next character");
2404 break;
2405 case MoveToPreviousChar:
2406 text = tr("Move the cursor to the previous character");
2407 break;
2408 case MoveToNextWord:
2409 text = tr("Move the cursor to the next word");
2410 break;
2411 case MoveToPreviousWord:
2412 text = tr("Move the cursor to the previous word");
2413 break;
2414 case MoveToNextLine:
2415 text = tr("Move the cursor to the next line");
2416 break;
2417 case MoveToPreviousLine:
2418 text = tr("Move the cursor to the previous line");
2419 break;
2420 case MoveToStartOfLine:
2421 text = tr("Move the cursor to the start of the line");
2422 break;
2423 case MoveToEndOfLine:
2424 text = tr("Move the cursor to the end of the line");
2425 break;
2426 case MoveToStartOfBlock:
2427 text = tr("Move the cursor to the start of the block");
2428 break;
2429 case MoveToEndOfBlock:
2430 text = tr("Move the cursor to the end of the block");
2431 break;
2432 case MoveToStartOfDocument:
2433 text = tr("Move the cursor to the start of the document");
2434 break;
2435 case MoveToEndOfDocument:
2436 text = tr("Move the cursor to the end of the document");
2437 break;
2438 case SelectNextChar:
2439 text = tr("Select to the next character");
2440 break;
2441 case SelectPreviousChar:
2442 text = tr("Select to the previous character");
2443 break;
2444 case SelectNextWord:
2445 text = tr("Select to the next word");
2446 break;
2447 case SelectPreviousWord:
2448 text = tr("Select to the previous word");
2449 break;
2450 case SelectNextLine:
2451 text = tr("Select to the next line");
2452 break;
2453 case SelectPreviousLine:
2454 text = tr("Select to the previous line");
2455 break;
2456 case SelectStartOfLine:
2457 text = tr("Select to the start of the line");
2458 break;
2459 case SelectEndOfLine:
2460 text = tr("Select to the end of the line");
2461 break;
2462 case SelectStartOfBlock:
2463 text = tr("Select to the start of the block");
2464 break;
2465 case SelectEndOfBlock:
2466 text = tr("Select to the end of the block");
2467 break;
2468 case SelectStartOfDocument:
2469 text = tr("Select to the start of the document");
2470 break;
2471 case SelectEndOfDocument:
2472 text = tr("Select to the end of the document");
2473 break;
2474 case DeleteStartOfWord:
2475 text = tr("Delete to the start of the word");
2476 break;
2477 case DeleteEndOfWord:
2478 text = tr("Delete to the end of the word");
2479 break;
2480
2481 case InsertParagraphSeparator:
2482 text = tr("Insert a new paragraph");
2483 break;
2484 case InsertLineSeparator:
2485 text = tr("Insert a new line");
2486 break;
2487
2488 case PasteAndMatchStyle:
2489 text = tr("Paste and Match Style");
2490 break;
2491 case RemoveFormat:
2492 text = tr("Remove formatting");
2493 break;
2494
2495 case ToggleStrikethrough:
2496 text = tr("Strikethrough");
2497 checkable = true;
2498 break;
2499 case ToggleSubscript:
2500 text = tr("Subscript");
2501 checkable = true;
2502 break;
2503 case ToggleSuperscript:
2504 text = tr("Superscript");
2505 checkable = true;
2506 break;
2507 case InsertUnorderedList:
2508 text = tr("Insert Bulleted List");
2509 checkable = true;
2510 break;
2511 case InsertOrderedList:
2512 text = tr("Insert Numbered List");
2513 checkable = true;
2514 break;
2515 case Indent:
2516 text = tr("Indent");
2517 break;
2518 case Outdent:
2519 text = tr("Outdent");
2520 break;
2521 case AlignCenter:
2522 text = tr("Center");
2523 break;
2524 case AlignJustified:
2525 text = tr("Justify");
2526 break;
2527 case AlignLeft:
2528 text = tr("Align Left");
2529 break;
2530 case AlignRight:
2531 text = tr("Align Right");
2532 break;
2533 case NoWebAction:
2534 return 0;
2535 default:
2536 break;
2537 }
2538 if (mappedAction != QWebPageAdapter::NoAction)
2539 text = d->contextMenuItemTagForAction(mappedAction, &checkable);
2540
2541 if (text.isEmpty())
2542 return 0;
2543
2544 QAction *a = new QAction(d->q);
2545 a->setText(text);
2546 a->setData(action);
2547 a->setCheckable(checkable);
2548 a->setIcon(icon);
2549
2550 connect(a, SIGNAL(triggered(bool)),
2551 this, SLOT(_q_webActionTriggered(bool)));
2552
2553 d->actions[action] = a;
2554 d->updateAction(action);
2555 return a;
2556}
2557
2558QAction* QWebPage::customAction(int action) const
2559{
2560 auto actionIter = d->customActions.constFind(action);
2561 if (actionIter != d->customActions.constEnd())
2562 return *actionIter;
2563
2564 QAction* a = new QAction(d->q);
2565 a->setData(action);
2566 connect(a, SIGNAL(triggered(bool)),
2567 this, SLOT(_q_customActionTriggered(bool)));
2568
2569 d->customActions.insert(action, a);
2570 return a;
2571}
2572#endif // QT_NO_ACTION
2573
2574/*!
2575 \property QWebPage::modified
2576 \brief whether the page contains unsubmitted form data, or the contents have been changed.
2577
2578 By default, this property is false.
2579
2580 \sa contentsChanged(), contentEditable, undoStack()
2581*/
2582bool QWebPage::isModified() const
2583{
2584#ifdef QT_NO_UNDOSTACK
2585 return false;
2586#else
2587 if (!d->undoStack)
2588 return false;
2589 return d->undoStack->canUndo();
2590#endif // QT_NO_UNDOSTACK
2591}
2592
2593#ifndef QT_NO_UNDOSTACK
2594/*!
2595 Returns a pointer to the undo stack used for editable content.
2596
2597 \sa modified
2598*/
2599QUndoStack *QWebPage::undoStack() const
2600{
2601 if (!d->undoStack)
2602 d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
2603
2604 return d->undoStack;
2605}
2606#endif // QT_NO_UNDOSTACK
2607
2608/*! \reimp
2609*/
2610bool QWebPage::event(QEvent *ev)
2611{
2612 switch (ev->type()) {
2613 case QEvent::Timer:
2614 d->timerEvent(static_cast<QTimerEvent*>(ev));
2615 break;
2616 case QEvent::MouseMove:
2617 d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
2618 break;
2619 case QEvent::MouseButtonPress:
2620 d->mousePressEvent(static_cast<QMouseEvent*>(ev));
2621 break;
2622 case QEvent::MouseButtonDblClick:
2623 d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
2624 break;
2625 case QEvent::MouseButtonRelease:
2626 d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
2627 break;
2628#if !defined(QT_NO_GRAPHICSVIEW)
2629 case QEvent::GraphicsSceneMouseMove: {
2630 QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
2631 QMouseEvent dummyEvent(QEvent::MouseMove, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
2632 d->mouseMoveEvent(&dummyEvent);
2633 ev->setAccepted(dummyEvent.isAccepted());
2634 break;
2635 }
2636 case QEvent::GraphicsSceneMouseRelease: {
2637 QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
2638 QMouseEvent dummyEvent(QEvent::MouseButtonRelease, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
2639 d->adjustPointForClicking(&dummyEvent);
2640 d->mouseReleaseEvent(&dummyEvent);
2641 ev->setAccepted(dummyEvent.isAccepted());
2642 break;
2643 }
2644 case QEvent::GraphicsSceneMousePress: {
2645 QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
2646 QMouseEvent dummyEvent(QEvent::MouseButtonPress, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
2647 d->adjustPointForClicking(&dummyEvent);
2648 d->mousePressEvent(&dummyEvent);
2649 ev->setAccepted(dummyEvent.isAccepted());
2650 break;
2651 }
2652 case QEvent::GraphicsSceneMouseDoubleClick: {
2653 QGraphicsSceneMouseEvent *gsEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
2654 QMouseEvent dummyEvent(QEvent::MouseButtonDblClick, gsEv->pos(), gsEv->screenPos(), gsEv->button(), gsEv->buttons(), gsEv->modifiers());
2655 d->adjustPointForClicking(&dummyEvent);
2656 d->mouseDoubleClickEvent(&dummyEvent);
2657 ev->setAccepted(dummyEvent.isAccepted());
2658 break;
2659 }
2660#endif
2661#ifndef QT_NO_CONTEXTMENU
2662 case QEvent::ContextMenu:
2663 d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos());
2664 break;
2665#if !defined(QT_NO_GRAPHICSVIEW)
2666 case QEvent::GraphicsSceneContextMenu:
2667 d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos());
2668 break;
2669#endif
2670#endif
2671#ifndef QT_NO_WHEELEVENT
2672 case QEvent::Wheel:
2673 d->wheelEvent(static_cast<QWheelEvent*>(ev), QApplication::wheelScrollLines());
2674 break;
2675#if !defined(QT_NO_GRAPHICSVIEW)
2676 case QEvent::GraphicsSceneWheel: {
2677 QGraphicsSceneWheelEvent *gsEv = static_cast<QGraphicsSceneWheelEvent*>(ev);
2678 QWheelEvent dummyEvent(gsEv->pos(), gsEv->screenPos(), gsEv->delta(), gsEv->buttons(), gsEv->modifiers(), gsEv->orientation());
2679 d->wheelEvent(&dummyEvent, QApplication::wheelScrollLines());
2680 ev->setAccepted(dummyEvent.isAccepted());
2681 break;
2682 }
2683#endif
2684#endif
2685 case QEvent::KeyPress:
2686 d->keyPressEvent(static_cast<QKeyEvent*>(ev));
2687 break;
2688 case QEvent::KeyRelease:
2689 d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
2690 break;
2691 case QEvent::FocusIn:
2692 d->focusInEvent(static_cast<QFocusEvent*>(ev));
2693 break;
2694 case QEvent::FocusOut:
2695 d->focusOutEvent(static_cast<QFocusEvent*>(ev));
2696 break;
2697#if ENABLE(DRAG_SUPPORT)
2698 case QEvent::DragEnter:
2699 d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
2700 break;
2701 case QEvent::DragLeave:
2702 d->dragLeaveEvent();
2703 ev->accept();
2704 break;
2705 case QEvent::DragMove:
2706 d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
2707 break;
2708 case QEvent::Drop:
2709 d->dropEvent(static_cast<QDropEvent*>(ev));
2710 break;
2711#if !defined(QT_NO_GRAPHICSVIEW)
2712 case QEvent::GraphicsSceneDragEnter:
2713 d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2714 break;
2715 case QEvent::GraphicsSceneDragMove:
2716 d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2717 break;
2718 case QEvent::GraphicsSceneDragLeave:
2719 d->dragLeaveEvent();
2720 ev->accept();
2721 break;
2722 case QEvent::GraphicsSceneDrop:
2723 d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
2724 break;
2725#endif
2726
2727#endif
2728 case QEvent::InputMethod:
2729 d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
2730 break;
2731 case QEvent::ShortcutOverride:
2732 d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
2733 break;
2734 case QEvent::Leave:
2735 d->leaveEvent(ev);
2736 break;
2737 case QEvent::TouchBegin:
2738 case QEvent::TouchUpdate:
2739 case QEvent::TouchEnd:
2740 case QEvent::TouchCancel:
2741 // Return whether the default action was cancelled in the JS event handler
2742 return d->touchEvent(static_cast<QTouchEvent*>(ev));
2743#ifndef QT_NO_GESTURES
2744 case QEvent::Gesture:
2745 d->gestureEvent(static_cast<QGestureEvent*>(ev));
2746 break;
2747#endif
2748#ifndef QT_NO_PROPERTIES
2749 case QEvent::DynamicPropertyChange:
2750 d->dynamicPropertyChangeEvent(this, static_cast<QDynamicPropertyChangeEvent*>(ev));
2751 break;
2752#endif
2753 case QEvent::Show:
2754 d->setPluginsVisible(true);
2755 break;
2756 case QEvent::Hide:
2757 d->setPluginsVisible(false);
2758 break;
2759 default:
2760 return QObject::event(ev);
2761 }
2762
2763 return true;
2764}
2765
2766/*!
2767 Similar to QWidget::focusNextPrevChild() it focuses the next focusable web element
2768 if \a next is true; otherwise the previous element is focused.
2769
2770 Returns true if it can find a new focusable element, or false if it can't.
2771*/
2772bool QWebPage::focusNextPrevChild(bool next)
2773{
2774 QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
2775 d->keyPressEvent(&ev);
2776 return d->hasFocusedNode();
2777}
2778
2779/*!
2780 \property QWebPage::contentEditable
2781 \brief whether the content in this QWebPage is editable or not
2782 \since 4.5
2783
2784 If this property is enabled the contents of the page can be edited by the user through a visible
2785 cursor. If disabled (the default) only HTML elements in the web page with their
2786 \c{contenteditable} attribute set are editable.
2787
2788 \sa modified, contentsChanged(), WebAction
2789*/
2790void QWebPage::setContentEditable(bool editable)
2791{
2792 if (isContentEditable() != editable) {
2793 d->setContentEditable(editable);
2794 d->updateEditorActions();
2795 }
2796}
2797
2798bool QWebPage::isContentEditable() const
2799{
2800 return d->isContentEditable();
2801}
2802
2803/*!
2804 \property QWebPage::forwardUnsupportedContent
2805 \brief whether QWebPage should forward unsupported content
2806
2807 If enabled, the unsupportedContent() signal is emitted with a network reply that
2808 can be used to read the content.
2809
2810 If disabled, the download of such content is aborted immediately.
2811
2812 By default unsupported content is not forwarded.
2813*/
2814
2815void QWebPage::setForwardUnsupportedContent(bool forward)
2816{
2817 d->forwardUnsupportedContent = forward;
2818}
2819
2820bool QWebPage::forwardUnsupportedContent() const
2821{
2822 return d->forwardUnsupportedContent;
2823}
2824
2825/*!
2826 \property QWebPage::linkDelegationPolicy
2827 \brief how QWebPage should delegate the handling of links through the
2828 linkClicked() signal
2829
2830 The default is to delegate no links.
2831*/
2832
2833void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
2834{
2835 d->linkPolicy = policy;
2836}
2837
2838QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
2839{
2840 return d->linkPolicy;
2841}
2842
2843#ifndef QT_NO_CONTEXTMENU
2844
2845bool QWebPagePrivate::handleScrollbarContextMenuEvent(QContextMenuEvent* event, bool horizontal, QWebPageAdapter::ScrollDirection* direction, QWebPageAdapter::ScrollGranularity* granularity)
2846{
2847 if (!QApplication::style()->styleHint(QStyle::SH_ScrollBar_ContextMenu))
2848 return false;
2849
2850 QMenu menu;
2851 QAction* actScrollHere = menu.addAction(QCoreApplication::translate("QWebPage", "Scroll here"));
2852 menu.addSeparator();
2853
2854 QAction* actScrollTop = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Left edge") : QCoreApplication::translate("QWebPage", "Top"));
2855 QAction* actScrollBottom = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Right edge") : QCoreApplication::translate("QWebPage", "Bottom"));
2856 menu.addSeparator();
2857
2858 QAction* actPageUp = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Page left") : QCoreApplication::translate("QWebPage", "Page up"));
2859 QAction* actPageDown = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Page right") : QCoreApplication::translate("QWebPage", "Page down"));
2860 menu.addSeparator();
2861
2862 QAction* actScrollUp = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Scroll left") : QCoreApplication::translate("QWebPage", "Scroll up"));
2863 QAction* actScrollDown = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Scroll right") : QCoreApplication::translate("QWebPage", "Scroll down"));
2864
2865 QAction* actionSelected = menu.exec(event->globalPos());
2866
2867 if (actionSelected == actScrollHere)
2868 return true;
2869 if (actionSelected == actScrollTop) {
2870 *direction = horizontal ? ScrollLeft : ScrollUp;
2871 *granularity = ScrollByDocument;
2872 } else if (actionSelected == actScrollBottom) {
2873 *direction =horizontal ? ScrollRight : ScrollDown;
2874 *granularity = ScrollByDocument;
2875 } else if (actionSelected == actPageUp) {
2876 *direction = horizontal ? ScrollLeft : ScrollUp;
2877 *granularity = ScrollByPage;
2878 } else if (actionSelected == actPageDown) {
2879 *direction =horizontal ? ScrollRight : ScrollDown;
2880 *granularity = ScrollByPage;
2881 } else if (actionSelected == actScrollUp) {
2882 *direction = horizontal ? ScrollLeft : ScrollUp;
2883 *granularity = ScrollByLine;
2884 } else if (actionSelected == actScrollDown) {
2885 *direction =horizontal ? ScrollRight : ScrollDown;
2886 *granularity = ScrollByLine;
2887 }
2888 return true;
2889}
2890
2891/*!
2892 Filters the context menu event, \a event, through handlers for scrollbars and
2893 custom event handlers in the web page. Returns true if the event was handled;
2894 otherwise false.
2895
2896 A web page may swallow a context menu event through a custom event handler, allowing for context
2897 menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
2898 Maps}, for example.
2899*/
2900bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
2901{
2902 QWebFrame* webFrame = frameAt(event->pos());
2903 return d->swallowContextMenuEvent(event, webFrame ? webFrame->d : 0);
2904}
2905#endif // QT_NO_CONTEXTMENU
2906
2907/*!
2908 Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
2909 element the CopyImageToClipboard action is enabled.
2910*/
2911void QWebPage::updatePositionDependentActions(const QPoint &pos)
2912{
2913#ifndef QT_NO_ACTION
2914 // First we disable all actions, but keep track of which ones were originally enabled.
2915 QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
2916 for (int i = QWebPageAdapter::NoAction + 1; i < QWebPageAdapter::ActionCount; ++i) {
2917 QWebPage::WebAction action = webActionForAdapterMenuAction(QWebPageAdapter::MenuAction(i));
2918 if (QAction *a = this->action(action)) {
2919 originallyEnabledWebActions.setBit(action, a->isEnabled());
2920 a->setEnabled(false);
2921 }
2922 }
2923#endif // QT_NO_ACTION
2924
2925 QBitArray visitedWebActions(QWebPage::WebActionCount);
2926 d->createMainFrame();
2927 // Then we let updatePositionDependantMenuActions() enable the actions that are put into the menu
2928 QWebHitTestResultPrivate* result = d->updatePositionDependentMenuActions(pos, &visitedWebActions);
2929 if (!result)
2930 d->hitTestResult = QWebHitTestResult();
2931 else
2932 d->hitTestResult = QWebHitTestResult(result);
2933
2934#ifndef QT_NO_ACTION
2935 // Finally, we restore the original enablement for the actions that were not put into the menu.
2936 originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
2937 for (int i = 0; i < QWebPage::WebActionCount; ++i) {
2938 if (originallyEnabledWebActions.at(i)) {
2939 if (QAction *a = this->action(QWebPage::WebAction(i)))
2940 a->setEnabled(true);
2941 }
2942 }
2943#endif // QT_NO_ACTION
2944
2945 // This whole process ensures that any actions put into to the context menu has the right
2946 // enablement, while also keeping the correct enablement for actions that were left out of
2947 // the menu.
2948
2949}
2950
2951
2952
2953/*!
2954 \enum QWebPage::Extension
2955
2956 This enum describes the types of extensions that the page can support. Before using these extensions, you
2957 should verify that the extension is supported by calling supportsExtension().
2958
2959 \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection.
2960 This extension is invoked when the web content requests one or more file names, for example
2961 as a result of the user clicking on a "file upload" button in a HTML form where multiple
2962 file selection is allowed.
2963
2964 \value ErrorPageExtension Whether the web page can provide an error page when loading fails.
2965 (introduced in Qt 4.6)
2966
2967 \sa ChooseMultipleFilesExtensionOption, ChooseMultipleFilesExtensionReturn, ErrorPageExtensionOption, ErrorPageExtensionReturn
2968*/
2969
2970/*!
2971 \enum QWebPage::ErrorDomain
2972 \since 4.6
2973
2974 This enum describes the domain of an ErrorPageExtensionOption object (i.e. the layer in which the error occurred).
2975
2976 \value QtNetwork The error occurred in the QtNetwork layer; the error code is of type QNetworkReply::NetworkError.
2977 \value Http The error occurred in the HTTP layer; the error code is a HTTP status code (see QNetworkRequest::HttpStatusCodeAttribute).
2978 \value WebKit The error is an internal WebKit error.
2979*/
2980
2981/*!
2982 \class QWebPage::ExtensionOption
2983 \since 4.4
2984 \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
2985
2986 \inmodule QtWebKit
2987
2988 \sa QWebPage::extension(), QWebPage::ExtensionReturn
2989*/
2990
2991
2992/*!
2993 \class QWebPage::ExtensionReturn
2994 \since 4.4
2995 \brief The ExtensionReturn class provides an output result from a QWebPage's extension.
2996
2997 \inmodule QtWebKit
2998
2999 \sa QWebPage::extension(), QWebPage::ExtensionOption
3000*/
3001
3002/*!
3003 \class QWebPage::ErrorPageExtensionOption
3004 \since 4.6
3005 \brief The ErrorPageExtensionOption class describes the option
3006 for the error page extension.
3007
3008 \inmodule QtWebKit
3009
3010 The ErrorPageExtensionOption class holds the \a url for which an error occurred as well as
3011 the associated \a frame.
3012
3013 The error itself is reported by an error \a domain, the \a error code as well as \a errorString.
3014
3015 \sa QWebPage::extension(), QWebPage::ErrorPageExtensionReturn
3016*/
3017
3018/*!
3019 \variable QWebPage::ErrorPageExtensionOption::url
3020 \brief the url for which an error occurred
3021*/
3022
3023/*!
3024 \variable QWebPage::ErrorPageExtensionOption::frame
3025 \brief the frame associated with the error
3026*/
3027
3028/*!
3029 \variable QWebPage::ErrorPageExtensionOption::domain
3030 \brief the domain that reported the error
3031*/
3032
3033/*!
3034 \variable QWebPage::ErrorPageExtensionOption::error
3035 \brief the error code. Interpretation of the value depends on the \a domain
3036 \sa QWebPage::ErrorDomain
3037*/
3038
3039/*!
3040 \variable QWebPage::ErrorPageExtensionOption::errorString
3041 \brief a string that describes the error
3042*/
3043
3044/*!
3045 \class QWebPage::ErrorPageExtensionReturn
3046 \since 4.6
3047 \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the
3048 frame for which the error occured.
3049
3050 \inmodule QtWebKit
3051
3052 The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are
3053 optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which
3054 is assumed to be UTF-8 if not indicated otherwise.
3055
3056 The error page is stored in the \a content byte array, as HTML content. In order to convert a
3057 QString to a byte array, the QString::toUtf8() method can be used.
3058
3059 External objects such as stylesheets or images referenced in the HTML are located relative to
3060 \a baseUrl.
3061
3062 \sa QWebPage::extension(), QWebPage::ErrorPageExtensionOption, QString::toUtf8()
3063*/
3064
3065/*!
3066 \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn()
3067
3068 Constructs a new error page object.
3069*/
3070
3071
3072/*!
3073 \variable QWebPage::ErrorPageExtensionReturn::contentType
3074 \brief the error page's content type
3075*/
3076
3077/*!
3078 \variable QWebPage::ErrorPageExtensionReturn::encoding
3079 \brief the error page encoding
3080*/
3081
3082/*!
3083 \variable QWebPage::ErrorPageExtensionReturn::baseUrl
3084 \brief the base url
3085
3086 External objects such as stylesheets or images referenced in the HTML are located relative to this url.
3087*/
3088
3089/*!
3090 \variable QWebPage::ErrorPageExtensionReturn::content
3091 \brief the HTML content of the error page
3092*/
3093
3094/*!
3095 \class QWebPage::ChooseMultipleFilesExtensionOption
3096 \since 4.5
3097 \brief The ChooseMultipleFilesExtensionOption class describes the option
3098 for the multiple files selection extension.
3099
3100 \inmodule QtWebKit
3101
3102 The ChooseMultipleFilesExtensionOption class holds the frame originating the request
3103 and the suggested filenames which might be provided.
3104
3105 \sa QWebPage::extension(), QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn
3106*/
3107
3108/*!
3109 \variable QWebPage::ChooseMultipleFilesExtensionOption::parentFrame
3110 \brief The frame in which the request originated
3111*/
3112
3113/*!
3114 \variable QWebPage::ChooseMultipleFilesExtensionOption::suggestedFileNames
3115 \brief The suggested filenames
3116*/
3117
3118/*!
3119 \variable QWebPage::ChooseMultipleFilesExtensionReturn::fileNames
3120 \brief The selected filenames
3121*/
3122
3123/*!
3124 \class QWebPage::ChooseMultipleFilesExtensionReturn
3125 \since 4.5
3126 \brief The ChooseMultipleFilesExtensionReturn describes the return value
3127 for the multiple files selection extension.
3128
3129 \inmodule QtWebKit
3130
3131 The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user
3132 when the extension is invoked.
3133
3134 \sa QWebPage::extension(), QWebPage::ChooseMultipleFilesExtensionOption
3135*/
3136
3137/*!
3138 This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
3139 argument is provided as input to the extension; the output results can be stored in \a output.
3140
3141 The behavior of this function is determined by \a extension. The \a option
3142 and \a output values are typically casted to the corresponding types (for
3143 example, ChooseMultipleFilesExtensionOption and
3144 ChooseMultipleFilesExtensionReturn for ChooseMultipleFilesExtension).
3145
3146 You can call supportsExtension() to check if an extension is supported by the page.
3147
3148 Returns true if the extension was called successfully; otherwise returns false.
3149
3150 \sa supportsExtension(), Extension
3151*/
3152bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
3153{
3154#ifndef QT_NO_FILEDIALOG
3155 if (extension == ChooseMultipleFilesExtension) {
3156 // FIXME: do not ignore suggestedFiles
3157 QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames;
3158 QStringList names = QFileDialog::getOpenFileNames(view(), QString());
3159 static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
3160 return true;
3161 }
3162#endif
3163
3164 return false;
3165}
3166
3167/*!
3168 This virtual function returns true if the web page supports \a extension; otherwise false is returned.
3169
3170 \sa extension()
3171*/
3172bool QWebPage::supportsExtension(Extension extension) const
3173{
3174#ifndef QT_NO_FILEDIALOG
3175 return extension == ChooseMultipleFilesExtension;
3176#else
3177 Q_UNUSED(extension);
3178 return false;
3179#endif
3180}
3181
3182/*!
3183 * \internal
3184 */
3185QWebPageAdapter *QWebPage::handle() const
3186{
3187 return d;
3188}
3189
3190/*!
3191 Finds the specified string, \a subString, in the page, using the given \a options.
3192
3193 If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
3194 that exist in the page. All subsequent calls will extend the highlight, rather than
3195 replace it, with occurrences of the new string.
3196
3197 If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
3198 and all subsequent calls will replace the current occurrence with the next one.
3199
3200 To clear the selection, just pass an empty string.
3201
3202 Returns true if \a subString was found; otherwise returns false.
3203*/
3204bool QWebPage::findText(const QString &subString, FindFlags options)
3205{
3206 return d->findText(subString, static_cast<QWebPageAdapter::FindFlag>(
3207 static_cast<FindFlags::Int>(options)));
3208}
3209
3210/*!
3211 Returns a pointer to the page's settings object.
3212
3213 \sa QWebSettings::globalSettings()
3214*/
3215QWebSettings *QWebPage::settings() const
3216{
3217 return d->settings;
3218}
3219
3220/*!
3221 This function is called when the web content requests a file name, for example
3222 as a result of the user clicking on a "file upload" button in a HTML form.
3223
3224 A suggested filename may be provided in \a suggestedFile. The frame originating the
3225 request is provided as \a parentFrame.
3226
3227 \sa ChooseMultipleFilesExtension
3228*/
3229QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
3230{
3231 Q_UNUSED(parentFrame);
3232#ifndef QT_NO_FILEDIALOG
3233 return QFileDialog::getOpenFileName(view(), QString(), suggestedFile);
3234#else
3235 return QString();
3236#endif
3237}
3238
3239/*!
3240 Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
3241 QWebPage.
3242
3243 \note It is currently not supported to change the network access manager after the
3244 QWebPage has used it. The results of doing this are undefined.
3245
3246 \sa networkAccessManager()
3247*/
3248void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
3249{
3250 d->setNetworkAccessManager(manager);
3251}
3252
3253/*!
3254 Returns the QNetworkAccessManager that is responsible for serving network
3255 requests for this QWebPage.
3256
3257 \sa setNetworkAccessManager()
3258*/
3259QNetworkAccessManager *QWebPage::networkAccessManager() const
3260{
3261 return d->networkAccessManager();
3262}
3263
3264/*!
3265 Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
3266 QWebPage.
3267
3268 Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
3269
3270 \sa pluginFactory()
3271*/
3272void QWebPage::setPluginFactory(QWebPluginFactory *factory)
3273{
3274 d->pluginFactory = factory;
3275}
3276
3277/*!
3278 Returns the QWebPluginFactory that is responsible for creating plugins embedded into
3279 this QWebPage. If no plugin factory is installed a null pointer is returned.
3280
3281 \sa setPluginFactory()
3282*/
3283QWebPluginFactory *QWebPage::pluginFactory() const
3284{
3285 return d->pluginFactory;
3286}
3287
3288/*!
3289 This function is called when a user agent for HTTP requests is needed. You can reimplement this
3290 function to dynamically return different user agents for different URLs, based on the \a url parameter.
3291
3292 The default implementation returns the following value:
3293
3294 "Mozilla/5.0 (%Platform%%Security%%Subplatform%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%"
3295
3296 In this string the following values are replaced at run-time:
3297 \list
3298 \li %Platform% expands to the windowing system followed by "; " if it is not Windows (e.g. "X11; ").
3299 \li %Security% expands to "N; " if SSL is disabled.
3300 \li %Subplatform% expands to the operating system version (e.g. "Windows NT 6.1" or "Intel Mac OS X 10.5").
3301 \li %WebKitVersion% is the version of WebKit the application was compiled against.
3302 \li %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
3303 \endlist
3304*/
3305QString QWebPage::userAgentForUrl(const QUrl&) const
3306{
3307 return QWebPageAdapter::defaultUserAgentString();
3308}
3309
3310
3311/*!
3312 Returns the total number of bytes that were received from the network to render the current page,
3313 including extra content such as embedded images.
3314
3315 \sa bytesReceived()
3316*/
3317quint64 QWebPage::totalBytes() const
3318{
3319 return d->m_totalBytes;
3320}
3321
3322
3323/*!
3324 Returns the number of bytes that were received from the network to render the current page.
3325
3326 \sa totalBytes(), loadProgress()
3327*/
3328quint64 QWebPage::bytesReceived() const
3329{
3330 return d->m_bytesReceived;
3331}
3332
3333
3334/*!
3335 \property QWebPage::visibilityState
3336 \brief the page's visibility state
3337
3338 This property should be changed by Qt applications who want to notify the JavaScript application
3339 that the visibility state has changed (e.g. by reimplementing QWidget::setVisible).
3340 The visibility state will be updated with the \a state parameter value only if it's different from the previous set.
3341 Then, HTML DOM Document Object attributes 'hidden' and 'visibilityState'
3342 will be updated to the correct value and a 'visiblitychange' event will be fired.
3343 More information about this HTML5 API can be found at \l{http://www.w3.org/TR/page-visibility/}{W3C Recommendation: Page Visibility}.
3344
3345 By default, this property is set to VisibilityStateVisible.
3346*/
3347void QWebPage::setVisibilityState(VisibilityState state)
3348{
3349 d->setVisibilityState(static_cast<QWebPageAdapter::VisibilityState>(state));
3350}
3351
3352QWebPage::VisibilityState QWebPage::visibilityState() const
3353{
3354 return static_cast<VisibilityState>(d->visibilityState());
3355}
3356
3357
3358bool QWebPage::recentlyAudible() const
3359{
3360 return d->isPlayingAudio();
3361}
3362
3363
3364/*!
3365 \since 4.8
3366 \fn void QWebPage::viewportChangeRequested()
3367
3368 Page authors can provide the supplied values by using the viewport meta tag. More information
3369 about this can be found at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
3370
3371 \sa QWebPage::ViewportAttributes, setPreferredContentsSize(), QGraphicsWebView::setScale()
3372*/
3373
3374/*!
3375 \fn void QWebPage::loadStarted()
3376
3377 This signal is emitted when a page starts loading content.
3378
3379 \sa loadFinished()
3380*/
3381
3382/*!
3383 \fn void QWebPage::loadProgress(int progress)
3384
3385 This signal is emitted when the global progress status changes.
3386 The current value is provided by \a progress and scales from 0 to 100,
3387 which is the default range of QProgressBar.
3388 It accumulates changes from all the child frames.
3389
3390 \sa bytesReceived()
3391*/
3392
3393/*!
3394 \fn void QWebPage::loadFinished(bool ok)
3395
3396 This signal is emitted when the page finishes loading content. This signal
3397 is independant of script execution or page rendering.
3398 \a ok will indicate whether the load was successful or any error occurred.
3399
3400 \sa loadStarted(), ErrorPageExtension
3401*/
3402
3403/*!
3404 \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
3405
3406 This signal is emitted when the mouse hovers over a link.
3407
3408 \a link contains the link url.
3409 \a title is the link element's title, if it is specified in the markup.
3410 \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
3411
3412 When the mouse leaves the link element the signal is emitted with empty parameters.
3413
3414 \sa linkClicked()
3415*/
3416
3417/*!
3418 \fn void QWebPage::statusBarMessage(const QString& text)
3419
3420 This signal is emitted when the statusbar \a text is changed by the page.
3421*/
3422
3423/*!
3424 \fn void QWebPage::frameCreated(QWebFrame *frame)
3425
3426 This signal is emitted whenever the page creates a new \a frame.
3427
3428 \sa currentFrame()
3429*/
3430
3431/*!
3432 \fn void QWebPage::selectionChanged()
3433
3434 This signal is emitted whenever the selection changes, either interactively
3435 or programmatically (e.g. by calling triggerAction() with a selection action).
3436
3437 \sa selectedText()
3438*/
3439
3440/*!
3441 \fn void QWebPage::contentsChanged()
3442 \since 4.5
3443
3444 This signal is emitted whenever the text in form elements changes
3445 as well as other editable content.
3446
3447 \sa contentEditable, modified, QWebFrame::toHtml(), QWebFrame::toPlainText()
3448*/
3449
3450/*!
3451 \fn void QWebPage::geometryChangeRequested(const QRect& geom)
3452
3453 This signal is emitted whenever the document wants to change the position and size of the
3454 page to \a geom. This can happen for example through JavaScript.
3455*/
3456
3457/*!
3458 \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
3459
3460 This signal is emitted whenever this QWebPage should be updated. It's useful
3461 when rendering a QWebPage without a QWebView or QGraphicsWebView.
3462 \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
3463 the mainFrame() and call the render(QPainter*, const QRegion&) method with the
3464 \a dirtyRect as the second parameter.
3465
3466 \sa mainFrame()
3467 \sa view()
3468*/
3469
3470/*!
3471 \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
3472
3473 This signal is emitted whenever the content given by \a rectToScroll needs
3474 to be scrolled \a dx and \a dy downwards.
3475*/
3476
3477/*!
3478 \fn void QWebPage::windowCloseRequested()
3479
3480 This signal is emitted whenever the page requests the web browser window to be closed,
3481 for example through the JavaScript \c{window.close()} call.
3482*/
3483
3484/*!
3485 \fn void QWebPage::printRequested(QWebFrame *frame)
3486
3487 This signal is emitted whenever the page requests the web browser to print \a frame,
3488 for example through the JavaScript \c{window.print()} call.
3489
3490 \sa QWebFrame::print(), QPrintPreviewDialog
3491*/
3492
3493/*!
3494 \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
3495
3496 This signal is emitted when WebKit cannot handle a link the user navigated to or a
3497 web server's response includes a "Content-Disposition" header with the 'attachment'
3498 directive. If "Content-Disposition" is present in \a reply, the web server is indicating
3499 that the client should prompt the user to save the content regardless of content-type.
3500 See RFC 2616 sections 19.5.1 for details about Content-Disposition.
3501
3502 At signal emission time the meta-data of the QNetworkReply \a reply is available.
3503
3504 \note The receiving slot is responsible for deleting the QNetworkReply \a reply.
3505
3506 \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
3507
3508 \sa downloadRequested()
3509*/
3510
3511/*!
3512 \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
3513
3514 This signal is emitted when the user decides to download a link. The url of
3515 the link as well as additional meta-information is contained in \a request.
3516
3517 \sa unsupportedContent()
3518*/
3519
3520/*!
3521 \fn void QWebPage::microFocusChanged()
3522
3523 This signal is emitted when for example the position of the cursor in an editable form
3524 element changes. It is used to inform input methods about the new on-screen position where
3525 the user is able to enter text. This signal is usually connected to the
3526 QWidget::updateMicroFocus() slot.
3527*/
3528
3529/*!
3530 \fn void QWebPage::linkClicked(const QUrl &url)
3531
3532 This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
3533 property is set to delegate the link handling for the specified \a url.
3534
3535 By default no links are delegated and are handled by QWebPage instead.
3536
3537 \note This signal possibly won't be emitted for clicked links which use
3538 JavaScript to trigger navigation.
3539
3540 \sa linkHovered()
3541*/
3542
3543/*!
3544 \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
3545
3546 This signal is emitted whenever the visibility of the toolbar in a web browser
3547 window that hosts QWebPage should be changed to \a visible.
3548*/
3549
3550/*!
3551 \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
3552
3553 This signal is emitted whenever the visibility of the statusbar in a web browser
3554 window that hosts QWebPage should be changed to \a visible.
3555*/
3556
3557/*!
3558 \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
3559
3560 This signal is emitted whenever the visibility of the menubar in a web browser
3561 window that hosts QWebPage should be changed to \a visible.
3562*/
3563
3564/*!
3565 \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
3566 \since 4.5
3567
3568 This signal is emitted whenever the web site shown in \a frame is asking to store data
3569 to the database \a databaseName and the quota allocated to that web site is exceeded.
3570
3571 \sa QWebDatabase
3572*/
3573/*!
3574 \fn void QWebPage::applicationCacheQuotaExceeded(QWebSecurityOrigin* origin, quint64 defaultOriginQuota, quint64 totalSpaceNeeded);
3575
3576 This signal is emitted whenever the web site is asking to store data to the application cache
3577 database databaseName and the quota allocated to that web site is exceeded.
3578
3579*/
3580
3581/*!
3582 \since 4.5
3583 \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
3584
3585 This signal is emitted shortly before the history of navigated pages
3586 in \a frame is changed, for example when navigating back in the history.
3587
3588 The provided QWebHistoryItem, \a item, holds the history entry of the frame before
3589 the change.
3590
3591 A potential use-case for this signal is to store custom data in
3592 the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
3593*/
3594
3595/*!
3596 \since 4.5
3597 \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
3598
3599 This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
3600*/
3601
3602#include "moc_qwebpage.cpp"
3603