2 Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies)
3 Copyright (C) 2007 Staikos Computing Services Inc.
4 Copyright (C) 2007 Apple Inc.
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.
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.
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.
26 #include "qwebframe.h"
27 #include "qwebpage_p.h"
28 #include "qwebframe_p.h"
29 #include "qwebhistory.h"
30 #include "qwebhistory_p.h"
31 #include "qwebinspector.h"
32 #include "qwebinspector_p.h"
33 #include "qwebsettings.h"
34 #include "qwebkitplatformplugin.h"
35 #include "qwebkitversion.h"
37 #include "CSSComputedStyleDeclaration.h"
38 #include "CSSParser.h"
39 #include "ApplicationCacheStorage.h"
40 #include "BackForwardListImpl.h"
41 #include "MemoryCache.h"
43 #include "ChromeClientQt.h"
44 #include "ClientRect.h"
45 #include "ContextMenu.h"
46 #include "ContextMenuClientQt.h"
47 #include "ContextMenuController.h"
48 #include "DeviceMotionClientQt.h"
49 #include "DeviceOrientationClientQt.h"
50 #include "DocumentLoader.h"
51 #include "DragClientQt.h"
52 #include "DragController.h"
55 #include "EditorClientQt.h"
56 #include "FocusController.h"
57 #include "FormState.h"
59 #include "FrameLoadRequest.h"
60 #include "FrameLoader.h"
61 #include "FrameLoader.h"
62 #include "FrameLoaderClientQt.h"
63 #include "FrameTree.h"
64 #include "FrameView.h"
65 #if ENABLE(CLIENT_BASED_GEOLOCATION)
66 #include "GeolocationClientMock.h"
67 #include "GeolocationClientQt.h"
68 #endif // CLIENT_BASED_GEOLOCATION
69 #include "GeolocationPermissionClientQt.h"
70 #include "HTMLFormElement.h"
71 #include "HTMLFrameOwnerElement.h"
72 #include "HTMLInputElement.h"
73 #include "HTMLNames.h"
75 #include "HitTestResult.h"
77 #include "InspectorClientQt.h"
78 #include "InspectorController.h"
79 #include "InspectorServerQt.h"
81 #include "LocalizedStrings.h"
83 #include "MIMETypeRegistry.h"
84 #include "NavigationAction.h"
85 #include "NetworkingContext.h"
87 #include "NotificationPresenterClientQt.h"
88 #include "NotImplemented.h"
90 #include "PageClientQt.h"
91 #include "PageGroup.h"
92 #include "Pasteboard.h"
93 #include "PlatformKeyboardEvent.h"
94 #include "PlatformTouchEvent.h"
95 #include "PlatformWheelEvent.h"
96 #include "PluginDatabase.h"
97 #include "PluginDatabase.h"
98 #include "PluginPackage.h"
99 #include "ProgressTracker.h"
100 #include "QtPlatformPlugin.h"
102 #include "RenderTextControl.h"
103 #include "SchemeRegistry.h"
104 #include "Scrollbar.h"
105 #include "SecurityOrigin.h"
106 #include "Settings.h"
107 #if defined Q_OS_WIN32
108 #include "SystemInfo.h"
110 #include "TextIterator.h"
111 #include "WebPlatformStrategies.h"
113 #include "WebSystemInterface.h"
115 #include "WindowFeatures.h"
116 #include "WorkerThread.h"
117 #include <runtime/InitializeThreading.h>
118 #include <wtf/MainThread.h>
120 #include <QApplication>
121 #include <QBasicTimer>
124 #include <QDesktopWidget>
125 #include <QDragEnterEvent>
126 #include <QDragLeaveEvent>
127 #include <QDragMoveEvent>
128 #include <QDropEvent>
129 #include <QFileDialog>
130 #include <QHttpRequestHeader>
131 #include <QInputDialog>
132 #include <QMessageBox>
133 #include <QNetworkProxy>
134 #include <QUndoStack>
137 #include <QClipboard>
138 #include <QSslSocket>
141 #include <QTextCharFormat>
142 #include <QTextDocument>
143 #include <QTouchEvent>
144 #include <QNetworkAccessManager>
145 #include <QNetworkRequest>
146 #if defined(Q_WS_X11)
149 #if USE(QT_MOBILITY_SYSTEMINFO)
150 #include <qsysteminfo.h>
153 using namespace WebCore;
155 // from text/qfont.cpp
157 extern Q_GUI_EXPORT int qt_defaultDpi();
160 bool QWebPagePrivate::drtRun = false;
162 // Lookup table mapping QWebPage::WebActions to the associated Editor commands
163 static const char* editorCommandWebActions[] =
167 0, // OpenLinkInNewWindow,
168 0, // OpenFrameInNewWindow,
170 0, // DownloadLinkToDisk,
171 0, // CopyLinkToClipboard,
173 0, // OpenImageInNewWindow,
174 0, // DownloadImageToDisk,
175 0, // CopyImageToClipboard,
188 "MoveForward", // MoveToNextChar,
189 "MoveBackward", // MoveToPreviousChar,
190 "MoveWordForward", // MoveToNextWord,
191 "MoveWordBackward", // MoveToPreviousWord,
192 "MoveDown", // MoveToNextLine,
193 "MoveUp", // MoveToPreviousLine,
194 "MoveToBeginningOfLine", // MoveToStartOfLine,
195 "MoveToEndOfLine", // MoveToEndOfLine,
196 "MoveToBeginningOfParagraph", // MoveToStartOfBlock,
197 "MoveToEndOfParagraph", // MoveToEndOfBlock,
198 "MoveToBeginningOfDocument", // MoveToStartOfDocument,
199 "MoveToEndOfDocument", // MoveToEndOfDocument,
200 "MoveForwardAndModifySelection", // SelectNextChar,
201 "MoveBackwardAndModifySelection", // SelectPreviousChar,
202 "MoveWordForwardAndModifySelection", // SelectNextWord,
203 "MoveWordBackwardAndModifySelection", // SelectPreviousWord,
204 "MoveDownAndModifySelection", // SelectNextLine,
205 "MoveUpAndModifySelection", // SelectPreviousLine,
206 "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine,
207 "MoveToEndOfLineAndModifySelection", // SelectEndOfLine,
208 "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock,
209 "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock,
210 "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument,
211 "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument,
212 "DeleteWordBackward", // DeleteStartOfWord,
213 "DeleteWordForward", // DeleteEndOfWord,
215 0, // SetTextDirectionDefault,
216 0, // SetTextDirectionLeftToRight,
217 0, // SetTextDirectionRightToLeft,
219 "ToggleBold", // ToggleBold,
220 "ToggleItalic", // ToggleItalic,
221 "ToggleUnderline", // ToggleUnderline,
223 0, // InspectElement,
225 "InsertNewline", // InsertParagraphSeparator
226 "InsertLineBreak", // InsertLineSeparator
228 "SelectAll", // SelectAll
229 0, // ReloadAndBypassCache,
231 "PasteAndMatchStyle", // PasteAndMatchStyle
232 "RemoveFormat", // RemoveFormat
233 "Strikethrough", // ToggleStrikethrough,
234 "Subscript", // ToggleSubscript
235 "Superscript", // ToggleSuperscript
236 "InsertUnorderedList", // InsertUnorderedList
237 "InsertOrderedList", // InsertOrderedList
239 "Outdent", // Outdent,
241 "AlignCenter", // AlignCenter,
242 "AlignJustified", // AlignJustified,
243 "AlignLeft", // AlignLeft,
244 "AlignRight", // AlignRight,
246 0, // StopScheduledPageRefresh,
248 0, // CopyImageUrlToClipboard,
253 // Lookup the appropriate editor command to use for WebAction \a action
254 const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action)
256 if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*))))
257 return editorCommandWebActions[action];
261 static inline DragOperation dropActionToDragOp(Qt::DropActions actions)
264 if (actions & Qt::CopyAction)
265 result |= DragOperationCopy;
266 // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
267 // hence it should be considered as "move"
268 if (actions & Qt::MoveAction)
269 result |= (DragOperationMove | DragOperationGeneric);
270 if (actions & Qt::LinkAction)
271 result |= DragOperationLink;
272 if (result == (DragOperationCopy | DragOperationMove | DragOperationGeneric | DragOperationLink))
273 result = DragOperationEvery;
274 return (DragOperation)result;
277 static inline Qt::DropAction dragOpToDropAction(unsigned actions)
279 Qt::DropAction result = Qt::IgnoreAction;
280 if (actions & DragOperationCopy)
281 result = Qt::CopyAction;
282 else if (actions & DragOperationMove)
283 result = Qt::MoveAction;
284 // DragOperationgeneric represents InternetExplorer's equivalent of Move operation,
285 // hence it should be considered as "move"
286 else if (actions & DragOperationGeneric)
287 result = Qt::MoveAction;
288 else if (actions & DragOperationLink)
289 result = Qt::LinkAction;
293 QWebPagePrivate::QWebPagePrivate(QWebPage *qq)
296 #ifndef QT_NO_UNDOSTACK
299 , insideOpenCall(false)
302 , clickCausedFocus(false)
304 , forwardUnsupportedContent(false)
305 , smartInsertDeleteEnabled(true)
306 , selectTrailingWhitespaceEnabled(false)
307 , linkPolicy(QWebPage::DontDelegateLinks)
308 , viewportSize(QSize(0, 0))
310 , useFixedLayout(false)
312 , inspectorFrontend(0)
314 , inspectorIsInternalOnly(false)
315 , m_lastDropAction(Qt::IgnoreAction)
317 WebCore::InitializeLoggingChannelsIfNecessary();
318 ScriptController::initializeThreading();
319 WTF::initializeMainThread();
320 WebCore::SecurityOrigin::setLocalLoadPolicy(WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
322 WebPlatformStrategies::initialize();
325 InitWebCoreSystemInterface();
328 Page::PageClients pageClients;
329 pageClients.chromeClient = new ChromeClientQt(q);
330 pageClients.contextMenuClient = new ContextMenuClientQt();
331 pageClients.editorClient = new EditorClientQt(q);
332 pageClients.dragClient = new DragClientQt(q);
333 pageClients.inspectorClient = new InspectorClientQt(q);
334 #if ENABLE(DEVICE_ORIENTATION)
335 pageClients.deviceOrientationClient = new DeviceOrientationClientQt(q);
336 pageClients.deviceMotionClient = new DeviceMotionClientQt(q);
338 #if ENABLE(CLIENT_BASED_GEOLOCATION)
339 if (QWebPagePrivate::drtRun)
340 pageClients.geolocationClient = new GeolocationClientMock();
342 pageClients.geolocationClient = new GeolocationClientQt(q);
344 page = new Page(pageClients);
346 // By default each page is put into their own unique page group, which affects popup windows
347 // and visited links. Page groups (per process only) is a feature making it possible to use
348 // separate settings for each group, so that for instance an integrated browser/email reader
349 // can use different settings for displaying HTML pages and HTML email. To make QtWebKit work
350 // as expected out of the box, we use a default group similar to what other ports are doing.
351 page->setGroupName("Default Group");
353 #if ENABLE(CLIENT_BASED_GEOLOCATION)
354 // In case running in DumpRenderTree mode set the controller to mock provider.
355 if (QWebPagePrivate::drtRun)
356 static_cast<GeolocationClientMock*>(pageClients.geolocationClient)->setController(page->geolocationController());
358 settings = new QWebSettings(page->settings());
360 history.d = new QWebHistoryPrivate(static_cast<WebCore::BackForwardListImpl*>(page->backForwardList()));
361 memset(actions, 0, sizeof(actions));
363 PageGroup::setShouldTrackVisitedLinks(true);
365 #if ENABLE(NOTIFICATIONS)
366 NotificationPresenterClientQt::notificationPresenter()->addClient();
370 QWebPagePrivate::~QWebPagePrivate()
372 if (inspector && inspectorIsInternalOnly) {
373 // Since we have to delete an internal inspector,
374 // call setInspector(0) directly to prevent potential crashes
377 #ifndef QT_NO_CONTEXTMENU
378 delete currentContextMenu.data();
380 #ifndef QT_NO_UNDOSTACK
387 inspector->setPage(0);
389 #if ENABLE(NOTIFICATIONS)
390 NotificationPresenterClientQt::notificationPresenter()->removeClient();
394 WebCore::ViewportArguments QWebPagePrivate::viewportArguments()
396 return page ? page->viewportArguments() : WebCore::ViewportArguments();
399 WebCore::Page* QWebPagePrivate::core(const QWebPage* page)
401 return page->d->page;
404 QWebPagePrivate* QWebPagePrivate::priv(QWebPage* page)
409 bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
412 && frame == mainFrame.data())
414 return q->acceptNavigationRequest(frame, request, type);
417 void QWebPagePrivate::createMainFrame()
420 QWebFrameData frameData(page);
421 mainFrame = new QWebFrame(q, &frameData);
423 emit q->frameCreated(mainFrame.data());
427 static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action)
430 case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink;
431 case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow;
432 case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk;
433 case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard;
434 case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow;
435 case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk;
436 case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard;
437 case WebCore::ContextMenuItemTagCopyImageUrlToClipboard: return QWebPage::CopyImageUrlToClipboard;
438 case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow;
439 case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy;
440 case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back;
441 case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward;
442 case WebCore::ContextMenuItemTagStop: return QWebPage::Stop;
443 case WebCore::ContextMenuItemTagReload: return QWebPage::Reload;
444 case WebCore::ContextMenuItemTagCut: return QWebPage::Cut;
445 case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste;
446 case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault;
447 case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight;
448 case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft;
449 case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold;
450 case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic;
451 case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline;
452 case WebCore::ContextMenuItemTagSelectAll: return QWebPage::SelectAll;
453 #if ENABLE(INSPECTOR)
454 case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement;
458 return QWebPage::NoWebAction;
461 #ifndef QT_NO_CONTEXTMENU
462 QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu,
463 const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions)
465 if (!client || !webcoreMenu)
468 QMenu* menu = new QMenu(client->ownerWidget());
469 for (int i = 0; i < items->count(); ++i) {
470 const ContextMenuItem &item = items->at(i);
471 switch (item.type()) {
472 case WebCore::CheckableActionType: /* fall through */
473 case WebCore::ActionType: {
474 QWebPage::WebAction action = webActionForContextMenuAction(item.action());
475 QAction *a = q->action(action);
477 ContextMenuItem it(item);
478 page->contextMenuController()->checkOrEnableIfNeeded(it);
479 PlatformMenuItemDescription desc = it.releasePlatformDescription();
480 a->setEnabled(desc.enabled);
481 a->setChecked(desc.checked);
482 a->setCheckable(item.type() == WebCore::CheckableActionType);
485 visitedWebActions->setBit(action);
489 case WebCore::SeparatorType:
490 menu->addSeparator();
492 case WebCore::SubmenuType: {
493 QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions);
495 bool anyEnabledAction = false;
497 QList<QAction *> actions = subMenu->actions();
498 for (int i = 0; i < actions.count(); ++i) {
499 if (actions.at(i)->isVisible())
500 anyEnabledAction |= actions.at(i)->isEnabled();
503 // don't show sub-menus with just disabled actions
504 if (anyEnabledAction) {
505 subMenu->setTitle(item.title());
506 menu->addAction(subMenu->menuAction());
515 #endif // QT_NO_CONTEXTMENU
518 void QWebPagePrivate::_q_webActionTriggered(bool checked)
520 QAction *a = qobject_cast<QAction *>(q->sender());
523 QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt());
524 q->triggerAction(action, checked);
526 #endif // QT_NO_ACTION
528 void QWebPagePrivate::_q_cleanupLeakMessages()
531 // Need this to make leak messages accurate.
532 memoryCache()->setCapacities(0, 0, 0);
536 void QWebPagePrivate::updateAction(QWebPage::WebAction action)
541 QAction *a = actions[action];
542 if (!a || !mainFrame)
545 WebCore::FrameLoader *loader = mainFrame.data()->d->frame->loader();
546 WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor();
548 bool enabled = a->isEnabled();
549 bool checked = a->isChecked();
553 enabled = page->canGoBackOrForward(-1);
555 case QWebPage::Forward:
556 enabled = page->canGoBackOrForward(1);
559 enabled = loader->isLoading();
561 case QWebPage::Reload:
562 case QWebPage::ReloadAndBypassCache:
563 enabled = !loader->isLoading();
565 #ifndef QT_NO_UNDOSTACK
568 // those two are handled by QUndoStack
570 #endif // QT_NO_UNDOSTACK
571 case QWebPage::SelectAll: // editor command is always enabled
573 case QWebPage::SetTextDirectionDefault:
574 case QWebPage::SetTextDirectionLeftToRight:
575 case QWebPage::SetTextDirectionRightToLeft:
576 enabled = editor->canEdit();
580 // see if it's an editor command
581 const char* commandName = editorCommandForWebActions(action);
583 // if it's an editor command, let it's logic determine state
585 Editor::Command command = editor->command(commandName);
586 enabled = command.isEnabled();
588 checked = command.state() != FalseTriState;
596 a->setEnabled(enabled);
598 if (a->isCheckable())
599 a->setChecked(checked);
600 #endif // QT_NO_ACTION
603 void QWebPagePrivate::updateNavigationActions()
605 updateAction(QWebPage::Back);
606 updateAction(QWebPage::Forward);
607 updateAction(QWebPage::Stop);
608 updateAction(QWebPage::Reload);
609 updateAction(QWebPage::ReloadAndBypassCache);
612 void QWebPagePrivate::updateEditorActions()
614 updateAction(QWebPage::Cut);
615 updateAction(QWebPage::Copy);
616 updateAction(QWebPage::Paste);
617 updateAction(QWebPage::MoveToNextChar);
618 updateAction(QWebPage::MoveToPreviousChar);
619 updateAction(QWebPage::MoveToNextWord);
620 updateAction(QWebPage::MoveToPreviousWord);
621 updateAction(QWebPage::MoveToNextLine);
622 updateAction(QWebPage::MoveToPreviousLine);
623 updateAction(QWebPage::MoveToStartOfLine);
624 updateAction(QWebPage::MoveToEndOfLine);
625 updateAction(QWebPage::MoveToStartOfBlock);
626 updateAction(QWebPage::MoveToEndOfBlock);
627 updateAction(QWebPage::MoveToStartOfDocument);
628 updateAction(QWebPage::MoveToEndOfDocument);
629 updateAction(QWebPage::SelectNextChar);
630 updateAction(QWebPage::SelectPreviousChar);
631 updateAction(QWebPage::SelectNextWord);
632 updateAction(QWebPage::SelectPreviousWord);
633 updateAction(QWebPage::SelectNextLine);
634 updateAction(QWebPage::SelectPreviousLine);
635 updateAction(QWebPage::SelectStartOfLine);
636 updateAction(QWebPage::SelectEndOfLine);
637 updateAction(QWebPage::SelectStartOfBlock);
638 updateAction(QWebPage::SelectEndOfBlock);
639 updateAction(QWebPage::SelectStartOfDocument);
640 updateAction(QWebPage::SelectEndOfDocument);
641 updateAction(QWebPage::DeleteStartOfWord);
642 updateAction(QWebPage::DeleteEndOfWord);
643 updateAction(QWebPage::SetTextDirectionDefault);
644 updateAction(QWebPage::SetTextDirectionLeftToRight);
645 updateAction(QWebPage::SetTextDirectionRightToLeft);
646 updateAction(QWebPage::ToggleBold);
647 updateAction(QWebPage::ToggleItalic);
648 updateAction(QWebPage::ToggleUnderline);
649 updateAction(QWebPage::InsertParagraphSeparator);
650 updateAction(QWebPage::InsertLineSeparator);
651 updateAction(QWebPage::PasteAndMatchStyle);
652 updateAction(QWebPage::RemoveFormat);
653 updateAction(QWebPage::ToggleStrikethrough);
654 updateAction(QWebPage::ToggleSubscript);
655 updateAction(QWebPage::ToggleSuperscript);
656 updateAction(QWebPage::InsertUnorderedList);
657 updateAction(QWebPage::InsertOrderedList);
658 updateAction(QWebPage::Indent);
659 updateAction(QWebPage::Outdent);
660 updateAction(QWebPage::AlignCenter);
661 updateAction(QWebPage::AlignJustified);
662 updateAction(QWebPage::AlignLeft);
663 updateAction(QWebPage::AlignRight);
666 void QWebPagePrivate::timerEvent(QTimerEvent *ev)
668 int timerId = ev->timerId();
669 if (timerId == tripleClickTimer.timerId())
670 tripleClickTimer.stop();
676 void QWebPagePrivate::mouseMoveEvent(T* ev)
678 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
682 bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0));
683 ev->setAccepted(accepted);
687 void QWebPagePrivate::mousePressEvent(T* ev)
689 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
693 RefPtr<WebCore::Node> oldNode;
694 Frame* focusedFrame = page->focusController()->focusedFrame();
695 if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
696 oldNode = focusedDocument->focusedNode();
698 if (tripleClickTimer.isActive()
699 && (ev->pos() - tripleClick).manhattanLength()
700 < QApplication::startDragDistance()) {
701 mouseTripleClickEvent(ev);
705 bool accepted = false;
706 adjustPointForClicking(ev);
707 PlatformMouseEvent mev(ev, 1);
708 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
709 if (mev.button() != NoButton)
710 accepted = frame->eventHandler()->handleMousePressEvent(mev);
711 ev->setAccepted(accepted);
713 RefPtr<WebCore::Node> newNode;
714 focusedFrame = page->focusController()->focusedFrame();
715 if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0)
716 newNode = focusedDocument->focusedNode();
718 if (newNode && oldNode != newNode)
719 clickCausedFocus = true;
723 void QWebPagePrivate::mouseDoubleClickEvent(T *ev)
725 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
729 bool accepted = false;
730 PlatformMouseEvent mev(ev, 2);
731 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
732 if (mev.button() != NoButton)
733 accepted = frame->eventHandler()->handleMousePressEvent(mev);
734 ev->setAccepted(accepted);
736 tripleClickTimer.start(QApplication::doubleClickInterval(), q);
737 tripleClick = QPointF(ev->pos()).toPoint();
741 void QWebPagePrivate::mouseTripleClickEvent(T *ev)
743 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
747 bool accepted = false;
748 PlatformMouseEvent mev(ev, 3);
749 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
750 if (mev.button() != NoButton)
751 accepted = frame->eventHandler()->handleMousePressEvent(mev);
752 ev->setAccepted(accepted);
755 void QWebPagePrivate::handleClipboard(QEvent* ev, Qt::MouseButton button)
757 #ifndef QT_NO_CLIPBOARD
758 if (QApplication::clipboard()->supportsSelection()) {
759 bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
760 Pasteboard::generalPasteboard()->setSelectionMode(true);
761 WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame();
762 if (button == Qt::LeftButton) {
763 if (focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) {
764 Pasteboard::generalPasteboard()->writeSelection(focusFrame->editor()->selectedRange().get(), focusFrame->editor()->canSmartCopyOrDelete(), focusFrame);
765 ev->setAccepted(true);
767 } else if (button == Qt::MidButton) {
768 if (focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) {
769 focusFrame->editor()->paste();
770 ev->setAccepted(true);
773 Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
779 void QWebPagePrivate::mouseReleaseEvent(T *ev)
781 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
785 bool accepted = false;
786 adjustPointForClicking(ev);
787 PlatformMouseEvent mev(ev, 0);
788 // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton
789 if (mev.button() != NoButton)
790 accepted = frame->eventHandler()->handleMouseReleaseEvent(mev);
791 ev->setAccepted(accepted);
793 handleClipboard(ev, ev->button());
794 handleSoftwareInputPanel(ev->button(), QPointF(ev->pos()).toPoint());
797 void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button, const QPoint& pos)
799 Frame* frame = page->focusController()->focusedFrame();
803 if (client && client->inputMethodEnabled()
804 && frame->document()->focusedNode()
805 && button == Qt::LeftButton && qApp->autoSipEnabled()) {
806 QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel(
807 client->ownerWidget()->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
808 if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) {
809 HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(frame->view()->windowToContents(pos), false);
810 if (result.isContentEditable()) {
811 QEvent event(QEvent::RequestSoftwareInputPanel);
812 QApplication::sendEvent(client->ownerWidget(), &event);
817 clickCausedFocus = false;
820 #ifndef QT_NO_CONTEXTMENU
821 void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos)
823 QMenu *menu = q->createStandardContextMenu();
825 menu->exec(globalPos);
829 #endif // QT_NO_CONTEXTMENU
833 This function creates the standard context menu which is shown when
834 the user clicks on the web page with the right mouse button. It is
835 called from the default contextMenuEvent() handler. The popup menu's
836 ownership is transferred to the caller.
838 QMenu *QWebPage::createStandardContextMenu()
840 #ifndef QT_NO_CONTEXTMENU
841 QMenu* menu = d->currentContextMenu.data();
842 d->currentContextMenu.clear();
849 #ifndef QT_NO_WHEELEVENT
851 void QWebPagePrivate::wheelEvent(T *ev)
853 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
857 WebCore::PlatformWheelEvent pev(ev);
858 bool accepted = frame->eventHandler()->handleWheelEvent(pev);
859 ev->setAccepted(accepted);
861 #endif // QT_NO_WHEELEVENT
863 #ifndef QT_NO_SHORTCUT
864 QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event)
867 QKeySequence::StandardKey standardKey;
868 QWebPage::WebAction action;
869 } editorActions[] = {
870 { QKeySequence::Cut, QWebPage::Cut },
871 { QKeySequence::Copy, QWebPage::Copy },
872 { QKeySequence::Paste, QWebPage::Paste },
873 { QKeySequence::Undo, QWebPage::Undo },
874 { QKeySequence::Redo, QWebPage::Redo },
875 { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar },
876 { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar },
877 { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord },
878 { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord },
879 { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine },
880 { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine },
881 { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine },
882 { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine },
883 { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock },
884 { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock },
885 { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument },
886 { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument },
887 { QKeySequence::SelectNextChar, QWebPage::SelectNextChar },
888 { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar },
889 { QKeySequence::SelectNextWord, QWebPage::SelectNextWord },
890 { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord },
891 { QKeySequence::SelectNextLine, QWebPage::SelectNextLine },
892 { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine },
893 { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine },
894 { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine },
895 { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock },
896 { QKeySequence::SelectEndOfBlock, QWebPage::SelectEndOfBlock },
897 { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument },
898 { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument },
899 { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord },
900 { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord },
901 { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator },
902 { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator },
903 { QKeySequence::SelectAll, QWebPage::SelectAll },
904 { QKeySequence::UnknownKey, QWebPage::NoWebAction }
907 for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
908 if (event == editorActions[i].standardKey)
909 return editorActions[i].action;
911 return QWebPage::NoWebAction;
913 #endif // QT_NO_SHORTCUT
915 void QWebPagePrivate::keyPressEvent(QKeyEvent *ev)
917 bool handled = false;
918 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
919 // we forward the key event to WebCore first to handle potential DOM
920 // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent
921 // to trigger editor commands via triggerAction().
923 handled = frame->eventHandler()->keyEvent(ev);
926 if (!handleScrolling(ev, frame)) {
929 q->triggerAction(QWebPage::Back);
931 case Qt::Key_Forward:
932 q->triggerAction(QWebPage::Forward);
935 q->triggerAction(QWebPage::Stop);
937 case Qt::Key_Refresh:
938 q->triggerAction(QWebPage::Reload);
940 case Qt::Key_Backspace:
941 if (ev->modifiers() == Qt::ShiftModifier)
942 q->triggerAction(QWebPage::Forward);
944 q->triggerAction(QWebPage::Back);
953 ev->setAccepted(handled);
956 void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev)
958 if (ev->isAutoRepeat()) {
959 ev->setAccepted(true);
963 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
964 bool handled = frame->eventHandler()->keyEvent(ev);
965 ev->setAccepted(handled);
968 void QWebPagePrivate::focusInEvent(QFocusEvent*)
970 FocusController *focusController = page->focusController();
971 focusController->setActive(true);
972 focusController->setFocused(true);
973 if (!focusController->focusedFrame())
974 focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame.data()));
977 void QWebPagePrivate::focusOutEvent(QFocusEvent*)
979 // only set the focused frame inactive so that we stop painting the caret
980 // and the focus frame. But don't tell the focus controller so that upon
981 // focusInEvent() we can re-activate the frame.
982 FocusController *focusController = page->focusController();
983 // Call setFocused first so that window.onblur doesn't get called twice
984 focusController->setFocused(false);
985 focusController->setActive(false);
989 void QWebPagePrivate::dragEnterEvent(T* ev)
991 #ifndef QT_NO_DRAGANDDROP
992 DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
993 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
994 Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData));
995 ev->setDropAction(action);
996 ev->acceptProposedAction();
1001 void QWebPagePrivate::dragLeaveEvent(T *ev)
1003 #ifndef QT_NO_DRAGANDDROP
1004 DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone);
1005 page->dragController()->dragExited(&dragData);
1011 void QWebPagePrivate::dragMoveEvent(T *ev)
1013 #ifndef QT_NO_DRAGANDDROP
1014 DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1015 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1016 m_lastDropAction = dragOpToDropAction(page->dragController()->dragUpdated(&dragData));
1017 ev->setDropAction(m_lastDropAction);
1018 if (m_lastDropAction != Qt::IgnoreAction)
1024 void QWebPagePrivate::dropEvent(T *ev)
1026 #ifndef QT_NO_DRAGANDDROP
1027 DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(),
1028 QCursor::pos(), dropActionToDragOp(ev->possibleActions()));
1029 if (page->dragController()->performDrag(&dragData)) {
1030 ev->setDropAction(m_lastDropAction);
1036 void QWebPagePrivate::leaveEvent(QEvent*)
1038 // Fake a mouse move event just outside of the widget, since all
1039 // the interesting mouse-out behavior like invalidating scrollbars
1040 // is handled by the WebKit event handler's mouseMoved function.
1041 QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
1042 mouseMoveEvent(&fakeEvent);
1046 \property QWebPage::palette
1047 \brief the page's palette
1049 The base brush of the palette is used to draw the background of the main frame.
1051 By default, this property contains the application's default palette.
1053 void QWebPage::setPalette(const QPalette &pal)
1056 if (!d->mainFrame || !d->mainFrame.data()->d->frame->view())
1059 QBrush brush = pal.brush(QPalette::Base);
1060 QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
1061 QWebFramePrivate::core(d->mainFrame.data())->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha());
1064 QPalette QWebPage::palette() const
1069 void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
1071 WebCore::Frame *frame = page->focusController()->focusedOrMainFrame();
1072 WebCore::Editor *editor = frame->editor();
1074 if (!editor->canEdit()) {
1080 if (frame->selection()->rootEditableElement())
1081 node = frame->selection()->rootEditableElement()->shadowAncestorNode();
1083 Vector<CompositionUnderline> underlines;
1084 bool hasSelection = false;
1086 for (int i = 0; i < ev->attributes().size(); ++i) {
1087 const QInputMethodEvent::Attribute& a = ev->attributes().at(i);
1089 case QInputMethodEvent::TextFormat: {
1090 QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat();
1091 QColor qcolor = textCharFormat.underlineColor();
1092 underlines.append(CompositionUnderline(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)), Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())), false));
1095 case QInputMethodEvent::Cursor: {
1096 frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible
1098 RenderObject* caretRenderer = frame->selection()->caretRenderer();
1099 if (caretRenderer) {
1100 QColor qcolor = a.value.value<QColor>();
1101 caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha())));
1106 case QInputMethodEvent::Selection: {
1107 hasSelection = true;
1108 // A selection in the inputMethodEvent is always reflected in the visible text
1110 if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
1111 textControl->setSelectionRange(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1114 if (!ev->preeditString().isEmpty())
1115 editor->setComposition(ev->preeditString(), underlines, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
1117 // If we are in the middle of a composition, an empty pre-edit string and a selection of zero
1118 // cancels the current composition
1119 if (editor->hasComposition() && (a.start + a.length == 0))
1120 editor->setComposition(QString(), underlines, 0, 0);
1129 if (node && ev->replacementLength() > 0) {
1130 int cursorPos = frame->selection()->extent().offsetInContainerNode();
1131 int start = cursorPos + ev->replacementStart();
1132 if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
1133 textControl->setSelectionRange(start, start + ev->replacementLength());
1134 // Commit regardless of whether commitString is empty, to get rid of selection.
1135 editor->confirmComposition(ev->commitString());
1136 } else if (!ev->commitString().isEmpty()) {
1137 if (editor->hasComposition())
1138 editor->confirmComposition(ev->commitString());
1140 editor->insertText(ev->commitString(), 0);
1141 } else if (!hasSelection && !ev->preeditString().isEmpty())
1142 editor->setComposition(ev->preeditString(), underlines, 0, 0);
1143 else if (ev->preeditString().isEmpty() && editor->hasComposition())
1144 editor->confirmComposition(String());
1149 #ifndef QT_NO_PROPERTIES
1152 double deferredRepaintDelay;
1153 double initialDeferredRepaintDelayDuringLoading;
1154 double maxDeferredRepaintDelayDuringLoading;
1155 double deferredRepaintDelayIncrementDuringLoading;
1156 } QRepaintThrottlingPreset;
1158 void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* event)
1160 if (event->propertyName() == "_q_viewMode") {
1161 page->setViewMode(Page::stringToViewMode(q->property("_q_viewMode").toString()));
1162 } else if (event->propertyName() == "_q_HTMLTokenizerChunkSize") {
1163 int chunkSize = q->property("_q_HTMLTokenizerChunkSize").toInt();
1164 q->handle()->page->setCustomHTMLTokenizerChunkSize(chunkSize);
1165 } else if (event->propertyName() == "_q_HTMLTokenizerTimeDelay") {
1166 double timeDelay = q->property("_q_HTMLTokenizerTimeDelay").toDouble();
1167 q->handle()->page->setCustomHTMLTokenizerTimeDelay(timeDelay);
1168 } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelay") {
1169 double p = q->property("_q_RepaintThrottlingDeferredRepaintDelay").toDouble();
1170 FrameView::setRepaintThrottlingDeferredRepaintDelay(p);
1171 } else if (event->propertyName() == "_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading") {
1172 double p = q->property("_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading").toDouble();
1173 FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(p);
1174 } else if (event->propertyName() == "_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading") {
1175 double p = q->property("_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading").toDouble();
1176 FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(p);
1177 } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading") {
1178 double p = q->property("_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading").toDouble();
1179 FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(p);
1180 } else if (event->propertyName() == "_q_RepaintThrottlingPreset") {
1181 static const QRepaintThrottlingPreset presets[] = {
1182 { "NoThrottling", 0, 0, 0, 0 },
1183 { "Legacy", 0.025, 0, 2.5, 0.5 },
1184 { "Minimal", 0.01, 0, 1, 0.2 },
1185 { "Medium", 0.025, 1, 5, 0.5 },
1186 { "Heavy", 0.1, 2, 10, 1 }
1189 QString p = q->property("_q_RepaintThrottlingPreset").toString();
1190 for (size_t i = 0; i < sizeof(presets) / sizeof(presets[0]); i++) {
1191 if (p == QLatin1String(presets[i].name)) {
1192 FrameView::setRepaintThrottlingDeferredRepaintDelay(
1193 presets[i].deferredRepaintDelay);
1194 FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(
1195 presets[i].initialDeferredRepaintDelayDuringLoading);
1196 FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(
1197 presets[i].maxDeferredRepaintDelayDuringLoading);
1198 FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(
1199 presets[i].deferredRepaintDelayIncrementDuringLoading);
1204 #if ENABLE(TILED_BACKING_STORE)
1205 else if (event->propertyName() == "_q_TiledBackingStoreTileSize") {
1206 WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1207 if (!frame->tiledBackingStore())
1209 QSize tileSize = q->property("_q_TiledBackingStoreTileSize").toSize();
1210 frame->tiledBackingStore()->setTileSize(tileSize);
1211 } else if (event->propertyName() == "_q_TiledBackingStoreTileCreationDelay") {
1212 WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1213 if (!frame->tiledBackingStore())
1215 int tileCreationDelay = q->property("_q_TiledBackingStoreTileCreationDelay").toInt();
1216 frame->tiledBackingStore()->setTileCreationDelay(static_cast<double>(tileCreationDelay) / 1000.);
1217 } else if (event->propertyName() == "_q_TiledBackingStoreKeepAreaMultiplier") {
1218 WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1219 if (!frame->tiledBackingStore())
1221 float keepMultiplier;
1222 float coverMultiplier;
1223 frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1224 QSizeF qSize = q->property("_q_TiledBackingStoreKeepAreaMultiplier").toSizeF();
1225 // setKeepAndCoverAreaMultipliers do not use FloatSize anymore, keep only the height part.
1226 keepMultiplier = qSize.height();
1227 frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1228 } else if (event->propertyName() == "_q_TiledBackingStoreCoverAreaMultiplier") {
1229 WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame());
1230 if (!frame->tiledBackingStore())
1232 float keepMultiplier;
1233 float coverMultiplier;
1234 frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1235 QSizeF qSize = q->property("_q_TiledBackingStoreCoverAreaMultiplier").toSizeF();
1236 // setKeepAndCoverAreaMultipliers do not use FloatSize anymore, keep only the height part.
1237 coverMultiplier = qSize.height();
1238 frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier);
1241 else if (event->propertyName() == "_q_webInspectorServerPort") {
1242 InspectorServerQt* inspectorServer = InspectorServerQt::server();
1243 inspectorServer->listen(inspectorServerPort());
1244 } else if (event->propertyName() == "_q_deadDecodedDataDeletionInterval") {
1245 double interval = q->property("_q_deadDecodedDataDeletionInterval").toDouble();
1246 memoryCache()->setDeadDecodedDataDeletionInterval(interval);
1251 void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event)
1253 WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
1254 WebCore::Editor* editor = frame->editor();
1255 if (editor->canEdit()) {
1256 if (event->modifiers() == Qt::NoModifier
1257 || event->modifiers() == Qt::ShiftModifier
1258 || event->modifiers() == Qt::KeypadModifier) {
1259 if (event->key() < Qt::Key_Escape) {
1262 switch (event->key()) {
1263 case Qt::Key_Return:
1265 case Qt::Key_Delete:
1268 case Qt::Key_Backspace:
1280 #ifndef QT_NO_SHORTCUT
1281 else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction)
1287 bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame)
1289 ScrollDirection direction;
1290 ScrollGranularity granularity;
1292 #ifndef QT_NO_SHORTCUT
1293 if (ev == QKeySequence::MoveToNextPage
1294 || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) {
1295 granularity = ScrollByPage;
1296 direction = ScrollDown;
1297 } else if (ev == QKeySequence::MoveToPreviousPage
1298 || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) {
1299 granularity = ScrollByPage;
1300 direction = ScrollUp;
1302 #endif // QT_NO_SHORTCUT
1303 if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier)
1304 || ev->key() == Qt::Key_Home) {
1305 granularity = ScrollByDocument;
1306 direction = ScrollUp;
1307 } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier)
1308 || ev->key() == Qt::Key_End) {
1309 granularity = ScrollByDocument;
1310 direction = ScrollDown;
1312 switch (ev->key()) {
1314 granularity = ScrollByLine;
1315 direction = ScrollUp;
1318 granularity = ScrollByLine;
1319 direction = ScrollDown;
1322 granularity = ScrollByLine;
1323 direction = ScrollLeft;
1326 granularity = ScrollByLine;
1327 direction = ScrollRight;
1334 return frame->eventHandler()->scrollRecursively(direction, granularity);
1337 void QWebPagePrivate::adjustPointForClicking(QMouseEvent*)
1342 #if !defined(QT_NO_GRAPHICSVIEW)
1343 void QWebPagePrivate::adjustPointForClicking(QGraphicsSceneMouseEvent* ev)
1345 QtPlatformPlugin platformPlugin;
1346 OwnPtr<QWebTouchModifier> touchModifier = platformPlugin.createTouchModifier();
1350 unsigned topPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Up);
1351 unsigned rightPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Right);
1352 unsigned bottomPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Down);
1353 unsigned leftPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Left);
1355 touchModifier = nullptr;
1357 if (!topPadding && !rightPadding && !bottomPadding && !leftPadding)
1360 Document* startingDocument = page->mainFrame()->document();
1361 if (!startingDocument)
1364 IntPoint originalPoint(QPointF(ev->pos()).toPoint());
1365 TouchAdjuster touchAdjuster(topPadding, rightPadding, bottomPadding, leftPadding);
1366 IntPoint adjustedPoint = touchAdjuster.findCandidatePointForTouch(originalPoint, startingDocument);
1367 if (adjustedPoint == IntPoint::zero())
1370 ev->setPos(QPointF(adjustedPoint));
1374 bool QWebPagePrivate::touchEvent(QTouchEvent* event)
1376 #if ENABLE(TOUCH_EVENTS)
1377 WebCore::Frame* frame = QWebFramePrivate::core(mainFrame.data());
1381 // Always accept the QTouchEvent so that we'll receive also TouchUpdate and TouchEnd events
1382 event->setAccepted(true);
1384 // Return whether the default action was cancelled in the JS event handler
1385 return frame->eventHandler()->handleTouchEvent(PlatformTouchEvent(event));
1393 This method is used by the input method to query a set of properties of the page
1394 to be able to support complex input method operations as support for surrounding
1395 text and reconversions.
1397 \a property specifies which property is queried.
1399 \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext
1401 QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const
1403 Frame* frame = d->page->focusController()->focusedFrame();
1407 WebCore::Editor* editor = frame->editor();
1409 RenderObject* renderer = 0;
1410 RenderTextControl* renderTextControl = 0;
1412 if (frame->selection()->rootEditableElement())
1413 renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer();
1415 if (renderer && renderer->isTextControl())
1416 renderTextControl = toRenderTextControl(renderer);
1419 case Qt::ImMicroFocus: {
1420 WebCore::FrameView* view = frame->view();
1421 if (view && view->needsLayout()) {
1422 // We can't access absoluteCaretBounds() while the view needs to layout.
1425 return QVariant(view->contentsToWindow(frame->selection()->absoluteCaretBounds()));
1428 if (renderTextControl) {
1429 RenderStyle* renderStyle = renderTextControl->style();
1430 return QVariant(QFont(renderStyle->font().font()));
1432 return QVariant(QFont());
1434 case Qt::ImCursorPosition: {
1435 if (editor->hasComposition())
1436 return QVariant(frame->selection()->end().offsetInContainerNode());
1437 return QVariant(frame->selection()->extent().offsetInContainerNode());
1439 case Qt::ImSurroundingText: {
1440 if (renderTextControl && renderTextControl->textFormControlElement()) {
1441 QString text = renderTextControl->textFormControlElement()->value();
1442 RefPtr<Range> range = editor->compositionRange();
1444 text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get()));
1445 return QVariant(text);
1449 case Qt::ImCurrentSelection: {
1450 if (!editor->hasComposition() && renderTextControl && renderTextControl->textFormControlElement()) {
1451 int start = frame->selection()->start().offsetInContainerNode();
1452 int end = frame->selection()->end().offsetInContainerNode();
1454 return QVariant(QString(renderTextControl->textFormControlElement()->value()).mid(start, end - start));
1459 case Qt::ImAnchorPosition: {
1460 if (editor->hasComposition())
1461 return QVariant(frame->selection()->start().offsetInContainerNode());
1462 return QVariant(frame->selection()->base().offsetInContainerNode());
1464 case Qt::ImMaximumTextLength: {
1465 if (frame->selection()->isContentEditable()) {
1466 if (frame->document() && frame->document()->focusedNode()) {
1467 if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) {
1468 HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode());
1469 return QVariant(inputElement->maxLength());
1472 return QVariant(HTMLInputElement::maximumLength);
1484 void QWebPagePrivate::setInspector(QWebInspector* insp)
1487 inspector->d->setFrontend(0);
1489 if (inspectorIsInternalOnly) {
1490 QWebInspector* inspToDelete = inspector;
1492 inspectorIsInternalOnly = false;
1493 delete inspToDelete; // Delete after to prevent infinite recursion
1498 // Give inspector frontend web view if previously created
1499 if (inspector && inspectorFrontend)
1500 inspector->d->setFrontend(inspectorFrontend);
1505 Returns the inspector and creates it if it wasn't created yet.
1506 The instance created here will not be available through QWebPage's API.
1508 QWebInspector* QWebPagePrivate::getOrCreateInspector()
1510 #if ENABLE(INSPECTOR)
1512 QWebInspector* insp = new QWebInspector;
1514 inspectorIsInternalOnly = true;
1516 Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q)
1523 InspectorController* QWebPagePrivate::inspectorController()
1525 #if ENABLE(INSPECTOR)
1526 return page->inspectorController();
1532 quint16 QWebPagePrivate::inspectorServerPort()
1534 #if ENABLE(INSPECTOR) && !defined(QT_NO_PROPERTIES)
1535 if (q && q->property("_q_webInspectorServerPort").isValid())
1536 return q->property("_q_webInspectorServerPort").toInt();
1541 static bool hasMouseListener(Element* element)
1544 return element->hasEventListeners(eventNames().clickEvent)
1545 || element->hasEventListeners(eventNames().mousedownEvent)
1546 || element->hasEventListeners(eventNames().mouseupEvent);
1549 static bool isClickableElement(Element* element, RefPtr<NodeList> list)
1552 bool isClickable = hasMouseListener(element);
1553 if (!isClickable && list) {
1554 Element* parent = element->parentElement();
1555 unsigned count = list->length();
1556 for (unsigned i = 0; i < count && parent; i++) {
1557 if (list->item(i) != parent)
1560 isClickable = hasMouseListener(parent);
1564 parent = parent->parentElement();
1568 ExceptionCode ec = 0;
1570 || element->webkitMatchesSelector("a,*:link,*:visited,*[role=button],button,input,select,label", ec)
1571 || computedStyle(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer";
1574 static bool isValidFrameOwner(Element* element)
1577 return element->isFrameOwnerElement() && static_cast<HTMLFrameOwnerElement*>(element)->contentFrame();
1580 static Element* nodeToElement(Node* node)
1582 if (node && node->isElementNode())
1583 return static_cast<Element*>(node);
1587 QWebPagePrivate::TouchAdjuster::TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
1588 : m_topPadding(topPadding)
1589 , m_rightPadding(rightPadding)
1590 , m_bottomPadding(bottomPadding)
1591 , m_leftPadding(leftPadding)
1595 IntPoint QWebPagePrivate::TouchAdjuster::findCandidatePointForTouch(const IntPoint& touchPoint, Document* document) const
1600 int x = touchPoint.x();
1601 int y = touchPoint.y();
1603 RefPtr<NodeList> intersectedNodes = document->nodesFromRect(x, y, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding, false);
1604 if (!intersectedNodes)
1607 Element* closestClickableElement = 0;
1608 IntRect largestIntersectionRect;
1609 FrameView* view = document->frame()->view();
1611 // Touch rect in contents coordinates.
1612 IntRect touchRect(HitTestResult::rectForPoint(view->windowToContents(IntPoint(x, y)), m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding));
1614 // Iterate over the list of nodes hit looking for the one whose bounding area
1615 // has largest intersection with the touch area (point + padding).
1616 for (unsigned i = 0; i < intersectedNodes->length(); i++) {
1617 Node* currentNode = intersectedNodes->item(i);
1619 Element* currentElement = nodeToElement(currentNode);
1620 if (!currentElement || (!isClickableElement(currentElement, 0) && !isValidFrameOwner(currentElement)))
1623 IntRect currentElementBoundingRect = currentElement->getRect();
1624 currentElementBoundingRect.intersect(touchRect);
1626 if (currentElementBoundingRect.isEmpty())
1629 int currentIntersectionRectArea = currentElementBoundingRect.width() * currentElementBoundingRect.height();
1630 int largestIntersectionRectArea = largestIntersectionRect.width() * largestIntersectionRect.height();
1631 if (currentIntersectionRectArea > largestIntersectionRectArea) {
1632 closestClickableElement = currentElement;
1633 largestIntersectionRect = currentElementBoundingRect;
1637 if (largestIntersectionRect.isEmpty())
1640 // Handle the case when user taps a inner frame. It is done in three steps:
1641 // 1) Transform the original touch point to the inner document coordinates;
1642 // 1) Call nodesFromRect for the inner document in case;
1643 // 3) Re-add the inner frame offset (location) before passing the new clicking
1644 // position to WebCore.
1645 if (closestClickableElement->isFrameOwnerElement()) {
1646 // Adjust client coordinates' origin to be top left of inner frame viewport.
1647 PassRefPtr<ClientRect> rect = closestClickableElement->getBoundingClientRect();
1648 IntPoint newTouchPoint = touchPoint;
1649 IntSize offset = IntSize(rect->left(), rect->top());
1650 newTouchPoint -= offset;
1652 HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(closestClickableElement);
1653 Document* childDocument = owner->contentFrame()->document();
1654 return findCandidatePointForTouch(newTouchPoint, childDocument);
1656 return view->contentsToWindow(largestIntersectionRect).center();
1660 \enum QWebPage::FindFlag
1662 This enum describes the options available to the findText() function. The options
1663 can be OR-ed together from the following list:
1665 \value FindBackward Searches backwards instead of forwards.
1666 \value FindCaseSensitively By default findText() works case insensitive. Specifying this option
1667 changes the behaviour to a case sensitive find operation.
1668 \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end
1669 was reached and the text was not found.
1670 \value HighlightAllOccurrences Highlights all existing occurrences of a specific string.
1674 \enum QWebPage::LinkDelegationPolicy
1676 This enum defines the delegation policies a webpage can have when activating links and emitting
1677 the linkClicked() signal.
1679 \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all.
1680 \value DelegateExternalLinks When activating links that point to documents not stored on the
1681 local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted.
1682 \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted.
1684 \sa QWebPage::linkDelegationPolicy
1688 \enum QWebPage::NavigationType
1690 This enum describes the types of navigation available when browsing through hyperlinked
1693 \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link.
1694 \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form.
1695 \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested.
1696 \value NavigationTypeReload The user activated the reload action.
1697 \value NavigationTypeFormResubmitted An HTML form was submitted a second time.
1698 \value NavigationTypeOther A navigation to another document using a method not listed above.
1700 \sa acceptNavigationRequest()
1704 \enum QWebPage::WebAction
1706 This enum describes the types of action which can be performed on the web page.
1708 Actions only have an effect when they are applicable. The availability of
1709 actions can be be determined by checking \l{QAction::}{isEnabled()} on the
1710 action returned by action().
1712 One method of enabling the text editing, cursor movement, and text selection actions
1713 is by setting \l contentEditable to true.
1715 \value NoWebAction No action is triggered.
1716 \value OpenLink Open the current link.
1717 \value OpenLinkInNewWindow Open the current link in a new window.
1718 \value OpenFrameInNewWindow Replicate the current frame in a new window.
1719 \value DownloadLinkToDisk Download the current link to the disk.
1720 \value CopyLinkToClipboard Copy the current link to the clipboard.
1721 \value OpenImageInNewWindow Open the highlighted image in a new window.
1722 \value DownloadImageToDisk Download the highlighted image to the disk.
1723 \value CopyImageToClipboard Copy the highlighted image to the clipboard.
1724 \value CopyImageUrlToClipboard Copy the highlighted image's URL to the clipboard.
1725 \value Back Navigate back in the history of navigated links.
1726 \value Forward Navigate forward in the history of navigated links.
1727 \value Stop Stop loading the current page.
1728 \value StopScheduledPageRefresh Stop all pending page refresh/redirect requests.
1729 \value Reload Reload the current page.
1730 \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6)
1731 \value Cut Cut the content currently selected into the clipboard.
1732 \value Copy Copy the content currently selected into the clipboard.
1733 \value Paste Paste content from the clipboard.
1734 \value Undo Undo the last editing action.
1735 \value Redo Redo the last editing action.
1736 \value MoveToNextChar Move the cursor to the next character.
1737 \value MoveToPreviousChar Move the cursor to the previous character.
1738 \value MoveToNextWord Move the cursor to the next word.
1739 \value MoveToPreviousWord Move the cursor to the previous word.
1740 \value MoveToNextLine Move the cursor to the next line.
1741 \value MoveToPreviousLine Move the cursor to the previous line.
1742 \value MoveToStartOfLine Move the cursor to the start of the line.
1743 \value MoveToEndOfLine Move the cursor to the end of the line.
1744 \value MoveToStartOfBlock Move the cursor to the start of the block.
1745 \value MoveToEndOfBlock Move the cursor to the end of the block.
1746 \value MoveToStartOfDocument Move the cursor to the start of the document.
1747 \value MoveToEndOfDocument Move the cursor to the end of the document.
1748 \value SelectNextChar Select to the next character.
1749 \value SelectPreviousChar Select to the previous character.
1750 \value SelectNextWord Select to the next word.
1751 \value SelectPreviousWord Select to the previous word.
1752 \value SelectNextLine Select to the next line.
1753 \value SelectPreviousLine Select to the previous line.
1754 \value SelectStartOfLine Select to the start of the line.
1755 \value SelectEndOfLine Select to the end of the line.
1756 \value SelectStartOfBlock Select to the start of the block.
1757 \value SelectEndOfBlock Select to the end of the block.
1758 \value SelectStartOfDocument Select to the start of the document.
1759 \value SelectEndOfDocument Select to the end of the document.
1760 \value DeleteStartOfWord Delete to the start of the word.
1761 \value DeleteEndOfWord Delete to the end of the word.
1762 \value SetTextDirectionDefault Set the text direction to the default direction.
1763 \value SetTextDirectionLeftToRight Set the text direction to left-to-right.
1764 \value SetTextDirectionRightToLeft Set the text direction to right-to-left.
1765 \value ToggleBold Toggle the formatting between bold and normal weight.
1766 \value ToggleItalic Toggle the formatting between italic and normal style.
1767 \value ToggleUnderline Toggle underlining.
1768 \value InspectElement Show the Web Inspector with the currently highlighted HTML element.
1769 \value InsertParagraphSeparator Insert a new paragraph.
1770 \value InsertLineSeparator Insert a new line.
1771 \value SelectAll Selects all content.
1772 \value PasteAndMatchStyle Paste content from the clipboard with current style.
1773 \value RemoveFormat Removes formatting and style.
1774 \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style.
1775 \value ToggleSubscript Toggle the formatting between subscript and baseline.
1776 \value ToggleSuperscript Toggle the formatting between supercript and baseline.
1777 \value InsertUnorderedList Toggles the selection between an ordered list and a normal block.
1778 \value InsertOrderedList Toggles the selection between an ordered list and a normal block.
1779 \value Indent Increases the indentation of the currently selected format block by one increment.
1780 \value Outdent Decreases the indentation of the currently selected format block by one increment.
1781 \value AlignCenter Applies center alignment to content.
1782 \value AlignJustified Applies full justification to content.
1783 \value AlignLeft Applies left justification to content.
1784 \value AlignRight Applies right justification to content.
1787 \omitvalue WebActionCount
1792 \enum QWebPage::WebWindowType
1794 This enum describes the types of window that can be created by the createWindow() function.
1796 \value WebBrowserWindow The window is a regular web browser window.
1797 \value WebModalDialog The window acts as modal dialog.
1802 \class QWebPage::ViewportAttributes
1804 \brief The QWebPage::ViewportAttributes class describes hints that can be applied to a viewport.
1806 QWebPage::ViewportAttributes provides a description of a viewport, such as viewport geometry,
1807 initial scale factor with limits, plus information about whether a user should be able
1808 to scale the contents in the viewport or not, ie. by zooming.
1810 ViewportAttributes can be set by a web author using the viewport meta tag extension, documented
1811 at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}.
1813 All values might not be set, as such when dealing with the hints, the developer needs to
1814 check whether the values are valid. Negative values denote an invalid qreal value.
1820 Constructs an empty QWebPage::ViewportAttributes.
1822 QWebPage::ViewportAttributes::ViewportAttributes()
1824 , m_initialScaleFactor(-1.0)
1825 , m_minimumScaleFactor(-1.0)
1826 , m_maximumScaleFactor(-1.0)
1827 , m_devicePixelRatio(-1.0)
1828 , m_isUserScalable(true)
1835 Constructs a QWebPage::ViewportAttributes which is a copy from \a other .
1837 QWebPage::ViewportAttributes::ViewportAttributes(const QWebPage::ViewportAttributes& other)
1839 , m_initialScaleFactor(other.m_initialScaleFactor)
1840 , m_minimumScaleFactor(other.m_minimumScaleFactor)
1841 , m_maximumScaleFactor(other.m_maximumScaleFactor)
1842 , m_devicePixelRatio(other.m_devicePixelRatio)
1843 , m_isUserScalable(other.m_isUserScalable)
1844 , m_isValid(other.m_isValid)
1845 , m_size(other.m_size)
1851 Destroys the QWebPage::ViewportAttributes.
1853 QWebPage::ViewportAttributes::~ViewportAttributes()
1859 Assigns the given QWebPage::ViewportAttributes to this viewport hints and returns a
1862 QWebPage::ViewportAttributes& QWebPage::ViewportAttributes::operator=(const QWebPage::ViewportAttributes& other)
1864 if (this != &other) {
1866 m_initialScaleFactor = other.m_initialScaleFactor;
1867 m_minimumScaleFactor = other.m_minimumScaleFactor;
1868 m_maximumScaleFactor = other.m_maximumScaleFactor;
1869 m_isUserScalable = other.m_isUserScalable;
1870 m_isValid = other.m_isValid;
1871 m_size = other.m_size;
1877 /*! \fn inline bool QWebPage::ViewportAttributes::isValid() const
1878 Returns whether this is a valid ViewportAttributes or not.
1880 An invalid ViewportAttributes will have an empty QSize, negative values for scale factors and
1881 true for the boolean isUserScalable.
1884 /*! \fn inline QSize QWebPage::ViewportAttributes::size() const
1885 Returns the size of the viewport.
1888 /*! \fn inline qreal QWebPage::ViewportAttributes::initialScaleFactor() const
1889 Returns the initial scale of the viewport as a multiplier.
1892 /*! \fn inline qreal QWebPage::ViewportAttributes::minimumScaleFactor() const
1893 Returns the minimum scale value of the viewport as a multiplier.
1896 /*! \fn inline qreal QWebPage::ViewportAttributes::maximumScaleFactor() const
1897 Returns the maximum scale value of the viewport as a multiplier.
1900 /*! \fn inline bool QWebPage::ViewportAttributes::isUserScalable() const
1901 Determines whether or not the scale can be modified by the user.
1908 \brief The QWebPage class provides an object to view and edit web documents.
1912 QWebPage holds a main frame responsible for web content, settings, the history
1913 of navigated links and actions. This class can be used, together with QWebFrame,
1914 to provide functionality like QWebView in a widget-less environment.
1916 QWebPage's API is very similar to QWebView, as you are still provided with
1917 common functions like action() (known as
1918 \l{QWebView::pageAction()}{pageAction}() in QWebView), triggerAction(),
1919 findText() and settings(). More QWebView-like functions can be found in the
1920 main frame of QWebPage, obtained via the mainFrame() function. For example,
1921 the \l{QWebFrame::load()}{load}(), \l{QWebFrame::setUrl()}{setUrl}() and
1922 \l{QWebFrame::setHtml()}{setHtml}() functions for QWebPage can be accessed
1925 The loadStarted() signal is emitted when the page begins to load.The
1926 loadProgress() signal, on the other hand, is emitted whenever an element
1927 of the web page completes loading, such as an embedded image, a script,
1928 etc. Finally, the loadFinished() signal is emitted when the page contents
1929 are loaded completely, independent of script execution or page rendering.
1930 Its argument, either true or false, indicates whether or not the load
1931 operation succeeded.
1933 \section1 Using QWebPage in a Widget-less Environment
1935 Before you begin painting a QWebPage object, you need to set the size of
1936 the viewport by calling setViewportSize(). Then, you invoke the main
1937 frame's render function (QWebFrame::render()). An example of this
1938 is shown in the code snippet below.
1940 Suppose we have a \c Thumbnail class as follows:
1942 \snippet webkitsnippets/webpage/main.cpp 0
1944 The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage
1945 object's \l{QWebPage::}{loadFinished()} signal to our private slot,
1948 \snippet webkitsnippets/webpage/main.cpp 1
1950 The \c render() function shows how we can paint a thumbnail using a
1953 \snippet webkitsnippets/webpage/main.cpp 2
1955 We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and
1956 then we instantiate a QImage object, \c image, with the same size as our
1957 \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent
1958 as a parameter to \c painter. Next, we render the contents of the main
1959 frame and its subframes into \c painter. Finally, we save the scaled image.
1965 Constructs an empty QWebPage with parent \a parent.
1967 QWebPage::QWebPage(QObject *parent)
1969 , d(new QWebPagePrivate(this))
1971 setView(qobject_cast<QWidget*>(parent));
1973 connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int)));
1975 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages()));
1980 Destroys the web page.
1982 QWebPage::~QWebPage()
1984 d->createMainFrame();
1985 FrameLoader* loader = d->mainFrame.data()->d->frame->loader();
1987 loader->detachFromParent();
1992 Returns the main frame of the page.
1994 The main frame provides access to the hierarchy of sub-frames and is also needed if you
1995 want to explicitly render a web page into a given painter.
1999 QWebFrame *QWebPage::mainFrame() const
2001 d->createMainFrame();
2002 return d->mainFrame.data();
2006 Returns the frame currently active.
2008 \sa mainFrame(), frameCreated()
2010 QWebFrame *QWebPage::currentFrame() const
2012 d->createMainFrame();
2013 WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2014 return qobject_cast<QWebFrame*>(frame->loader()->networkingContext()->originatingObject());
2021 Returns the frame at the given point \a pos, or 0 if there is no frame at
2024 \sa mainFrame(), currentFrame()
2026 QWebFrame* QWebPage::frameAt(const QPoint& pos) const
2028 QWebFrame* webFrame = mainFrame();
2029 if (!webFrame->geometry().contains(pos))
2031 QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos);
2032 return hitTestResult.frame();
2036 Returns a pointer to the view's history of navigated web pages.
2038 QWebHistory *QWebPage::history() const
2040 d->createMainFrame();
2045 Sets the \a view that is associated with the web page.
2049 void QWebPage::setView(QWidget* view)
2051 if (this->view() == view)
2055 setViewportSize(view ? view->size() : QSize(0, 0));
2057 // If we have no client, we install a special client delegating
2058 // the responsibility to the QWidget. This is the code path
2059 // handling a.o. the "legacy" QWebView.
2061 // If such a special delegate already exist, we substitute the view.
2064 if (d->client->isQWidgetClient())
2065 static_cast<PageClientQWidget*>(d->client.get())->view = view;
2070 d->client = adoptPtr(new PageClientQWidget(view, this));
2074 Returns the view widget that is associated with the web page.
2078 QWidget *QWebPage::view() const
2080 return d->view.data();
2084 This function is called whenever a JavaScript program tries to print a \a message to the web browser's console.
2086 For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber.
2088 The default implementation prints nothing.
2090 void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
2094 // Catch plugin logDestroy message for LayoutTests/plugins/open-and-close-window-with-plugin.html
2095 // At this point DRT's WebPage has already been destroyed
2096 if (QWebPagePrivate::drtRun) {
2097 if (message == QLatin1String("PLUGIN: NPP_Destroy"))
2098 fprintf (stdout, "CONSOLE MESSAGE: line %d: %s\n", lineNumber, message.toUtf8().constData());
2103 This function is called whenever a JavaScript program running inside \a frame calls the alert() function with
2106 The default implementation shows the message, \a msg, with QMessageBox::information.
2108 void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg)
2111 #ifndef QT_NO_MESSAGEBOX
2112 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2113 QMessageBox::information(parent, tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Ok);
2118 This function is called whenever a JavaScript program running inside \a frame calls the confirm() function
2119 with the message, \a msg. Returns true if the user confirms the message; otherwise returns false.
2121 The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
2123 bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg)
2126 #ifdef QT_NO_MESSAGEBOX
2129 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2130 return QMessageBox::Yes == QMessageBox::information(parent, tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Yes, QMessageBox::No);
2135 This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input.
2136 The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue.
2138 If the prompt was cancelled by the user the implementation should return false; otherwise the
2139 result should be written to \a result and true should be returned. If the prompt was not cancelled by the
2140 user, the implementation should return true and the result string must not be null.
2142 The default implementation uses QInputDialog::getText().
2144 bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result)
2148 #ifndef QT_NO_INPUTDIALOG
2149 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2150 QString x = QInputDialog::getText(parent, tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QLineEdit::Normal, defaultValue, &ok);
2158 \fn bool QWebPage::shouldInterruptJavaScript()
2160 This function is called when a JavaScript program is running for a long period of time.
2162 If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
2164 The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
2166 \warning Because of binary compatibility constraints, this function is not virtual. If you want to
2167 provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript()
2168 slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
2170 bool QWebPage::shouldInterruptJavaScript()
2172 #ifdef QT_NO_MESSAGEBOX
2175 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
2176 return QMessageBox::Yes == QMessageBox::information(parent, 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);
2180 void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy)
2184 #if ENABLE(NOTIFICATIONS)
2185 if (policy == PermissionGrantedByUser)
2186 NotificationPresenterClientQt::notificationPresenter()->allowNotificationForFrame(frame->d->frame);
2190 #if ENABLE(GEOLOCATION)
2191 GeolocationPermissionClientQt::geolocationPermissionClient()->setPermission(frame, policy);
2201 This function is called whenever WebKit wants to create a new window of the given \a type, for
2202 example when a JavaScript program requests to open a document in a new window.
2204 If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned.
2206 If the view associated with the web page is a QWebView object, then the default implementation forwards
2207 the request to QWebView's createWindow() function; otherwise it returns a null pointer.
2209 If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window.
2211 \note In the cases when the window creation is being triggered by JavaScript, apart from
2212 reimplementing this method application must also set the JavaScriptCanOpenWindows attribute
2213 of QWebSettings to true in order for it to get called.
2215 \sa acceptNavigationRequest(), QWebView::createWindow()
2217 QWebPage *QWebPage::createWindow(WebWindowType type)
2219 QWebView *webView = qobject_cast<QWebView*>(view());
2221 QWebView *newView = webView->createWindow(type);
2223 return newView->page();
2229 This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is
2230 called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues
2231 correspond to the HTML object element attributes and child elements to configure the embeddable object.
2233 QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues)
2237 Q_UNUSED(paramNames)
2238 Q_UNUSED(paramValues)
2242 static void extractContentTypeFromHash(const HashSet<String>& types, QStringList* list)
2247 HashSet<String>::const_iterator endIt = types.end();
2248 for (HashSet<String>::const_iterator it = types.begin(); it != endIt; ++it)
2252 static void extractContentTypeFromPluginVector(const Vector<PluginPackage*>& plugins, QStringList* list)
2257 for (unsigned int i = 0; i < plugins.size(); ++i) {
2258 MIMEToDescriptionsMap::const_iterator map_it = plugins[i]->mimeToDescriptions().begin();
2259 MIMEToDescriptionsMap::const_iterator map_end = plugins[i]->mimeToDescriptions().end();
2260 for (; map_it != map_end; ++map_it)
2261 *list << map_it->first;
2266 * Returns the list of all content types supported by QWebPage.
2268 QStringList QWebPage::supportedContentTypes() const
2270 QStringList mimeTypes;
2272 extractContentTypeFromHash(MIMETypeRegistry::getSupportedImageMIMETypes(), &mimeTypes);
2273 extractContentTypeFromHash(MIMETypeRegistry::getSupportedNonImageMIMETypes(), &mimeTypes);
2274 if (d->page->settings() && d->page->settings()->arePluginsEnabled())
2275 extractContentTypeFromPluginVector(PluginDatabase::installedPlugins()->plugins(), &mimeTypes);
2281 * Returns true if QWebPage can handle the given \a mimeType; otherwise, returns false.
2283 bool QWebPage::supportsContentType(const QString& mimeType) const
2285 const String type = mimeType.toLower();
2286 if (MIMETypeRegistry::isSupportedImageMIMEType(type))
2289 if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
2292 if (d->page->settings() && d->page->settings()->arePluginsEnabled()
2293 && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type))
2299 static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame)
2301 return WebCore::FrameLoadRequest(frame->document()->securityOrigin(),
2302 WebCore::ResourceRequest(url, frame->loader()->outgoingReferrer()));
2305 static void openNewWindow(const QUrl& url, WebCore::Frame* frame)
2307 if (Page* oldPage = frame->page()) {
2308 WindowFeatures features;
2309 NavigationAction action;
2310 FrameLoadRequest request = frameLoadRequest(url, frame);
2311 if (Page* newPage = oldPage->chrome()->createWindow(frame, request, features, action)) {
2312 newPage->mainFrame()->loader()->loadFrameRequest(request, false, false, 0, 0, SendReferrer);
2313 newPage->chrome()->show();
2318 static void collectChildFrames(QWebFrame* frame, QList<QWebFrame*>& list)
2320 list << frame->childFrames();
2321 QListIterator<QWebFrame*> it(frame->childFrames());
2322 while (it.hasNext()) {
2323 collectChildFrames(it.next(), list);
2328 This function can be called to trigger the specified \a action.
2329 It is also called by QtWebKit if the user triggers the action, for example
2330 through a context menu item.
2332 If \a action is a checkable action then \a checked specified whether the action
2337 void QWebPage::triggerAction(WebAction action, bool)
2339 WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame();
2342 WebCore::Editor *editor = frame->editor();
2343 const char *command = 0;
2347 if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) {
2348 WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame;
2349 targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()),
2350 /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0,
2351 /*FormState*/ 0, SendReferrer);
2355 case OpenLinkInNewWindow:
2356 openNewWindow(d->hitTestResult.linkUrl(), frame);
2358 case OpenFrameInNewWindow: {
2359 KURL url = frame->loader()->documentLoader()->unreachableURL();
2361 url = frame->loader()->documentLoader()->url();
2362 openNewWindow(url, frame);
2365 case CopyLinkToClipboard: {
2366 #if defined(Q_WS_X11)
2367 bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode();
2368 Pasteboard::generalPasteboard()->setSelectionMode(true);
2369 editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2370 Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode);
2372 editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText());
2375 case OpenImageInNewWindow:
2376 openNewWindow(d->hitTestResult.imageUrl(), frame);
2378 case DownloadImageToDisk:
2379 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer()));
2381 case DownloadLinkToDisk:
2382 frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer()));
2384 #ifndef QT_NO_CLIPBOARD
2385 case CopyImageToClipboard:
2386 QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap());
2388 case CopyImageUrlToClipboard:
2389 QApplication::clipboard()->setText(d->hitTestResult.imageUrl().toString());
2396 d->page->goForward();
2399 mainFrame()->d->frame->loader()->stopForUserCancel();
2400 d->updateNavigationActions();
2403 mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false);
2405 case ReloadAndBypassCache:
2406 mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true);
2408 case SetTextDirectionDefault:
2409 editor->setBaseWritingDirection(NaturalWritingDirection);
2411 case SetTextDirectionLeftToRight:
2412 editor->setBaseWritingDirection(LeftToRightWritingDirection);
2414 case SetTextDirectionRightToLeft:
2415 editor->setBaseWritingDirection(RightToLeftWritingDirection);
2417 case InspectElement: {
2418 #if ENABLE(INSPECTOR)
2419 if (!d->hitTestResult.isNull()) {
2420 d->getOrCreateInspector(); // Make sure the inspector is created
2421 d->inspector->show(); // The inspector is expected to be shown on inspection
2422 d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get());
2427 case StopScheduledPageRefresh: {
2428 QWebFrame* topFrame = mainFrame();
2429 topFrame->d->frame->navigationScheduler()->cancel();
2430 QList<QWebFrame*> childFrames;
2431 collectChildFrames(topFrame, childFrames);
2432 QListIterator<QWebFrame*> it(childFrames);
2433 while (it.hasNext())
2434 it.next()->d->frame->navigationScheduler()->cancel();
2438 command = QWebPagePrivate::editorCommandForWebActions(action);
2443 editor->command(command).execute();
2446 QSize QWebPage::viewportSize() const
2448 if (d->mainFrame && d->mainFrame.data()->d->frame->view())
2449 return d->mainFrame.data()->d->frame->view()->frameRect().size();
2451 return d->viewportSize;
2455 \property QWebPage::viewportSize
2456 \brief the size of the viewport
2458 The size affects for example the visibility of scrollbars
2459 if the document is larger than the viewport.
2461 By default, for a newly-created Web page, this property contains a size with
2462 zero width and height.
2464 \sa QWebFrame::render(), preferredContentsSize
2466 void QWebPage::setViewportSize(const QSize &size) const
2468 d->viewportSize = size;
2470 QWebFrame *frame = mainFrame();
2471 if (frame->d->frame && frame->d->frame->view()) {
2472 WebCore::FrameView* view = frame->d->frame->view();
2474 view->adjustViewSize();
2478 static int getintenv(const char* variable)
2481 int value = qgetenv(variable).toInt(&ok);
2482 return (ok) ? value : -1;
2485 static QSize queryDeviceSizeForScreenContainingWidget(const QWidget* widget)
2487 QDesktopWidget* desktop = QApplication::desktop();
2494 // Returns the available geometry of the screen which contains widget.
2495 // NOTE: this must be the the full screen size including any fixed status areas etc.
2496 size = desktop->availableGeometry(widget).size();
2498 size = desktop->availableGeometry().size();
2500 // This must be in portrait mode, adjust if not.
2501 if (size.width() > size.height()) {
2502 int width = size.width();
2503 size.setWidth(size.height());
2504 size.setHeight(width);
2511 Computes the optimal viewport configuration given the \a availableSize, when
2512 user interface components are disregarded.
2514 The configuration is also dependent on the device screen size which is obtained
2515 automatically. For testing purposes the size can be overridden by setting two
2516 environment variables QTWEBKIT_DEVICE_WIDTH and QTWEBKIT_DEVICE_HEIGHT, which
2517 both needs to be set.
2519 The ViewportAttributes includes a pixel density ratio, which will also be exposed to
2520 the web author though the -webkit-pixel-ratio media feature. This is the ratio
2521 between 1 density-independent pixel (DPI) and physical pixels.
2523 A density-independent pixel is equivalent to one physical pixel on a 160 DPI screen,
2524 so on our platform assumes that as the baseline density.
2526 The conversion of DIP units to screen pixels is quite simple:
2528 pixels = DIPs * (density / 160).
2530 Thus, on a 240 DPI screen, 1 DIPs would equal 1.5 physical pixels.
2532 An invalid instance will be returned in the case an empty size is passed to the
2535 \note The density is automatically obtained from the DPI of the screen where the page
2536 is being shown, but as many X11 servers are reporting wrong DPI, it is possible to
2537 override it using QX11Info::setAppDpiY().
2540 QWebPage::ViewportAttributes QWebPage::viewportAttributesForSize(const QSize& availableSize) const
2542 static int desktopWidth = 980;
2544 ViewportAttributes result;
2546 if (availableSize.isEmpty())
2547 return result; // Returns an invalid instance.
2549 int deviceWidth = getintenv("QTWEBKIT_DEVICE_WIDTH");
2550 int deviceHeight = getintenv("QTWEBKIT_DEVICE_HEIGHT");
2552 // Both environment variables need to be set - or they will be ignored.
2553 if (deviceWidth < 0 && deviceHeight < 0) {
2554 QSize size = queryDeviceSizeForScreenContainingWidget((d->client) ? d->client->ownerWidget() : 0);
2555 deviceWidth = size.width();
2556 deviceHeight = size.height();
2559 WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(d->viewportArguments(), desktopWidth, deviceWidth, deviceHeight, qt_defaultDpi(), availableSize);
2561 result.m_isValid = true;
2562 result.m_size = conf.layoutSize;
2563 result.m_initialScaleFactor = conf.initialScale;
2564 result.m_minimumScaleFactor = conf.minimumScale;
2565 result.m_maximumScaleFactor = conf.maximumScale;
2566 result.m_devicePixelRatio = conf.devicePixelRatio;
2567 result.m_isUserScalable = static_cast<bool>(conf.userScalable);
2569 d->page->setDeviceScaleFactor(conf.devicePixelRatio);
2574 QSize QWebPage::preferredContentsSize() const
2576 QWebFrame* frame = d->mainFrame.data();
2578 WebCore::FrameView* view = frame->d->frame->view();
2579 if (view && view->useFixedLayout())
2580 return d->mainFrame.data()->d->frame->view()->fixedLayoutSize();
2583 return d->fixedLayoutSize;
2587 \property QWebPage::preferredContentsSize
2589 \brief a custom size used for laying out the page contents.
2591 By default all pages are laid out using the viewport of the page as the base.
2593 As pages mostly are designed for desktop usage, they often do not layout properly
2594 on small devices as the contents require a certain view width. For this reason
2595 it is common to use a different layout size and then scale the contents to fit
2596 within the actual view.
2598 If this property is set to a valid size, this size is used for all layout needs
2599 instead of the size of the viewport.
2601 Setting an invalid size, makes the page fall back to using the viewport size for layout.
2605 void QWebPage::setPreferredContentsSize(const QSize& size) const
2607 // FIXME: Rename this method to setCustomLayoutSize
2609 d->fixedLayoutSize = size;
2611 QWebFrame* frame = mainFrame();
2612 if (!frame->d->frame || !frame->d->frame->view())
2615 WebCore::FrameView* view = frame->d->frame->view();
2617 if (size.isValid()) {
2618 view->setUseFixedLayout(true);
2619 view->setFixedLayoutSize(size);
2620 } else if (view->useFixedLayout())
2621 view->setUseFixedLayout(false);
2627 This function is to be called after any (animated) scroll/pan has ended, in the case the application handles the
2628 scrolling/panning of the web contents. This is commonly used in combination with tiling where is it common for
2629 the application to pan the actual view, which then resizes itself to the size of the contents.
2631 \note Calling this function makes WebKit stop trying to calculate the visibleContentRect. To turn that on
2632 again, call this method with an empty rect.
2634 \sa QGraphicsWebView::resizesToContents, QWebSettings::TiledBackingStoreEnabled
2636 void QWebPage::setActualVisibleContentRect(const QRect& rect) const
2638 QWebFrame* frame = mainFrame();
2639 if (!frame->d->frame || !frame->d->frame->view())
2642 WebCore::FrameView* view = frame->d->frame->view();
2643 view->setFixedVisibleContentRect(rect);
2647 \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2649 This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of
2650 the specified navigation type \a type.
2652 If \a frame is a null pointer then navigation to a new window is requested. If the request is
2653 accepted createWindow() will be called.
2655 The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true
2656 to let QWebPage handle the navigation itself.
2660 bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type)
2663 if (type == NavigationTypeLinkClicked) {
2664 switch (d->linkPolicy) {
2665 case DontDelegateLinks:
2668 case DelegateExternalLinks:
2669 if (WebCore::SchemeRegistry::shouldTreatURLSchemeAsLocal(request.url().scheme()))
2671 emit linkClicked(request.url());
2674 case DelegateAllLinks:
2675 emit linkClicked(request.url());
2683 \property QWebPage::hasSelection
2684 \brief whether this page contains selected content or not.
2686 \sa selectionChanged()
2688 bool QWebPage::hasSelection() const
2690 d->createMainFrame();
2691 WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame();
2693 return (frame->selection()->selection().selectionType() != VisibleSelection::NoSelection);
2698 \property QWebPage::selectedText
2699 \brief the text currently selected
2701 By default, this property contains an empty string.
2703 \sa selectionChanged(), selectedHtml()
2705 QString QWebPage::selectedText() const
2707 d->createMainFrame();
2708 WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame();
2709 if (frame->selection()->selection().selectionType() == VisibleSelection::NoSelection)
2711 return frame->editor()->selectedText();
2716 \property QWebPage::selectedHtml
2717 \brief the HTML currently selected
2719 By default, this property contains an empty string.
2721 \sa selectionChanged(), selectedText()
2723 QString QWebPage::selectedHtml() const
2725 d->createMainFrame();
2726 return d->page->focusController()->focusedOrMainFrame()->editor()->selectedRange()->toHTML();
2729 #ifndef QT_NO_ACTION
2731 Returns a QAction for the specified WebAction \a action.
2733 The action is owned by the QWebPage but you can customize the look by
2734 changing its properties.
2736 QWebPage also takes care of implementing the action, so that upon
2737 triggering the corresponding action is performed on the page.
2741 QAction *QWebPage::action(WebAction action) const
2743 if (action == QWebPage::NoWebAction) return 0;
2744 if (d->actions[action])
2745 return d->actions[action];
2749 QStyle *style = d->client ? d->client->style() : qApp->style();
2750 bool checkable = false;
2754 text = contextMenuItemTagOpenLink();
2756 case OpenLinkInNewWindow:
2757 text = contextMenuItemTagOpenLinkInNewWindow();
2759 case OpenFrameInNewWindow:
2760 text = contextMenuItemTagOpenFrameInNewWindow();
2763 case DownloadLinkToDisk:
2764 text = contextMenuItemTagDownloadLinkToDisk();
2766 case CopyLinkToClipboard:
2767 text = contextMenuItemTagCopyLinkToClipboard();
2770 case OpenImageInNewWindow:
2771 text = contextMenuItemTagOpenImageInNewWindow();
2773 case DownloadImageToDisk:
2774 text = contextMenuItemTagDownloadImageToDisk();
2776 case CopyImageToClipboard:
2777 text = contextMenuItemTagCopyImageToClipboard();
2779 case CopyImageUrlToClipboard:
2780 text = contextMenuItemTagCopyImageUrlToClipboard();
2784 text = contextMenuItemTagGoBack();
2785 icon = style->standardIcon(QStyle::SP_ArrowBack);
2788 text = contextMenuItemTagGoForward();
2789 icon = style->standardIcon(QStyle::SP_ArrowForward);
2792 text = contextMenuItemTagStop();
2793 icon = style->standardIcon(QStyle::SP_BrowserStop);
2796 text = contextMenuItemTagReload();
2797 icon = style->standardIcon(QStyle::SP_BrowserReload);
2801 text = contextMenuItemTagCut();
2804 text = contextMenuItemTagCopy();
2807 text = contextMenuItemTagPaste();
2810 text = contextMenuItemTagSelectAll();
2812 #ifndef QT_NO_UNDOSTACK
2814 QAction *a = undoStack()->createUndoAction(d->q);
2815 d->actions[action] = a;
2819 QAction *a = undoStack()->createRedoAction(d->q);
2820 d->actions[action] = a;
2823 #endif // QT_NO_UNDOSTACK
2824 case MoveToNextChar:
2825 text = tr("Move the cursor to the next character");
2827 case MoveToPreviousChar:
2828 text = tr("Move the cursor to the previous character");
2830 case MoveToNextWord:
2831 text = tr("Move the cursor to the next word");
2833 case MoveToPreviousWord:
2834 text = tr("Move the cursor to the previous word");
2836 case MoveToNextLine:
2837 text = tr("Move the cursor to the next line");
2839 case MoveToPreviousLine:
2840 text = tr("Move the cursor to the previous line");
2842 case MoveToStartOfLine:
2843 text = tr("Move the cursor to the start of the line");
2845 case MoveToEndOfLine:
2846 text = tr("Move the cursor to the end of the line");
2848 case MoveToStartOfBlock:
2849 text = tr("Move the cursor to the start of the block");
2851 case MoveToEndOfBlock:
2852 text = tr("Move the cursor to the end of the block");
2854 case MoveToStartOfDocument:
2855 text = tr("Move the cursor to the start of the document");
2857 case MoveToEndOfDocument:
2858 text = tr("Move the cursor to the end of the document");
2860 case SelectNextChar:
2861 text = tr("Select to the next character");
2863 case SelectPreviousChar:
2864 text = tr("Select to the previous character");
2866 case SelectNextWord:
2867 text = tr("Select to the next word");
2869 case SelectPreviousWord:
2870 text = tr("Select to the previous word");
2872 case SelectNextLine:
2873 text = tr("Select to the next line");
2875 case SelectPreviousLine:
2876 text = tr("Select to the previous line");
2878 case SelectStartOfLine:
2879 text = tr("Select to the start of the line");
2881 case SelectEndOfLine:
2882 text = tr("Select to the end of the line");
2884 case SelectStartOfBlock:
2885 text = tr("Select to the start of the block");
2887 case SelectEndOfBlock:
2888 text = tr("Select to the end of the block");
2890 case SelectStartOfDocument:
2891 text = tr("Select to the start of the document");
2893 case SelectEndOfDocument:
2894 text = tr("Select to the end of the document");
2896 case DeleteStartOfWord:
2897 text = tr("Delete to the start of the word");
2899 case DeleteEndOfWord:
2900 text = tr("Delete to the end of the word");
2903 case SetTextDirectionDefault:
2904 text = contextMenuItemTagDefaultDirection();
2906 case SetTextDirectionLeftToRight:
2907 text = contextMenuItemTagLeftToRight();
2910 case SetTextDirectionRightToLeft:
2911 text = contextMenuItemTagRightToLeft();
2916 text = contextMenuItemTagBold();
2920 text = contextMenuItemTagItalic();
2923 case ToggleUnderline:
2924 text = contextMenuItemTagUnderline();
2928 case InspectElement:
2929 text = contextMenuItemTagInspectElement();
2932 case InsertParagraphSeparator:
2933 text = tr("Insert a new paragraph");
2935 case InsertLineSeparator:
2936 text = tr("Insert a new line");
2939 case PasteAndMatchStyle:
2940 text = tr("Paste and Match Style");
2943 text = tr("Remove formatting");
2946 case ToggleStrikethrough:
2947 text = tr("Strikethrough");
2950 case ToggleSubscript:
2951 text = tr("Subscript");
2954 case ToggleSuperscript:
2955 text = tr("Superscript");
2958 case InsertUnorderedList:
2959 text = tr("Insert Bulleted List");
2962 case InsertOrderedList:
2963 text = tr("Insert Numbered List");
2967 text = tr("Indent");
2970 text = tr("Outdent");
2973 text = tr("Center");
2975 case AlignJustified:
2976 text = tr("Justify");
2979 text = tr("Align Left");
2982 text = tr("Align Right");
2993 QAction *a = new QAction(d->q);
2996 a->setCheckable(checkable);
2999 connect(a, SIGNAL(triggered(bool)),
3000 this, SLOT(_q_webActionTriggered(bool)));
3002 d->actions[action] = a;
3003 d->updateAction(action);
3006 #endif // QT_NO_ACTION
3009 \property QWebPage::modified
3010 \brief whether the page contains unsubmitted form data, or the contents have been changed.
3012 By default, this property is false.
3014 \sa contentsChanged(), contentEditable, undoStack()
3016 bool QWebPage::isModified() const
3018 #ifdef QT_NO_UNDOSTACK
3023 return d->undoStack->canUndo();
3024 #endif // QT_NO_UNDOSTACK
3027 #ifndef QT_NO_UNDOSTACK
3029 Returns a pointer to the undo stack used for editable content.
3033 QUndoStack *QWebPage::undoStack() const
3036 d->undoStack = new QUndoStack(const_cast<QWebPage *>(this));
3038 return d->undoStack;
3040 #endif // QT_NO_UNDOSTACK
3044 bool QWebPage::event(QEvent *ev)
3046 switch (ev->type()) {
3048 d->timerEvent(static_cast<QTimerEvent*>(ev));
3050 case QEvent::MouseMove:
3051 d->mouseMoveEvent(static_cast<QMouseEvent*>(ev));
3053 case QEvent::MouseButtonPress:
3054 d->mousePressEvent(static_cast<QMouseEvent*>(ev));
3056 case QEvent::MouseButtonDblClick:
3057 d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
3059 case QEvent::MouseButtonRelease:
3060 d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
3062 #if !defined(QT_NO_GRAPHICSVIEW)
3063 case QEvent::GraphicsSceneMouseMove:
3064 d->mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3066 case QEvent::GraphicsSceneMousePress:
3067 d->mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3069 case QEvent::GraphicsSceneMouseDoubleClick:
3070 d->mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3072 case QEvent::GraphicsSceneMouseRelease:
3073 d->mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(ev));
3076 #ifndef QT_NO_CONTEXTMENU
3077 case QEvent::ContextMenu:
3078 d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos());
3080 #if !defined(QT_NO_GRAPHICSVIEW)
3081 case QEvent::GraphicsSceneContextMenu:
3082 d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos());
3086 #ifndef QT_NO_WHEELEVENT
3088 d->wheelEvent(static_cast<QWheelEvent*>(ev));
3090 #if !defined(QT_NO_GRAPHICSVIEW)
3091 case QEvent::GraphicsSceneWheel:
3092 d->wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(ev));
3096 case QEvent::KeyPress:
3097 d->keyPressEvent(static_cast<QKeyEvent*>(ev));
3099 case QEvent::KeyRelease:
3100 d->keyReleaseEvent(static_cast<QKeyEvent*>(ev));
3102 case QEvent::FocusIn:
3103 d->focusInEvent(static_cast<QFocusEvent*>(ev));
3105 case QEvent::FocusOut:
3106 d->focusOutEvent(static_cast<QFocusEvent*>(ev));
3108 #ifndef QT_NO_DRAGANDDROP
3109 case QEvent::DragEnter:
3110 d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
3112 case QEvent::DragLeave:
3113 d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev));
3115 case QEvent::DragMove:
3116 d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev));
3119 d->dropEvent(static_cast<QDropEvent*>(ev));
3121 #if !defined(QT_NO_GRAPHICSVIEW)
3122 case QEvent::GraphicsSceneDragEnter:
3123 d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3125 case QEvent::GraphicsSceneDragMove:
3126 d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3128 case QEvent::GraphicsSceneDragLeave:
3129 d->dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3131 case QEvent::GraphicsSceneDrop:
3132 d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev));
3137 case QEvent::InputMethod:
3138 d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev));
3140 case QEvent::ShortcutOverride:
3141 d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev));
3146 case QEvent::TouchBegin:
3147 case QEvent::TouchUpdate:
3148 case QEvent::TouchEnd:
3149 // Return whether the default action was cancelled in the JS event handler
3150 return d->touchEvent(static_cast<QTouchEvent*>(ev));
3151 #ifndef QT_NO_PROPERTIES
3152 case QEvent::DynamicPropertyChange:
3153 d->dynamicPropertyChangeEvent(static_cast<QDynamicPropertyChangeEvent*>(ev));
3157 return QObject::event(ev);
3164 Similar to QWidget::focusNextPrevChild() it focuses the next focusable web element
3165 if \a next is true; otherwise the previous element is focused.
3167 Returns true if it can find a new focusable element, or false if it can't.
3169 bool QWebPage::focusNextPrevChild(bool next)
3171 QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier));
3172 d->keyPressEvent(&ev);
3173 bool hasFocusedNode = false;
3174 Frame *frame = d->page->focusController()->focusedFrame();
3176 Document *document = frame->document();
3177 hasFocusedNode = document && document->focusedNode();
3179 //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode;
3180 return hasFocusedNode;
3184 \property QWebPage::contentEditable
3185 \brief whether the content in this QWebPage is editable or not
3188 If this property is enabled the contents of the page can be edited by the user through a visible
3189 cursor. If disabled (the default) only HTML elements in the web page with their
3190 \c{contenteditable} attribute set are editable.
3192 \sa modified, contentsChanged(), WebAction
3194 void QWebPage::setContentEditable(bool editable)
3196 if (isContentEditable() != editable) {
3197 d->page->setEditable(editable);
3198 d->page->setTabKeyCyclesThroughElements(!editable);
3200 WebCore::Frame* frame = d->mainFrame.data()->d->frame;
3202 frame->editor()->applyEditingStyleToBodyElement();
3203 // FIXME: mac port calls this if there is no selectedDOMRange
3204 //frame->setSelectionFromNone();
3208 d->updateEditorActions();
3212 bool QWebPage::isContentEditable() const
3214 return d->page->isEditable();
3218 \property QWebPage::forwardUnsupportedContent
3219 \brief whether QWebPage should forward unsupported content
3221 If enabled, the unsupportedContent() signal is emitted with a network reply that
3222 can be used to read the content.
3224 If disabled, the download of such content is aborted immediately.
3226 By default unsupported content is not forwarded.
3229 void QWebPage::setForwardUnsupportedContent(bool forward)
3231 d->forwardUnsupportedContent = forward;
3234 bool QWebPage::forwardUnsupportedContent() const
3236 return d->forwardUnsupportedContent;
3240 \property QWebPage::linkDelegationPolicy
3241 \brief how QWebPage should delegate the handling of links through the
3242 linkClicked() signal
3244 The default is to delegate no links.
3247 void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy)
3249 d->linkPolicy = policy;
3252 QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const
3254 return d->linkPolicy;
3257 #ifndef QT_NO_CONTEXTMENU
3259 Filters the context menu event, \a event, through handlers for scrollbars and
3260 custom event handlers in the web page. Returns true if the event was handled;
3263 A web page may swallow a context menu event through a custom event handler, allowing for context
3264 menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google
3267 bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event)
3269 d->page->contextMenuController()->clearContextMenu();
3271 if (QWebFrame* webFrame = frameAt(event->pos())) {
3272 Frame* frame = QWebFramePrivate::core(webFrame);
3273 if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).pos()))
3274 return scrollbar->contextMenu(PlatformMouseEvent(event, 1));
3277 WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
3278 focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1));
3279 ContextMenu *menu = d->page->contextMenuController()->contextMenu();
3280 // If the website defines its own handler then sendContextMenuEvent takes care of
3281 // calling/showing it and the context menu pointer will be zero. This is the case
3282 // on maps.google.com for example.
3286 #endif // QT_NO_CONTEXTMENU
3289 Updates the page's actions depending on the position \a pos. For example if \a pos is over an image
3290 element the CopyImageToClipboard action is enabled.
3292 void QWebPage::updatePositionDependentActions(const QPoint &pos)
3294 #ifndef QT_NO_ACTION
3295 // First we disable all actions, but keep track of which ones were originally enabled.
3296 QBitArray originallyEnabledWebActions(QWebPage::WebActionCount);
3297 for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) {
3298 QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i));
3299 if (QAction *a = this->action(action)) {
3300 originallyEnabledWebActions.setBit(action, a->isEnabled());
3301 a->setEnabled(false);
3304 #endif // QT_NO_ACTION
3306 d->createMainFrame();
3307 WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame();
3309 HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false);
3310 if (result.scrollbar())
3311 d->hitTestResult = QWebHitTestResult();
3313 d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result));
3314 d->page->contextMenuController()->setHitTestResult(result);
3316 #if ENABLE(INSPECTOR)
3317 if (d->page->inspectorController()->enabled())
3318 d->page->contextMenuController()->addInspectElementItem();
3321 QBitArray visitedWebActions(QWebPage::WebActionCount);
3323 #ifndef QT_NO_CONTEXTMENU
3324 delete d->currentContextMenu.data();
3326 // Then we let createContextMenu() enable the actions that are put into the menu
3327 d->currentContextMenu = d->createContextMenu(d->page->contextMenuController()->contextMenu(), d->page->contextMenuController()->contextMenu()->platformDescription(), &visitedWebActions);
3328 #endif // QT_NO_CONTEXTMENU
3330 #ifndef QT_NO_ACTION
3331 // Finally, we restore the original enablement for the actions that were not put into the menu.
3332 originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu)
3333 for (int i = 0; i < QWebPage::WebActionCount; ++i) {
3334 if (originallyEnabledWebActions.at(i)) {
3335 if (QAction *a = this->action(QWebPage::WebAction(i)))
3336 a->setEnabled(true);
3339 #endif // QT_NO_ACTION
3341 // This whole process ensures that any actions put into to the context menu has the right
3342 // enablement, while also keeping the correct enablement for actions that were left out of
3350 \enum QWebPage::Extension
3352 This enum describes the types of extensions that the page can support. Before using these extensions, you
3353 should verify that the extension is supported by calling supportsExtension().
3355 \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection.
3356 This extension is invoked when the web content requests one or more file names, for example
3357 as a result of the user clicking on a "file upload" button in a HTML form where multiple
3358 file selection is allowed.
3360 \value ErrorPageExtension Whether the web page can provide an error page when loading fails.
3361 (introduced in Qt 4.6)
3363 \sa ChooseMultipleFilesExtensionOption, ChooseMultipleFilesExtensionReturn, ErrorPageExtensionOption, ErrorPageExtensionReturn
3367 \enum QWebPage::ErrorDomain
3370 This enum describes the domain of an ErrorPageExtensionOption object (i.e. the layer in which the error occurred).
3372 \value QtNetwork The error occurred in the QtNetwork layer; the error code is of type QNetworkReply::NetworkError.
3373 \value Http The error occurred in the HTTP layer; the error code is a HTTP status code (see QNetworkRequest::HttpStatusCodeAttribute).
3374 \value WebKit The error is an internal WebKit error.
3378 \class QWebPage::ExtensionOption
3380 \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support.
3384 \sa QWebPage::extension() QWebPage::ExtensionReturn
3389 \class QWebPage::ExtensionReturn
3391 \brief The ExtensionReturn class provides an output result from a QWebPage's extension.
3395 \sa QWebPage::extension() QWebPage::ExtensionOption
3399 \class QWebPage::ErrorPageExtensionOption
3401 \brief The ErrorPageExtensionOption class describes the option
3402 for the error page extension.
3406 The ErrorPageExtensionOption class holds the \a url for which an error occurred as well as
3407 the associated \a frame.
3409 The error itself is reported by an error \a domain, the \a error code as well as \a errorString.
3411 \sa QWebPage::extension() QWebPage::ErrorPageExtensionReturn
3415 \variable QWebPage::ErrorPageExtensionOption::url
3416 \brief the url for which an error occurred
3420 \variable QWebPage::ErrorPageExtensionOption::frame
3421 \brief the frame associated with the error
3425 \variable QWebPage::ErrorPageExtensionOption::domain
3426 \brief the domain that reported the error
3430 \variable QWebPage::ErrorPageExtensionOption::error
3431 \brief the error code. Interpretation of the value depends on the \a domain
3432 \sa QWebPage::ErrorDomain
3436 \variable QWebPage::ErrorPageExtensionOption::errorString
3437 \brief a string that describes the error
3441 \class QWebPage::ErrorPageExtensionReturn
3443 \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the
3444 frame for which the error occured.
3448 The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are
3449 optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which
3450 is assumed to be UTF-8 if not indicated otherwise.
3452 The error page is stored in the \a content byte array, as HTML content. In order to convert a
3453 QString to a byte array, the QString::toUtf8() method can be used.
3455 External objects such as stylesheets or images referenced in the HTML are located relative to
3458 \sa QWebPage::extension() QWebPage::ErrorPageExtensionOption, QString::toUtf8()
3462 \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn()
3464 Constructs a new error page object.
3469 \variable QWebPage::ErrorPageExtensionReturn::contentType
3470 \brief the error page's content type
3474 \variable QWebPage::ErrorPageExtensionReturn::encoding
3475 \brief the error page encoding
3479 \variable QWebPage::ErrorPageExtensionReturn::baseUrl
3482 External objects such as stylesheets or images referenced in the HTML are located relative to this url.
3486 \variable QWebPage::ErrorPageExtensionReturn::content
3487 \brief the HTML content of the error page
3491 \class QWebPage::ChooseMultipleFilesExtensionOption
3493 \brief The ChooseMultipleFilesExtensionOption class describes the option
3494 for the multiple files selection extension.
3498 The ChooseMultipleFilesExtensionOption class holds the frame originating the request
3499 and the suggested filenames which might be provided.
3501 \sa QWebPage::extension() QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn
3505 \variable QWebPage::ChooseMultipleFilesExtensionOption::parentFrame
3506 \brief The frame in which the request originated
3510 \variable QWebPage::ChooseMultipleFilesExtensionOption::suggestedFileNames
3511 \brief The suggested filenames
3515 \variable QWebPage::ChooseMultipleFilesExtensionReturn::fileNames
3516 \brief The selected filenames
3520 \class QWebPage::ChooseMultipleFilesExtensionReturn
3522 \brief The ChooseMultipleFilesExtensionReturn describes the return value
3523 for the multiple files selection extension.
3527 The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user
3528 when the extension is invoked.
3530 \sa QWebPage::extension() QWebPage::ChooseMultipleFilesExtensionOption
3534 This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option
3535 argument is provided as input to the extension; the output results can be stored in \a output.
3537 The behavior of this function is determined by \a extension. The \a option
3538 and \a output values are typically casted to the corresponding types (for
3539 example, ChooseMultipleFilesExtensionOption and
3540 ChooseMultipleFilesExtensionReturn for ChooseMultipleFilesExtension).
3542 You can call supportsExtension() to check if an extension is supported by the page.
3544 Returns true if the extension was called successfully; otherwise returns false.
3546 \sa supportsExtension(), Extension
3548 bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
3550 #ifndef QT_NO_FILEDIALOG
3551 if (extension == ChooseMultipleFilesExtension) {
3552 // FIXME: do not ignore suggestedFiles
3553 QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames;
3554 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
3555 QStringList names = QFileDialog::getOpenFileNames(parent, QString::null);
3556 static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
3565 This virtual function returns true if the web page supports \a extension; otherwise false is returned.
3569 bool QWebPage::supportsExtension(Extension extension) const
3571 #ifndef QT_NO_FILEDIALOG
3572 return extension == ChooseMultipleFilesExtension;
3574 Q_UNUSED(extension);
3580 Finds the specified string, \a subString, in the page, using the given \a options.
3582 If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences
3583 that exist in the page. All subsequent calls will extend the highlight, rather than
3584 replace it, with occurrences of the new string.
3586 If the HighlightAllOccurrences flag is not passed, the function will select an occurrence
3587 and all subsequent calls will replace the current occurrence with the next one.
3589 To clear the selection, just pass an empty string.
3591 Returns true if \a subString was found; otherwise returns false.
3593 bool QWebPage::findText(const QString &subString, FindFlags options)
3595 ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive;
3596 if (options & FindCaseSensitively)
3597 caseSensitivity = ::TextCaseSensitive;
3599 if (options & HighlightAllOccurrences) {
3600 if (subString.isEmpty()) {
3601 d->page->unmarkAllTextMatches();
3604 return d->page->markAllMatchesForText(subString, caseSensitivity, true, 0);
3606 if (subString.isEmpty()) {
3607 d->page->mainFrame()->selection()->clear();
3608 Frame* frame = d->page->mainFrame()->tree()->firstChild();
3610 frame->selection()->clear();
3611 frame = frame->tree()->traverseNextWithWrap(false);
3614 ::FindDirection direction = ::FindDirectionForward;
3615 if (options & FindBackward)
3616 direction = ::FindDirectionBackward;
3618 const bool shouldWrap = options & FindWrapsAroundDocument;
3620 return d->page->findString(subString, caseSensitivity, direction, shouldWrap);
3625 Returns a pointer to the page's settings object.
3627 \sa QWebSettings::globalSettings()
3629 QWebSettings *QWebPage::settings() const
3635 This function is called when the web content requests a file name, for example
3636 as a result of the user clicking on a "file upload" button in a HTML form.
3638 A suggested filename may be provided in \a suggestedFile. The frame originating the
3639 request is provided as \a parentFrame.
3641 \sa ChooseMultipleFilesExtension
3643 QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile)
3645 Q_UNUSED(parentFrame)
3646 #ifndef QT_NO_FILEDIALOG
3647 QWidget* parent = (d->client) ? d->client->ownerWidget() : 0;
3648 return QFileDialog::getOpenFileName(parent, QString::null, suggestedFile);
3650 return QString::null;
3655 Sets the QNetworkAccessManager \a manager responsible for serving network requests for this
3658 \note It is currently not supported to change the network access manager after the
3659 QWebPage has used it. The results of doing this are undefined.
3661 \sa networkAccessManager()
3663 void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager)
3665 if (manager == d->networkManager)
3667 if (d->networkManager && d->networkManager->parent() == this)
3668 delete d->networkManager;
3669 d->networkManager = manager;
3673 Returns the QNetworkAccessManager that is responsible for serving network
3674 requests for this QWebPage.
3676 \sa setNetworkAccessManager()
3678 QNetworkAccessManager *QWebPage::networkAccessManager() const
3680 if (!d->networkManager) {
3681 QWebPage *that = const_cast<QWebPage *>(this);
3682 that->d->networkManager = new QNetworkAccessManager(that);
3684 return d->networkManager;
3688 Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this
3691 Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled.
3695 void QWebPage::setPluginFactory(QWebPluginFactory *factory)
3697 d->pluginFactory = factory;
3701 Returns the QWebPluginFactory that is responsible for creating plugins embedded into
3702 this QWebPage. If no plugin factory is installed a null pointer is returned.
3704 \sa setPluginFactory()
3706 QWebPluginFactory *QWebPage::pluginFactory() const
3708 return d->pluginFactory;
3712 This function is called when a user agent for HTTP requests is needed. You can reimplement this
3713 function to dynamically return different user agents for different URLs, based on the \a url parameter.
3715 The default implementation returns the following value:
3717 "Mozilla/5.0 (%Platform%%Security%%Subplatform%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%"
3719 On mobile platforms such as Symbian S60 and Maemo, "Mobile Safari" is used instead of "Safari".
3721 In this string the following values are replaced at run-time:
3723 \o %Platform% expands to the windowing system followed by "; " if it is not Windows (e.g. "X11; ").
3724 \o %Security% expands to "N; " if SSL is disabled.
3725 \o %Subplatform% expands to the operating system version (e.g. "Windows NT 6.1" or "Intel Mac OS X 10.5").
3726 \o %WebKitVersion% is the version of WebKit the application was compiled against.
3727 \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version.
3730 QString QWebPage::userAgentForUrl(const QUrl&) const
3732 // splitting the string in three and user QStringBuilder is better than using QString::arg()
3733 static QString firstPart;
3734 static QString secondPart;
3735 static QString thirdPart;
3737 if (firstPart.isNull() || secondPart.isNull() || thirdPart.isNull()) {
3738 QString firstPartTemp;
3739 firstPartTemp.reserve(150);
3740 firstPartTemp += QString::fromLatin1("Mozilla/5.0 ("
3745 #elif defined Q_WS_QWS
3747 #elif defined Q_WS_MAEMO_5
3749 #elif defined Q_WS_MAEMO_6
3751 #elif defined Q_WS_WIN
3753 #elif defined Q_WS_X11
3755 #elif defined Q_OS_SYMBIAN
3762 #if defined Q_OS_SYMBIAN
3763 QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
3764 switch (symbianVersion) {
3765 case QSysInfo::SV_9_2:
3766 firstPartTemp += QString::fromLatin1("OS/9.2; ");
3768 case QSysInfo::SV_9_3:
3769 firstPartTemp += QString::fromLatin1("OS/9.3; ");
3771 case QSysInfo::SV_9_4:
3772 firstPartTemp += QString::fromLatin1("OS/9.4; ");
3774 case QSysInfo::SV_SF_2:
3775 firstPartTemp += QString::fromLatin1("/2; ");
3777 case QSysInfo::SV_SF_3:
3778 firstPartTemp += QString::fromLatin1("/3; ");
3780 case QSysInfo::SV_SF_4:
3781 firstPartTemp += QString::fromLatin1("/4; ");
3784 firstPartTemp += QString::fromLatin1("; ");
3789 #if defined(QT_NO_OPENSSL)
3791 firstPartTemp += QString::fromLatin1("N; ");
3796 firstPartTemp += QString::fromLatin1("AIX");
3797 #elif defined Q_OS_WIN32
3798 firstPartTemp += windowsVersionForUAString();
3799 #elif defined Q_OS_DARWIN
3800 #ifdef __i386__ || __x86_64__
3801 firstPartTemp += QString::fromLatin1("Intel Mac OS X");
3803 firstPartTemp += QString::fromLatin1("PPC Mac OS X");
3806 #elif defined Q_OS_BSDI
3807 firstPartTemp += QString::fromLatin1("BSD");
3808 #elif defined Q_OS_BSD4
3809 firstPartTemp += QString::fromLatin1("BSD Four");
3810 #elif defined Q_OS_CYGWIN
3811 firstPartTemp += QString::fromLatin1("Cygwin");
3812 #elif defined Q_OS_DGUX
3813 firstPartTemp += QString::fromLatin1("DG/UX");
3814 #elif defined Q_OS_DYNIX
3815 firstPartTemp += QString::fromLatin1("DYNIX/ptx");
3816 #elif defined Q_OS_FREEBSD
3817 firstPartTemp += QString::fromLatin1("FreeBSD");
3818 #elif defined Q_OS_HPUX
3819 firstPartTemp += QString::fromLatin1("HP-UX");
3820 #elif defined Q_OS_HURD
3821 firstPartTemp += QString::fromLatin1("GNU Hurd");
3822 #elif defined Q_OS_IRIX
3823 firstPartTemp += QString::fromLatin1("SGI Irix");
3824 #elif defined Q_OS_LINUX
3825 #if !defined(Q_WS_MAEMO_5) && !defined(Q_WS_MAEMO_6)
3827 #if defined(__x86_64__)
3828 firstPartTemp += QString::fromLatin1("Linux x86_64");
3829 #elif defined(__i386__)
3830 firstPartTemp += QString::fromLatin1("Linux i686");
3832 firstPartTemp += QString::fromLatin1("Linux");
3836 #elif defined Q_OS_LYNX
3837 firstPartTemp += QString::fromLatin1("LynxOS");
3838 #elif defined Q_OS_NETBSD
3839 firstPartTemp += QString::fromLatin1("NetBSD");
3840 #elif defined Q_OS_OS2
3841 firstPartTemp += QString::fromLatin1("OS/2");
3842 #elif defined Q_OS_OPENBSD
3843 firstPartTemp += QString::fromLatin1("OpenBSD");
3844 #elif defined Q_OS_OS2EMX
3845 firstPartTemp += QString::fromLatin1("OS/2");
3846 #elif defined Q_OS_OSF
3847 firstPartTemp += QString::fromLatin1("HP Tru64 UNIX");
3848 #elif defined Q_OS_QNX6
3849 firstPartTemp += QString::fromLatin1("QNX RTP Six");
3850 #elif defined Q_OS_QNX
3851 firstPartTemp += QString::fromLatin1("QNX");
3852 #elif defined Q_OS_RELIANT
3853 firstPartTemp += QString::fromLatin1("Reliant UNIX");
3854 #elif defined Q_OS_SCO
3855 firstPartTemp += QString::fromLatin1("SCO OpenServer");
3856 #elif defined Q_OS_SOLARIS
3857 firstPartTemp += QString::fromLatin1("Sun Solaris");
3858 #elif defined Q_OS_ULTRIX
3859 firstPartTemp += QString::fromLatin1("DEC Ultrix");
3860 #elif defined Q_OS_SYMBIAN
3861 firstPartTemp += QLatin1Char(' ');
3862 QSysInfo::S60Version s60Version = QSysInfo::s60Version();
3863 switch (s60Version) {
3864 case QSysInfo::SV_S60_3_1:
3865 firstPartTemp += QString::fromLatin1("Series60/3.1");
3867 case QSysInfo::SV_S60_3_2:
3868 firstPartTemp += QString::fromLatin1("Series60/3.2");
3870 case QSysInfo::SV_S60_5_0:
3871 firstPartTemp += QString::fromLatin1("Series60/5.0");
3876 #elif defined Q_OS_UNIX
3877 firstPartTemp += QString::fromLatin1("UNIX BSD/SYSV system");
3878 #elif defined Q_OS_UNIXWARE
3879 firstPartTemp += QString::fromLatin1("UnixWare Seven, Open UNIX Eight");
3881 firstPartTemp += QString::fromLatin1("Unknown");
3884 #if USE(QT_MOBILITY_SYSTEMINFO)
3885 // adding Model Number
3886 QtMobility::QSystemDeviceInfo systemDeviceInfo;
3888 QString model = systemDeviceInfo.model();
3889 if (!model.isEmpty()) {
3890 if (!firstPartTemp.endsWith("; "))
3891 firstPartTemp += QString::fromLatin1("; ");
3892 firstPartTemp += systemDeviceInfo.model();
3895 firstPartTemp.squeeze();
3896 firstPart = firstPartTemp;
3898 QString secondPartTemp;
3899 secondPartTemp.reserve(150);
3900 secondPartTemp += QString::fromLatin1(") ");
3902 // webkit/qt version
3903 secondPartTemp += QString::fromLatin1("AppleWebKit/");
3904 secondPartTemp += qWebKitVersion();
3905 secondPartTemp += QString::fromLatin1(" (KHTML, like Gecko) ");
3908 // Application name split the third part
3909 secondPartTemp.squeeze();
3910 secondPart = secondPartTemp;
3912 QString thirdPartTemp;
3913 thirdPartTemp.reserve(150);
3914 #if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
3915 thirdPartTemp += QLatin1String(" Mobile Safari/");
3917 thirdPartTemp += QLatin1String(" Safari/");
3919 thirdPartTemp += qWebKitVersion();
3920 thirdPartTemp.squeeze();
3921 thirdPart = thirdPartTemp;
3922 Q_ASSERT(!firstPart.isNull());
3923 Q_ASSERT(!secondPart.isNull());
3924 Q_ASSERT(!thirdPart.isNull());
3927 // Application name/version
3928 QString appName = QCoreApplication::applicationName();
3929 if (!appName.isEmpty()) {
3930 QString appVer = QCoreApplication::applicationVersion();
3931 if (!appVer.isEmpty())
3932 appName.append(QLatin1Char('/') + appVer);
3935 appName = QString::fromLatin1("Qt/") + QString::fromLatin1(qVersion());
3938 return firstPart + secondPart + appName + thirdPart;
3942 void QWebPagePrivate::_q_onLoadProgressChanged(int)
3944 m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad();
3945 m_bytesReceived = page->progress()->totalBytesReceived();
3950 Returns the total number of bytes that were received from the network to render the current page,
3951 including extra content such as embedded images.
3955 quint64 QWebPage::totalBytes() const
3957 return d->m_totalBytes;
3962 Returns the number of bytes that were received from the network to render the current page.
3964 \sa totalBytes(), loadProgress()
3966 quint64 QWebPage::bytesReceived() const
3968 return d->m_bytesReceived;
3973 \fn void QWebPage::viewportChangeRequested()
3975 Page authors can provide the supplied values by using the viewport meta tag. More information
3976 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}.
3978 \sa QWebPage::ViewportAttributes, setPreferredContentsSize(), QGraphicsWebView::setScale()
3982 \fn void QWebPage::loadStarted()
3984 This signal is emitted when a page starts loading content.
3990 \fn void QWebPage::loadProgress(int progress)
3992 This signal is emitted when the global progress status changes.
3993 The current value is provided by \a progress and scales from 0 to 100,
3994 which is the default range of QProgressBar.
3995 It accumulates changes from all the child frames.
4001 \fn void QWebPage::loadFinished(bool ok)
4003 This signal is emitted when the page finishes loading content. This signal
4004 is independant of script execution or page rendering.
4005 \a ok will indicate whether the load was successful or any error occurred.
4007 \sa loadStarted(), ErrorPageExtension
4011 \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent)
4013 This signal is emitted when the mouse hovers over a link.
4015 \a link contains the link url.
4016 \a title is the link element's title, if it is specified in the markup.
4017 \a textContent provides text within the link element, e.g., text inside an HTML anchor tag.
4019 When the mouse leaves the link element the signal is emitted with empty parameters.
4025 \fn void QWebPage::statusBarMessage(const QString& text)
4027 This signal is emitted when the statusbar \a text is changed by the page.
4031 \fn void QWebPage::frameCreated(QWebFrame *frame)
4033 This signal is emitted whenever the page creates a new \a frame.
4039 \fn void QWebPage::selectionChanged()
4041 This signal is emitted whenever the selection changes, either interactively
4042 or programmatically (e.g. by calling triggerAction() with a selection action).
4048 \fn void QWebPage::contentsChanged()
4051 This signal is emitted whenever the text in form elements changes
4052 as well as other editable content.
4054 \sa contentEditable, modified, QWebFrame::toHtml(), QWebFrame::toPlainText()
4058 \fn void QWebPage::geometryChangeRequested(const QRect& geom)
4060 This signal is emitted whenever the document wants to change the position and size of the
4061 page to \a geom. This can happen for example through JavaScript.
4065 \fn void QWebPage::repaintRequested(const QRect& dirtyRect)
4067 This signal is emitted whenever this QWebPage should be updated. It's useful
4068 when rendering a QWebPage without a QWebView or QGraphicsWebView.
4069 \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get
4070 the mainFrame() and call the render(QPainter*, const QRegion&) method with the
4071 \a dirtyRect as the second parameter.
4078 \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll)
4080 This signal is emitted whenever the content given by \a rectToScroll needs
4081 to be scrolled \a dx and \a dy downwards and no view was set.
4087 \fn void QWebPage::windowCloseRequested()
4089 This signal is emitted whenever the page requests the web browser window to be closed,
4090 for example through the JavaScript \c{window.close()} call.
4094 \fn void QWebPage::printRequested(QWebFrame *frame)
4096 This signal is emitted whenever the page requests the web browser to print \a frame,
4097 for example through the JavaScript \c{window.print()} call.
4099 \sa QWebFrame::print(), QPrintPreviewDialog
4103 \fn void QWebPage::unsupportedContent(QNetworkReply *reply)
4105 This signal is emitted when WebKit cannot handle a link the user navigated to or a
4106 web server's response includes a "Content-Disposition" header with the 'attachment'
4107 directive. If "Content-Disposition" is present in \a reply, the web server is indicating
4108 that the client should prompt the user to save the content regardless of content-type.
4109 See RFC 2616 sections 19.5.1 for details about Content-Disposition.
4111 At signal emission time the meta-data of the QNetworkReply \a reply is available.
4113 \note The receiving slot is responsible for deleting the QNetworkReply \a reply.
4115 \note This signal is only emitted if the forwardUnsupportedContent property is set to true.
4117 \sa downloadRequested()
4121 \fn void QWebPage::downloadRequested(const QNetworkRequest &request)
4123 This signal is emitted when the user decides to download a link. The url of
4124 the link as well as additional meta-information is contained in \a request.
4126 \sa unsupportedContent()
4130 \fn void QWebPage::microFocusChanged()
4132 This signal is emitted when for example the position of the cursor in an editable form
4133 element changes. It is used to inform input methods about the new on-screen position where
4134 the user is able to enter text. This signal is usually connected to the
4135 QWidget::updateMicroFocus() slot.
4139 \fn void QWebPage::linkClicked(const QUrl &url)
4141 This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy
4142 property is set to delegate the link handling for the specified \a url.
4144 By default no links are delegated and are handled by QWebPage instead.
4146 \note This signal possibly won't be emitted for clicked links which use
4147 JavaScript to trigger navigation.
4153 \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible)
4155 This signal is emitted whenever the visibility of the toolbar in a web browser
4156 window that hosts QWebPage should be changed to \a visible.
4160 \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible)
4162 This signal is emitted whenever the visibility of the statusbar in a web browser
4163 window that hosts QWebPage should be changed to \a visible.
4167 \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible)
4169 This signal is emitted whenever the visibility of the menubar in a web browser
4170 window that hosts QWebPage should be changed to \a visible.
4174 \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName);
4177 This signal is emitted whenever the web site shown in \a frame is asking to store data
4178 to the database \a databaseName and the quota allocated to that web site is exceeded.
4183 \fn void QWebPage::applicationCacheQuotaExceeded(QWebSecurityOrigin* origin, quint64 defaultOriginQuota, quint64 totalSpaceNeeded);
4185 This signal is emitted whenever the web site is asking to store data to the application cache
4186 database databaseName and the quota allocated to that web site is exceeded.
4192 \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item);
4194 This signal is emitted shortly before the history of navigated pages
4195 in \a frame is changed, for example when navigating back in the history.
4197 The provided QWebHistoryItem, \a item, holds the history entry of the frame before
4200 A potential use-case for this signal is to store custom data in
4201 the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
4206 \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame);
4208 This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly.
4212 \fn QWebPagePrivate* QWebPage::handle() const
4216 #include "moc_qwebpage.cpp"