| /* |
| Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies) |
| Copyright (C) 2007 Staikos Computing Services Inc. |
| Copyright (C) 2007 Apple Inc. |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Library General Public |
| License as published by the Free Software Foundation; either |
| version 2 of the License, or (at your option) any later version. |
| |
| This library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Library General Public License for more details. |
| |
| You should have received a copy of the GNU Library General Public License |
| along with this library; see the file COPYING.LIB. If not, write to |
| the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "config.h" |
| #include "qwebpage.h" |
| |
| #include "qwebview.h" |
| #include "qwebframe.h" |
| #include "qwebpage_p.h" |
| #include "qwebframe_p.h" |
| #include "qwebhistory.h" |
| #include "qwebhistory_p.h" |
| #include "qwebinspector.h" |
| #include "qwebinspector_p.h" |
| #include "qwebsettings.h" |
| #include "qwebkitplatformplugin.h" |
| #include "qwebkitversion.h" |
| |
| #include "CSSComputedStyleDeclaration.h" |
| #include "CSSParser.h" |
| #include "ApplicationCacheStorage.h" |
| #include "BackForwardListImpl.h" |
| #include "MemoryCache.h" |
| #include "Chrome.h" |
| #include "ChromeClientQt.h" |
| #include "ClientRect.h" |
| #include "ContextMenu.h" |
| #include "ContextMenuClientQt.h" |
| #include "ContextMenuController.h" |
| #include "DeviceMotionClientQt.h" |
| #include "DeviceOrientationClientQt.h" |
| #include "DocumentLoader.h" |
| #include "DragClientQt.h" |
| #include "DragController.h" |
| #include "DragData.h" |
| #include "Editor.h" |
| #include "EditorClientQt.h" |
| #include "FocusController.h" |
| #include "FormState.h" |
| #include "Frame.h" |
| #include "FrameLoadRequest.h" |
| #include "FrameLoader.h" |
| #include "FrameLoader.h" |
| #include "FrameLoaderClientQt.h" |
| #include "FrameTree.h" |
| #include "FrameView.h" |
| #if ENABLE(CLIENT_BASED_GEOLOCATION) |
| #include "GeolocationClientMock.h" |
| #include "GeolocationClientQt.h" |
| #endif // CLIENT_BASED_GEOLOCATION |
| #include "GeolocationPermissionClientQt.h" |
| #include "HTMLFormElement.h" |
| #include "HTMLFrameOwnerElement.h" |
| #include "HTMLInputElement.h" |
| #include "HTMLNames.h" |
| #include "HashMap.h" |
| #include "HitTestResult.h" |
| #include "Image.h" |
| #include "InspectorClientQt.h" |
| #include "InspectorController.h" |
| #include "InspectorServerQt.h" |
| #include "KURL.h" |
| #include "LocalizedStrings.h" |
| #include "Logging.h" |
| #include "MIMETypeRegistry.h" |
| #include "NavigationAction.h" |
| #include "NetworkingContext.h" |
| #include "NodeList.h" |
| #include "NotificationPresenterClientQt.h" |
| #include "NotImplemented.h" |
| #include "Page.h" |
| #include "PageClientQt.h" |
| #include "PageGroup.h" |
| #include "Pasteboard.h" |
| #include "PlatformKeyboardEvent.h" |
| #include "PlatformTouchEvent.h" |
| #include "PlatformWheelEvent.h" |
| #include "PluginDatabase.h" |
| #include "PluginDatabase.h" |
| #include "PluginPackage.h" |
| #include "ProgressTracker.h" |
| #include "QtPlatformPlugin.h" |
| #include "RefPtr.h" |
| #include "RenderTextControl.h" |
| #include "SchemeRegistry.h" |
| #include "Scrollbar.h" |
| #include "SecurityOrigin.h" |
| #include "Settings.h" |
| #if defined Q_OS_WIN32 |
| #include "SystemInfo.h" |
| #endif // Q_OS_WIN32 |
| #include "TextIterator.h" |
| #include "WebPlatformStrategies.h" |
| #include "WindowFeatures.h" |
| #include "WorkerThread.h" |
| #include "runtime/InitializeThreading.h" |
| #include "wtf/Threading.h" |
| |
| #include <QApplication> |
| #include <QBasicTimer> |
| #include <QBitArray> |
| #include <QDebug> |
| #include <QDesktopWidget> |
| #include <QDragEnterEvent> |
| #include <QDragLeaveEvent> |
| #include <QDragMoveEvent> |
| #include <QDropEvent> |
| #include <QFileDialog> |
| #include <QHttpRequestHeader> |
| #include <QInputDialog> |
| #include <QMessageBox> |
| #include <QNetworkProxy> |
| #include <QUndoStack> |
| #include <QUrl> |
| #include <QPainter> |
| #include <QClipboard> |
| #include <QSslSocket> |
| #include <QStyle> |
| #include <QSysInfo> |
| #include <QTextCharFormat> |
| #include <QTextDocument> |
| #include <QTouchEvent> |
| #include <QNetworkAccessManager> |
| #include <QNetworkRequest> |
| #if defined(Q_WS_X11) |
| #include <QX11Info> |
| #endif |
| #if ENABLE(QT_USERAGENT_DEVICEMODEL) |
| #include <qsysteminfo.h> |
| #endif |
| |
| using namespace WebCore; |
| |
| // from text/qfont.cpp |
| QT_BEGIN_NAMESPACE |
| extern Q_GUI_EXPORT int qt_defaultDpi(); |
| QT_END_NAMESPACE |
| |
| bool QWebPagePrivate::drtRun = false; |
| |
| // Lookup table mapping QWebPage::WebActions to the associated Editor commands |
| static const char* editorCommandWebActions[] = |
| { |
| 0, // OpenLink, |
| |
| 0, // OpenLinkInNewWindow, |
| 0, // OpenFrameInNewWindow, |
| |
| 0, // DownloadLinkToDisk, |
| 0, // CopyLinkToClipboard, |
| |
| 0, // OpenImageInNewWindow, |
| 0, // DownloadImageToDisk, |
| 0, // CopyImageToClipboard, |
| 0, // CopyImageUrlToClipboard, |
| |
| 0, // Back, |
| 0, // Forward, |
| 0, // Stop, |
| 0, // Reload, |
| |
| "Cut", // Cut, |
| "Copy", // Copy, |
| "Paste", // Paste, |
| |
| "Undo", // Undo, |
| "Redo", // Redo, |
| "MoveForward", // MoveToNextChar, |
| "MoveBackward", // MoveToPreviousChar, |
| "MoveWordForward", // MoveToNextWord, |
| "MoveWordBackward", // MoveToPreviousWord, |
| "MoveDown", // MoveToNextLine, |
| "MoveUp", // MoveToPreviousLine, |
| "MoveToBeginningOfLine", // MoveToStartOfLine, |
| "MoveToEndOfLine", // MoveToEndOfLine, |
| "MoveToBeginningOfParagraph", // MoveToStartOfBlock, |
| "MoveToEndOfParagraph", // MoveToEndOfBlock, |
| "MoveToBeginningOfDocument", // MoveToStartOfDocument, |
| "MoveToEndOfDocument", // MoveToEndOfDocument, |
| "MoveForwardAndModifySelection", // SelectNextChar, |
| "MoveBackwardAndModifySelection", // SelectPreviousChar, |
| "MoveWordForwardAndModifySelection", // SelectNextWord, |
| "MoveWordBackwardAndModifySelection", // SelectPreviousWord, |
| "MoveDownAndModifySelection", // SelectNextLine, |
| "MoveUpAndModifySelection", // SelectPreviousLine, |
| "MoveToBeginningOfLineAndModifySelection", // SelectStartOfLine, |
| "MoveToEndOfLineAndModifySelection", // SelectEndOfLine, |
| "MoveToBeginningOfParagraphAndModifySelection", // SelectStartOfBlock, |
| "MoveToEndOfParagraphAndModifySelection", // SelectEndOfBlock, |
| "MoveToBeginningOfDocumentAndModifySelection", //SelectStartOfDocument, |
| "MoveToEndOfDocumentAndModifySelection", // SelectEndOfDocument, |
| "DeleteWordBackward", // DeleteStartOfWord, |
| "DeleteWordForward", // DeleteEndOfWord, |
| |
| 0, // SetTextDirectionDefault, |
| 0, // SetTextDirectionLeftToRight, |
| 0, // SetTextDirectionRightToLeft, |
| |
| "ToggleBold", // ToggleBold, |
| "ToggleItalic", // ToggleItalic, |
| "ToggleUnderline", // ToggleUnderline, |
| |
| 0, // InspectElement, |
| |
| "InsertNewline", // InsertParagraphSeparator |
| "InsertLineBreak", // InsertLineSeparator |
| |
| "SelectAll", // SelectAll |
| 0, // ReloadAndBypassCache, |
| |
| "PasteAndMatchStyle", // PasteAndMatchStyle |
| "RemoveFormat", // RemoveFormat |
| "Strikethrough", // ToggleStrikethrough, |
| "Subscript", // ToggleSubscript |
| "Superscript", // ToggleSuperscript |
| "InsertUnorderedList", // InsertUnorderedList |
| "InsertOrderedList", // InsertOrderedList |
| "Indent", // Indent |
| "Outdent", // Outdent, |
| |
| "AlignCenter", // AlignCenter, |
| "AlignJustified", // AlignJustified, |
| "AlignLeft", // AlignLeft, |
| "AlignRight", // AlignRight, |
| |
| 0 // WebActionCount |
| }; |
| |
| // Lookup the appropriate editor command to use for WebAction \a action |
| const char* QWebPagePrivate::editorCommandForWebActions(QWebPage::WebAction action) |
| { |
| if ((action > QWebPage::NoWebAction) && (action < int(sizeof(editorCommandWebActions) / sizeof(const char*)))) |
| return editorCommandWebActions[action]; |
| return 0; |
| } |
| |
| static inline DragOperation dropActionToDragOp(Qt::DropActions actions) |
| { |
| unsigned result = 0; |
| if (actions & Qt::CopyAction) |
| result |= DragOperationCopy; |
| // DragOperationgeneric represents InternetExplorer's equivalent of Move operation, |
| // hence it should be considered as "move" |
| if (actions & Qt::MoveAction) |
| result |= (DragOperationMove | DragOperationGeneric); |
| if (actions & Qt::LinkAction) |
| result |= DragOperationLink; |
| return (DragOperation)result; |
| } |
| |
| static inline Qt::DropAction dragOpToDropAction(unsigned actions) |
| { |
| Qt::DropAction result = Qt::IgnoreAction; |
| if (actions & DragOperationCopy) |
| result = Qt::CopyAction; |
| else if (actions & DragOperationMove) |
| result = Qt::MoveAction; |
| // DragOperationgeneric represents InternetExplorer's equivalent of Move operation, |
| // hence it should be considered as "move" |
| else if (actions & DragOperationGeneric) |
| result = Qt::MoveAction; |
| else if (actions & DragOperationLink) |
| result = Qt::LinkAction; |
| return result; |
| } |
| |
| QWebPagePrivate::QWebPagePrivate(QWebPage *qq) |
| : q(qq) |
| , page(0) |
| , client(0) |
| , mainFrame(0) |
| #ifndef QT_NO_UNDOSTACK |
| , undoStack(0) |
| #endif |
| , insideOpenCall(false) |
| , m_totalBytes(0) |
| , m_bytesReceived() |
| , clickCausedFocus(false) |
| , networkManager(0) |
| , forwardUnsupportedContent(false) |
| , smartInsertDeleteEnabled(true) |
| , selectTrailingWhitespaceEnabled(false) |
| , linkPolicy(QWebPage::DontDelegateLinks) |
| , viewportSize(QSize(0, 0)) |
| , pixelRatio(1) |
| #ifndef QT_NO_CONTEXTMENU |
| , currentContextMenu(0) |
| #endif |
| , settings(0) |
| , useFixedLayout(false) |
| , pluginFactory(0) |
| , inspectorFrontend(0) |
| , inspector(0) |
| , inspectorIsInternalOnly(false) |
| { |
| WebCore::InitializeLoggingChannelsIfNecessary(); |
| ScriptController::initializeThreading(); |
| WTF::initializeMainThread(); |
| WebCore::SecurityOrigin::setLocalLoadPolicy(WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData); |
| |
| WebPlatformStrategies::initialize(); |
| |
| Page::PageClients pageClients; |
| pageClients.chromeClient = new ChromeClientQt(q); |
| pageClients.contextMenuClient = new ContextMenuClientQt(); |
| pageClients.editorClient = new EditorClientQt(q); |
| pageClients.dragClient = new DragClientQt(q); |
| pageClients.inspectorClient = new InspectorClientQt(q); |
| #if ENABLE(DEVICE_ORIENTATION) |
| pageClients.deviceOrientationClient = new DeviceOrientationClientQt(q); |
| pageClients.deviceMotionClient = new DeviceMotionClientQt(q); |
| #endif |
| #if ENABLE(CLIENT_BASED_GEOLOCATION) |
| if (QWebPagePrivate::drtRun) |
| pageClients.geolocationClient = new GeolocationClientMock(); |
| else |
| pageClients.geolocationClient = new GeolocationClientQt(q); |
| #endif |
| page = new Page(pageClients); |
| |
| #if ENABLE(CLIENT_BASED_GEOLOCATION) |
| // In case running in DumpRenderTree mode set the controller to mock provider. |
| if (QWebPagePrivate::drtRun) |
| static_cast<GeolocationClientMock*>(pageClients.geolocationClient)->setController(page->geolocationController()); |
| #endif |
| settings = new QWebSettings(page->settings()); |
| |
| history.d = new QWebHistoryPrivate(static_cast<WebCore::BackForwardListImpl*>(page->backForwardList())); |
| memset(actions, 0, sizeof(actions)); |
| |
| PageGroup::setShouldTrackVisitedLinks(true); |
| |
| #if ENABLE(NOTIFICATIONS) |
| NotificationPresenterClientQt::notificationPresenter()->addClient(); |
| #endif |
| } |
| |
| QWebPagePrivate::~QWebPagePrivate() |
| { |
| if (inspector && inspectorIsInternalOnly) { |
| // Since we have to delete an internal inspector, |
| // call setInspector(0) directly to prevent potential crashes |
| setInspector(0); |
| } |
| #ifndef QT_NO_CONTEXTMENU |
| delete currentContextMenu; |
| #endif |
| #ifndef QT_NO_UNDOSTACK |
| delete undoStack; |
| #endif |
| delete settings; |
| delete page; |
| |
| if (inspector) |
| inspector->setPage(0); |
| |
| #if ENABLE(NOTIFICATIONS) |
| NotificationPresenterClientQt::notificationPresenter()->removeClient(); |
| #endif |
| } |
| |
| WebCore::ViewportArguments QWebPagePrivate::viewportArguments() |
| { |
| return page ? page->viewportArguments() : WebCore::ViewportArguments(); |
| } |
| |
| WebCore::Page* QWebPagePrivate::core(const QWebPage* page) |
| { |
| return page->d->page; |
| } |
| |
| QWebPagePrivate* QWebPagePrivate::priv(QWebPage* page) |
| { |
| return page->d; |
| } |
| |
| bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) |
| { |
| if (insideOpenCall |
| && frame == mainFrame) |
| return true; |
| return q->acceptNavigationRequest(frame, request, type); |
| } |
| |
| void QWebPagePrivate::createMainFrame() |
| { |
| if (!mainFrame) { |
| QWebFrameData frameData(page); |
| mainFrame = new QWebFrame(q, &frameData); |
| |
| emit q->frameCreated(mainFrame); |
| } |
| } |
| |
| static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action) |
| { |
| switch (action) { |
| case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink; |
| case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow; |
| case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk; |
| case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard; |
| case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow; |
| case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk; |
| case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard; |
| case WebCore::ContextMenuItemTagCopyImageUrlToClipboard: return QWebPage::CopyImageUrlToClipboard; |
| case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow; |
| case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy; |
| case WebCore::ContextMenuItemTagGoBack: return QWebPage::Back; |
| case WebCore::ContextMenuItemTagGoForward: return QWebPage::Forward; |
| case WebCore::ContextMenuItemTagStop: return QWebPage::Stop; |
| case WebCore::ContextMenuItemTagReload: return QWebPage::Reload; |
| case WebCore::ContextMenuItemTagCut: return QWebPage::Cut; |
| case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste; |
| case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault; |
| case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight; |
| case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft; |
| case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold; |
| case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic; |
| case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline; |
| case WebCore::ContextMenuItemTagSelectAll: return QWebPage::SelectAll; |
| #if ENABLE(INSPECTOR) |
| case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement; |
| #endif |
| default: break; |
| } |
| return QWebPage::NoWebAction; |
| } |
| |
| #ifndef QT_NO_CONTEXTMENU |
| QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu, |
| const QList<WebCore::ContextMenuItem> *items, QBitArray *visitedWebActions) |
| { |
| if (!client || !webcoreMenu) |
| return 0; |
| |
| QMenu* menu = new QMenu(client->ownerWidget()); |
| for (int i = 0; i < items->count(); ++i) { |
| const ContextMenuItem &item = items->at(i); |
| switch (item.type()) { |
| case WebCore::CheckableActionType: /* fall through */ |
| case WebCore::ActionType: { |
| QWebPage::WebAction action = webActionForContextMenuAction(item.action()); |
| QAction *a = q->action(action); |
| if (a) { |
| ContextMenuItem it(item); |
| page->contextMenuController()->checkOrEnableIfNeeded(it); |
| PlatformMenuItemDescription desc = it.releasePlatformDescription(); |
| a->setEnabled(desc.enabled); |
| a->setChecked(desc.checked); |
| a->setCheckable(item.type() == WebCore::CheckableActionType); |
| |
| menu->addAction(a); |
| visitedWebActions->setBit(action); |
| } |
| break; |
| } |
| case WebCore::SeparatorType: |
| menu->addSeparator(); |
| break; |
| case WebCore::SubmenuType: { |
| QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu(), visitedWebActions); |
| |
| bool anyEnabledAction = false; |
| |
| QList<QAction *> actions = subMenu->actions(); |
| for (int i = 0; i < actions.count(); ++i) { |
| if (actions.at(i)->isVisible()) |
| anyEnabledAction |= actions.at(i)->isEnabled(); |
| } |
| |
| // don't show sub-menus with just disabled actions |
| if (anyEnabledAction) { |
| subMenu->setTitle(item.title()); |
| menu->addAction(subMenu->menuAction()); |
| } else |
| delete subMenu; |
| break; |
| } |
| } |
| } |
| return menu; |
| } |
| #endif // QT_NO_CONTEXTMENU |
| |
| #ifndef QT_NO_ACTION |
| void QWebPagePrivate::_q_webActionTriggered(bool checked) |
| { |
| QAction *a = qobject_cast<QAction *>(q->sender()); |
| if (!a) |
| return; |
| QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt()); |
| q->triggerAction(action, checked); |
| } |
| #endif // QT_NO_ACTION |
| |
| void QWebPagePrivate::_q_cleanupLeakMessages() |
| { |
| #ifndef NDEBUG |
| // Need this to make leak messages accurate. |
| memoryCache()->setCapacities(0, 0, 0); |
| #endif |
| } |
| |
| void QWebPagePrivate::updateAction(QWebPage::WebAction action) |
| { |
| #ifdef QT_NO_ACTION |
| Q_UNUSED(action) |
| #else |
| QAction *a = actions[action]; |
| if (!a || !mainFrame) |
| return; |
| |
| WebCore::FrameLoader *loader = mainFrame->d->frame->loader(); |
| WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor(); |
| |
| bool enabled = a->isEnabled(); |
| bool checked = a->isChecked(); |
| |
| switch (action) { |
| case QWebPage::Back: |
| enabled = page->canGoBackOrForward(-1); |
| break; |
| case QWebPage::Forward: |
| enabled = page->canGoBackOrForward(1); |
| break; |
| case QWebPage::Stop: |
| enabled = loader->isLoading(); |
| break; |
| case QWebPage::Reload: |
| case QWebPage::ReloadAndBypassCache: |
| enabled = !loader->isLoading(); |
| break; |
| #ifndef QT_NO_UNDOSTACK |
| case QWebPage::Undo: |
| case QWebPage::Redo: |
| // those two are handled by QUndoStack |
| break; |
| #endif // QT_NO_UNDOSTACK |
| case QWebPage::SelectAll: // editor command is always enabled |
| break; |
| case QWebPage::SetTextDirectionDefault: |
| case QWebPage::SetTextDirectionLeftToRight: |
| case QWebPage::SetTextDirectionRightToLeft: |
| enabled = editor->canEdit(); |
| checked = false; |
| break; |
| default: { |
| // see if it's an editor command |
| const char* commandName = editorCommandForWebActions(action); |
| |
| // if it's an editor command, let it's logic determine state |
| if (commandName) { |
| Editor::Command command = editor->command(commandName); |
| enabled = command.isEnabled(); |
| if (enabled) |
| checked = command.state() != FalseTriState; |
| else |
| checked = false; |
| } |
| break; |
| } |
| } |
| |
| a->setEnabled(enabled); |
| |
| if (a->isCheckable()) |
| a->setChecked(checked); |
| #endif // QT_NO_ACTION |
| } |
| |
| void QWebPagePrivate::updateNavigationActions() |
| { |
| updateAction(QWebPage::Back); |
| updateAction(QWebPage::Forward); |
| updateAction(QWebPage::Stop); |
| updateAction(QWebPage::Reload); |
| updateAction(QWebPage::ReloadAndBypassCache); |
| } |
| |
| void QWebPagePrivate::updateEditorActions() |
| { |
| updateAction(QWebPage::Cut); |
| updateAction(QWebPage::Copy); |
| updateAction(QWebPage::Paste); |
| updateAction(QWebPage::MoveToNextChar); |
| updateAction(QWebPage::MoveToPreviousChar); |
| updateAction(QWebPage::MoveToNextWord); |
| updateAction(QWebPage::MoveToPreviousWord); |
| updateAction(QWebPage::MoveToNextLine); |
| updateAction(QWebPage::MoveToPreviousLine); |
| updateAction(QWebPage::MoveToStartOfLine); |
| updateAction(QWebPage::MoveToEndOfLine); |
| updateAction(QWebPage::MoveToStartOfBlock); |
| updateAction(QWebPage::MoveToEndOfBlock); |
| updateAction(QWebPage::MoveToStartOfDocument); |
| updateAction(QWebPage::MoveToEndOfDocument); |
| updateAction(QWebPage::SelectNextChar); |
| updateAction(QWebPage::SelectPreviousChar); |
| updateAction(QWebPage::SelectNextWord); |
| updateAction(QWebPage::SelectPreviousWord); |
| updateAction(QWebPage::SelectNextLine); |
| updateAction(QWebPage::SelectPreviousLine); |
| updateAction(QWebPage::SelectStartOfLine); |
| updateAction(QWebPage::SelectEndOfLine); |
| updateAction(QWebPage::SelectStartOfBlock); |
| updateAction(QWebPage::SelectEndOfBlock); |
| updateAction(QWebPage::SelectStartOfDocument); |
| updateAction(QWebPage::SelectEndOfDocument); |
| updateAction(QWebPage::DeleteStartOfWord); |
| updateAction(QWebPage::DeleteEndOfWord); |
| updateAction(QWebPage::SetTextDirectionDefault); |
| updateAction(QWebPage::SetTextDirectionLeftToRight); |
| updateAction(QWebPage::SetTextDirectionRightToLeft); |
| updateAction(QWebPage::ToggleBold); |
| updateAction(QWebPage::ToggleItalic); |
| updateAction(QWebPage::ToggleUnderline); |
| updateAction(QWebPage::InsertParagraphSeparator); |
| updateAction(QWebPage::InsertLineSeparator); |
| updateAction(QWebPage::PasteAndMatchStyle); |
| updateAction(QWebPage::RemoveFormat); |
| updateAction(QWebPage::ToggleStrikethrough); |
| updateAction(QWebPage::ToggleSubscript); |
| updateAction(QWebPage::ToggleSuperscript); |
| updateAction(QWebPage::InsertUnorderedList); |
| updateAction(QWebPage::InsertOrderedList); |
| updateAction(QWebPage::Indent); |
| updateAction(QWebPage::Outdent); |
| updateAction(QWebPage::AlignCenter); |
| updateAction(QWebPage::AlignJustified); |
| updateAction(QWebPage::AlignLeft); |
| updateAction(QWebPage::AlignRight); |
| } |
| |
| void QWebPagePrivate::timerEvent(QTimerEvent *ev) |
| { |
| int timerId = ev->timerId(); |
| if (timerId == tripleClickTimer.timerId()) |
| tripleClickTimer.stop(); |
| else |
| q->timerEvent(ev); |
| } |
| |
| template<class T> |
| void QWebPagePrivate::mouseMoveEvent(T* ev) |
| { |
| WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); |
| if (!frame->view()) |
| return; |
| |
| bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0)); |
| ev->setAccepted(accepted); |
| } |
| |
| template<class T> |
| void QWebPagePrivate::mousePressEvent(T* ev) |
| { |
| WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); |
| if (!frame->view()) |
| return; |
| |
| RefPtr<WebCore::Node> oldNode; |
| Frame* focusedFrame = page->focusController()->focusedFrame(); |
| if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0) |
| oldNode = focusedDocument->focusedNode(); |
| |
| if (tripleClickTimer.isActive() |
| && (ev->pos() - tripleClick).manhattanLength() |
| < QApplication::startDragDistance()) { |
| mouseTripleClickEvent(ev); |
| return; |
| } |
| |
| bool accepted = false; |
| adjustPointForClicking(ev); |
| PlatformMouseEvent mev(ev, 1); |
| // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton |
| if (mev.button() != NoButton) |
| accepted = frame->eventHandler()->handleMousePressEvent(mev); |
| ev->setAccepted(accepted); |
| |
| RefPtr<WebCore::Node> newNode; |
| focusedFrame = page->focusController()->focusedFrame(); |
| if (Document* focusedDocument = focusedFrame ? focusedFrame->document() : 0) |
| newNode = focusedDocument->focusedNode(); |
| |
| if (newNode && oldNode != newNode) |
| clickCausedFocus = true; |
| } |
| |
| template<class T> |
| void QWebPagePrivate::mouseDoubleClickEvent(T *ev) |
| { |
| WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); |
| if (!frame->view()) |
| return; |
| |
| bool accepted = false; |
| PlatformMouseEvent mev(ev, 2); |
| // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton |
| if (mev.button() != NoButton) |
| accepted = frame->eventHandler()->handleMousePressEvent(mev); |
| ev->setAccepted(accepted); |
| |
| tripleClickTimer.start(QApplication::doubleClickInterval(), q); |
| tripleClick = QPointF(ev->pos()).toPoint(); |
| } |
| |
| template<class T> |
| void QWebPagePrivate::mouseTripleClickEvent(T *ev) |
| { |
| WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); |
| if (!frame->view()) |
| return; |
| |
| bool accepted = false; |
| PlatformMouseEvent mev(ev, 3); |
| // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton |
| if (mev.button() != NoButton) |
| accepted = frame->eventHandler()->handleMousePressEvent(mev); |
| ev->setAccepted(accepted); |
| } |
| |
| void QWebPagePrivate::handleClipboard(QEvent* ev, Qt::MouseButton button) |
| { |
| #ifndef QT_NO_CLIPBOARD |
| if (QApplication::clipboard()->supportsSelection()) { |
| bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode(); |
| Pasteboard::generalPasteboard()->setSelectionMode(true); |
| WebCore::Frame* focusFrame = page->focusController()->focusedOrMainFrame(); |
| if (button == Qt::LeftButton) { |
| if (focusFrame && (focusFrame->editor()->canCopy() || focusFrame->editor()->canDHTMLCopy())) { |
| Pasteboard::generalPasteboard()->writeSelection(focusFrame->editor()->selectedRange().get(), focusFrame->editor()->canSmartCopyOrDelete(), focusFrame); |
| ev->setAccepted(true); |
| } |
| } else if (button == Qt::MidButton) { |
| if (focusFrame && (focusFrame->editor()->canPaste() || focusFrame->editor()->canDHTMLPaste())) { |
| focusFrame->editor()->paste(); |
| ev->setAccepted(true); |
| } |
| } |
| Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode); |
| } |
| #endif |
| } |
| |
| template<class T> |
| void QWebPagePrivate::mouseReleaseEvent(T *ev) |
| { |
| WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); |
| if (!frame->view()) |
| return; |
| |
| bool accepted = false; |
| adjustPointForClicking(ev); |
| PlatformMouseEvent mev(ev, 0); |
| // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton |
| if (mev.button() != NoButton) |
| accepted = frame->eventHandler()->handleMouseReleaseEvent(mev); |
| ev->setAccepted(accepted); |
| |
| handleClipboard(ev, ev->button()); |
| handleSoftwareInputPanel(ev->button(), QPointF(ev->pos()).toPoint()); |
| } |
| |
| void QWebPagePrivate::handleSoftwareInputPanel(Qt::MouseButton button, const QPoint& pos) |
| { |
| Frame* frame = page->focusController()->focusedFrame(); |
| if (!frame) |
| return; |
| |
| if (client && client->inputMethodEnabled() |
| && frame->document()->focusedNode() |
| && button == Qt::LeftButton && qApp->autoSipEnabled()) { |
| QStyle::RequestSoftwareInputPanel behavior = QStyle::RequestSoftwareInputPanel( |
| client->ownerWidget()->style()->styleHint(QStyle::SH_RequestSoftwareInputPanel)); |
| if (!clickCausedFocus || behavior == QStyle::RSIP_OnMouseClick) { |
| HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(frame->view()->windowToContents(pos), false); |
| if (result.isContentEditable()) { |
| QEvent event(QEvent::RequestSoftwareInputPanel); |
| QApplication::sendEvent(client->ownerWidget(), &event); |
| } |
| } |
| } |
| |
| clickCausedFocus = false; |
| } |
| |
| #ifndef QT_NO_CONTEXTMENU |
| void QWebPagePrivate::contextMenuEvent(const QPoint& globalPos) |
| { |
| QMenu *menu = q->createStandardContextMenu(); |
| if (menu) { |
| menu->exec(globalPos); |
| delete menu; |
| } |
| } |
| #endif // QT_NO_CONTEXTMENU |
| |
| /*! |
| \since 4.5 |
| This function creates the standard context menu which is shown when |
| the user clicks on the web page with the right mouse button. It is |
| called from the default contextMenuEvent() handler. The popup menu's |
| ownership is transferred to the caller. |
| */ |
| QMenu *QWebPage::createStandardContextMenu() |
| { |
| #ifndef QT_NO_CONTEXTMENU |
| QMenu *menu = d->currentContextMenu; |
| d->currentContextMenu = 0; |
| return menu; |
| #else |
| return 0; |
| #endif |
| } |
| |
| #ifndef QT_NO_WHEELEVENT |
| template<class T> |
| void QWebPagePrivate::wheelEvent(T *ev) |
| { |
| WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); |
| if (!frame->view()) |
| return; |
| |
| WebCore::PlatformWheelEvent pev(ev); |
| bool accepted = frame->eventHandler()->handleWheelEvent(pev); |
| ev->setAccepted(accepted); |
| } |
| #endif // QT_NO_WHEELEVENT |
| |
| #ifndef QT_NO_SHORTCUT |
| QWebPage::WebAction QWebPagePrivate::editorActionForKeyEvent(QKeyEvent* event) |
| { |
| static struct { |
| QKeySequence::StandardKey standardKey; |
| QWebPage::WebAction action; |
| } editorActions[] = { |
| { QKeySequence::Cut, QWebPage::Cut }, |
| { QKeySequence::Copy, QWebPage::Copy }, |
| { QKeySequence::Paste, QWebPage::Paste }, |
| { QKeySequence::Undo, QWebPage::Undo }, |
| { QKeySequence::Redo, QWebPage::Redo }, |
| { QKeySequence::MoveToNextChar, QWebPage::MoveToNextChar }, |
| { QKeySequence::MoveToPreviousChar, QWebPage::MoveToPreviousChar }, |
| { QKeySequence::MoveToNextWord, QWebPage::MoveToNextWord }, |
| { QKeySequence::MoveToPreviousWord, QWebPage::MoveToPreviousWord }, |
| { QKeySequence::MoveToNextLine, QWebPage::MoveToNextLine }, |
| { QKeySequence::MoveToPreviousLine, QWebPage::MoveToPreviousLine }, |
| { QKeySequence::MoveToStartOfLine, QWebPage::MoveToStartOfLine }, |
| { QKeySequence::MoveToEndOfLine, QWebPage::MoveToEndOfLine }, |
| { QKeySequence::MoveToStartOfBlock, QWebPage::MoveToStartOfBlock }, |
| { QKeySequence::MoveToEndOfBlock, QWebPage::MoveToEndOfBlock }, |
| { QKeySequence::MoveToStartOfDocument, QWebPage::MoveToStartOfDocument }, |
| { QKeySequence::MoveToEndOfDocument, QWebPage::MoveToEndOfDocument }, |
| { QKeySequence::SelectNextChar, QWebPage::SelectNextChar }, |
| { QKeySequence::SelectPreviousChar, QWebPage::SelectPreviousChar }, |
| { QKeySequence::SelectNextWord, QWebPage::SelectNextWord }, |
| { QKeySequence::SelectPreviousWord, QWebPage::SelectPreviousWord }, |
| { QKeySequence::SelectNextLine, QWebPage::SelectNextLine }, |
| { QKeySequence::SelectPreviousLine, QWebPage::SelectPreviousLine }, |
| { QKeySequence::SelectStartOfLine, QWebPage::SelectStartOfLine }, |
| { QKeySequence::SelectEndOfLine, QWebPage::SelectEndOfLine }, |
| { QKeySequence::SelectStartOfBlock, QWebPage::SelectStartOfBlock }, |
| { QKeySequence::SelectEndOfBlock, QWebPage::SelectEndOfBlock }, |
| { QKeySequence::SelectStartOfDocument, QWebPage::SelectStartOfDocument }, |
| { QKeySequence::SelectEndOfDocument, QWebPage::SelectEndOfDocument }, |
| { QKeySequence::DeleteStartOfWord, QWebPage::DeleteStartOfWord }, |
| { QKeySequence::DeleteEndOfWord, QWebPage::DeleteEndOfWord }, |
| { QKeySequence::InsertParagraphSeparator, QWebPage::InsertParagraphSeparator }, |
| { QKeySequence::InsertLineSeparator, QWebPage::InsertLineSeparator }, |
| { QKeySequence::SelectAll, QWebPage::SelectAll }, |
| { QKeySequence::UnknownKey, QWebPage::NoWebAction } |
| }; |
| |
| for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i) |
| if (event == editorActions[i].standardKey) |
| return editorActions[i].action; |
| |
| return QWebPage::NoWebAction; |
| } |
| #endif // QT_NO_SHORTCUT |
| |
| void QWebPagePrivate::keyPressEvent(QKeyEvent *ev) |
| { |
| bool handled = false; |
| WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); |
| // we forward the key event to WebCore first to handle potential DOM |
| // defined event handlers and later on end up in EditorClientQt::handleKeyboardEvent |
| // to trigger editor commands via triggerAction(). |
| if (!handled) |
| handled = frame->eventHandler()->keyEvent(ev); |
| if (!handled) { |
| handled = true; |
| if (!handleScrolling(ev, frame)) { |
| switch (ev->key()) { |
| case Qt::Key_Back: |
| q->triggerAction(QWebPage::Back); |
| break; |
| case Qt::Key_Forward: |
| q->triggerAction(QWebPage::Forward); |
| break; |
| case Qt::Key_Stop: |
| q->triggerAction(QWebPage::Stop); |
| break; |
| case Qt::Key_Refresh: |
| q->triggerAction(QWebPage::Reload); |
| break; |
| case Qt::Key_Backspace: |
| if (ev->modifiers() == Qt::ShiftModifier) |
| q->triggerAction(QWebPage::Forward); |
| else |
| q->triggerAction(QWebPage::Back); |
| break; |
| default: |
| handled = false; |
| break; |
| } |
| } |
| } |
| |
| ev->setAccepted(handled); |
| } |
| |
| void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev) |
| { |
| if (ev->isAutoRepeat()) { |
| ev->setAccepted(true); |
| return; |
| } |
| |
| WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); |
| bool handled = frame->eventHandler()->keyEvent(ev); |
| ev->setAccepted(handled); |
| } |
| |
| void QWebPagePrivate::focusInEvent(QFocusEvent*) |
| { |
| FocusController *focusController = page->focusController(); |
| focusController->setActive(true); |
| focusController->setFocused(true); |
| if (!focusController->focusedFrame()) |
| focusController->setFocusedFrame(QWebFramePrivate::core(mainFrame)); |
| } |
| |
| void QWebPagePrivate::focusOutEvent(QFocusEvent*) |
| { |
| // only set the focused frame inactive so that we stop painting the caret |
| // and the focus frame. But don't tell the focus controller so that upon |
| // focusInEvent() we can re-activate the frame. |
| FocusController *focusController = page->focusController(); |
| // Call setFocused first so that window.onblur doesn't get called twice |
| focusController->setFocused(false); |
| focusController->setActive(false); |
| } |
| |
| template<class T> |
| void QWebPagePrivate::dragEnterEvent(T* ev) |
| { |
| #ifndef QT_NO_DRAGANDDROP |
| DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(), |
| QCursor::pos(), dropActionToDragOp(ev->possibleActions())); |
| Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData)); |
| ev->setDropAction(action); |
| ev->acceptProposedAction(); |
| #endif |
| } |
| |
| template<class T> |
| void QWebPagePrivate::dragLeaveEvent(T *ev) |
| { |
| #ifndef QT_NO_DRAGANDDROP |
| DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone); |
| page->dragController()->dragExited(&dragData); |
| ev->accept(); |
| #endif |
| } |
| |
| template<class T> |
| void QWebPagePrivate::dragMoveEvent(T *ev) |
| { |
| #ifndef QT_NO_DRAGANDDROP |
| DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(), |
| QCursor::pos(), dropActionToDragOp(ev->possibleActions())); |
| Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData)); |
| ev->setDropAction(action); |
| if (action != Qt::IgnoreAction) |
| ev->acceptProposedAction(); |
| #endif |
| } |
| |
| template<class T> |
| void QWebPagePrivate::dropEvent(T *ev) |
| { |
| #ifndef QT_NO_DRAGANDDROP |
| DragData dragData(ev->mimeData(), QPointF(ev->pos()).toPoint(), |
| QCursor::pos(), dropActionToDragOp(ev->possibleActions())); |
| if (page->dragController()->performDrag(&dragData)) |
| ev->acceptProposedAction(); |
| #endif |
| } |
| |
| void QWebPagePrivate::leaveEvent(QEvent*) |
| { |
| // Fake a mouse move event just outside of the widget, since all |
| // the interesting mouse-out behavior like invalidating scrollbars |
| // is handled by the WebKit event handler's mouseMoved function. |
| QMouseEvent fakeEvent(QEvent::MouseMove, QCursor::pos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier); |
| mouseMoveEvent(&fakeEvent); |
| } |
| |
| /*! |
| \property QWebPage::palette |
| \brief the page's palette |
| |
| The base brush of the palette is used to draw the background of the main frame. |
| |
| By default, this property contains the application's default palette. |
| */ |
| void QWebPage::setPalette(const QPalette &pal) |
| { |
| d->palette = pal; |
| if (!d->mainFrame || !d->mainFrame->d->frame->view()) |
| return; |
| |
| QBrush brush = pal.brush(QPalette::Base); |
| QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor(); |
| QWebFramePrivate::core(d->mainFrame)->view()->updateBackgroundRecursively(backgroundColor, !backgroundColor.alpha()); |
| } |
| |
| QPalette QWebPage::palette() const |
| { |
| return d->palette; |
| } |
| |
| void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev) |
| { |
| WebCore::Frame *frame = page->focusController()->focusedOrMainFrame(); |
| WebCore::Editor *editor = frame->editor(); |
| |
| if (!editor->canEdit()) { |
| ev->ignore(); |
| return; |
| } |
| |
| Node* node = 0; |
| if (frame->selection()->rootEditableElement()) |
| node = frame->selection()->rootEditableElement()->shadowAncestorNode(); |
| |
| Vector<CompositionUnderline> underlines; |
| bool hasSelection = false; |
| |
| for (int i = 0; i < ev->attributes().size(); ++i) { |
| const QInputMethodEvent::Attribute& a = ev->attributes().at(i); |
| switch (a.type) { |
| case QInputMethodEvent::TextFormat: { |
| QTextCharFormat textCharFormat = a.value.value<QTextFormat>().toCharFormat(); |
| QColor qcolor = textCharFormat.underlineColor(); |
| 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)); |
| break; |
| } |
| case QInputMethodEvent::Cursor: { |
| frame->selection()->setCaretVisible(a.length); //if length is 0 cursor is invisible |
| if (a.length > 0) { |
| RenderObject* caretRenderer = frame->selection()->caretRenderer(); |
| if (caretRenderer) { |
| QColor qcolor = a.value.value<QColor>(); |
| caretRenderer->style()->setColor(Color(makeRGBA(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha()))); |
| } |
| } |
| break; |
| } |
| case QInputMethodEvent::Selection: { |
| hasSelection = true; |
| // A selection in the inputMethodEvent is always reflected in the visible text |
| if (node) |
| setSelectionRange(node, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length))); |
| |
| if (!ev->preeditString().isEmpty()) |
| editor->setComposition(ev->preeditString(), underlines, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length))); |
| else { |
| // If we are in the middle of a composition, an empty pre-edit string and a selection of zero |
| // cancels the current composition |
| if (editor->hasComposition() && (a.start + a.length == 0)) |
| editor->setComposition(QString(), underlines, 0, 0); |
| } |
| break; |
| } |
| } |
| } |
| |
| if (node && ev->replacementLength() > 0) { |
| int cursorPos = frame->selection()->extent().offsetInContainerNode(); |
| int start = cursorPos + ev->replacementStart(); |
| setSelectionRange(node, start, start + ev->replacementLength()); |
| // Commit regardless of whether commitString is empty, to get rid of selection. |
| editor->confirmComposition(ev->commitString()); |
| } else if (!ev->commitString().isEmpty()) { |
| if (editor->hasComposition()) |
| editor->confirmComposition(ev->commitString()); |
| else |
| editor->insertText(ev->commitString(), 0); |
| } else if (!hasSelection && !ev->preeditString().isEmpty()) |
| editor->setComposition(ev->preeditString(), underlines, 0, 0); |
| else if (ev->preeditString().isEmpty() && editor->hasComposition()) |
| editor->confirmComposition(String()); |
| |
| ev->accept(); |
| } |
| |
| #ifndef QT_NO_PROPERTIES |
| typedef struct { |
| const char* name; |
| double deferredRepaintDelay; |
| double initialDeferredRepaintDelayDuringLoading; |
| double maxDeferredRepaintDelayDuringLoading; |
| double deferredRepaintDelayIncrementDuringLoading; |
| } QRepaintThrottlingPreset; |
| |
| void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* event) |
| { |
| if (event->propertyName() == "_q_viewMode") { |
| page->setViewMode(Page::stringToViewMode(q->property("_q_viewMode").toString())); |
| } else if (event->propertyName() == "_q_HTMLTokenizerChunkSize") { |
| int chunkSize = q->property("_q_HTMLTokenizerChunkSize").toInt(); |
| q->handle()->page->setCustomHTMLTokenizerChunkSize(chunkSize); |
| } else if (event->propertyName() == "_q_HTMLTokenizerTimeDelay") { |
| double timeDelay = q->property("_q_HTMLTokenizerTimeDelay").toDouble(); |
| q->handle()->page->setCustomHTMLTokenizerTimeDelay(timeDelay); |
| } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelay") { |
| double p = q->property("_q_RepaintThrottlingDeferredRepaintDelay").toDouble(); |
| FrameView::setRepaintThrottlingDeferredRepaintDelay(p); |
| } else if (event->propertyName() == "_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading") { |
| double p = q->property("_q_RepaintThrottlingnInitialDeferredRepaintDelayDuringLoading").toDouble(); |
| FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(p); |
| } else if (event->propertyName() == "_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading") { |
| double p = q->property("_q_RepaintThrottlingMaxDeferredRepaintDelayDuringLoading").toDouble(); |
| FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(p); |
| } else if (event->propertyName() == "_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading") { |
| double p = q->property("_q_RepaintThrottlingDeferredRepaintDelayIncrementDuringLoading").toDouble(); |
| FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(p); |
| } else if (event->propertyName() == "_q_RepaintThrottlingPreset") { |
| static const QRepaintThrottlingPreset presets[] = { |
| { "NoThrottling", 0, 0, 0, 0 }, |
| { "Legacy", 0.025, 0, 2.5, 0.5 }, |
| { "Minimal", 0.01, 0, 1, 0.2 }, |
| { "Medium", 0.025, 1, 5, 0.5 }, |
| { "Heavy", 0.1, 2, 10, 1 } |
| }; |
| |
| QString p = q->property("_q_RepaintThrottlingPreset").toString(); |
| for(int i = 0; i < sizeof(presets) / sizeof(presets[0]); i++) { |
| if (p == QLatin1String(presets[i].name)) { |
| FrameView::setRepaintThrottlingDeferredRepaintDelay( |
| presets[i].deferredRepaintDelay); |
| FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading( |
| presets[i].initialDeferredRepaintDelayDuringLoading); |
| FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading( |
| presets[i].maxDeferredRepaintDelayDuringLoading); |
| FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading( |
| presets[i].deferredRepaintDelayIncrementDuringLoading); |
| break; |
| } |
| } |
| } |
| #if ENABLE(TILED_BACKING_STORE) |
| else if (event->propertyName() == "_q_TiledBackingStoreTileSize") { |
| WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); |
| if (!frame->tiledBackingStore()) |
| return; |
| QSize tileSize = q->property("_q_TiledBackingStoreTileSize").toSize(); |
| frame->tiledBackingStore()->setTileSize(tileSize); |
| } else if (event->propertyName() == "_q_TiledBackingStoreTileCreationDelay") { |
| WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); |
| if (!frame->tiledBackingStore()) |
| return; |
| int tileCreationDelay = q->property("_q_TiledBackingStoreTileCreationDelay").toInt(); |
| frame->tiledBackingStore()->setTileCreationDelay(static_cast<double>(tileCreationDelay) / 1000.); |
| } else if (event->propertyName() == "_q_TiledBackingStoreKeepAreaMultiplier") { |
| WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); |
| if (!frame->tiledBackingStore()) |
| return; |
| FloatSize keepMultiplier; |
| FloatSize coverMultiplier; |
| frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); |
| QSizeF qSize = q->property("_q_TiledBackingStoreKeepAreaMultiplier").toSizeF(); |
| keepMultiplier = FloatSize(qSize.width(), qSize.height()); |
| frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); |
| } else if (event->propertyName() == "_q_TiledBackingStoreCoverAreaMultiplier") { |
| WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); |
| if (!frame->tiledBackingStore()) |
| return; |
| FloatSize keepMultiplier; |
| FloatSize coverMultiplier; |
| frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); |
| QSizeF qSize = q->property("_q_TiledBackingStoreCoverAreaMultiplier").toSizeF(); |
| coverMultiplier = FloatSize(qSize.width(), qSize.height()); |
| frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); |
| } |
| #endif |
| else if (event->propertyName() == "_q_webInspectorServerPort") { |
| InspectorServerQt* inspectorServer = InspectorServerQt::server(); |
| inspectorServer->listen(inspectorServerPort()); |
| } else if (event->propertyName() == "_q_deadDecodedDataDeletionInterval") { |
| double interval = q->property("_q_deadDecodedDataDeletionInterval").toDouble(); |
| memoryCache()->setDeadDecodedDataDeletionInterval(interval); |
| } |
| } |
| #endif |
| |
| void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event) |
| { |
| WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); |
| WebCore::Editor* editor = frame->editor(); |
| if (editor->canEdit()) { |
| if (event->modifiers() == Qt::NoModifier |
| || event->modifiers() == Qt::ShiftModifier |
| || event->modifiers() == Qt::KeypadModifier) { |
| if (event->key() < Qt::Key_Escape) { |
| event->accept(); |
| } else { |
| switch (event->key()) { |
| case Qt::Key_Return: |
| case Qt::Key_Enter: |
| case Qt::Key_Delete: |
| case Qt::Key_Home: |
| case Qt::Key_End: |
| case Qt::Key_Backspace: |
| case Qt::Key_Left: |
| case Qt::Key_Right: |
| case Qt::Key_Up: |
| case Qt::Key_Down: |
| case Qt::Key_Tab: |
| event->accept(); |
| default: |
| break; |
| } |
| } |
| } |
| #ifndef QT_NO_SHORTCUT |
| else if (editorActionForKeyEvent(event) != QWebPage::NoWebAction) |
| event->accept(); |
| #endif |
| } |
| } |
| |
| bool QWebPagePrivate::handleScrolling(QKeyEvent *ev, Frame *frame) |
| { |
| ScrollDirection direction; |
| ScrollGranularity granularity; |
| |
| #ifndef QT_NO_SHORTCUT |
| if (ev == QKeySequence::MoveToNextPage |
| || (ev->key() == Qt::Key_Space && !(ev->modifiers() & Qt::ShiftModifier))) { |
| granularity = ScrollByPage; |
| direction = ScrollDown; |
| } else if (ev == QKeySequence::MoveToPreviousPage |
| || ((ev->key() == Qt::Key_Space) && (ev->modifiers() & Qt::ShiftModifier))) { |
| granularity = ScrollByPage; |
| direction = ScrollUp; |
| } else |
| #endif // QT_NO_SHORTCUT |
| if ((ev->key() == Qt::Key_Up && ev->modifiers() & Qt::ControlModifier) |
| || ev->key() == Qt::Key_Home) { |
| granularity = ScrollByDocument; |
| direction = ScrollUp; |
| } else if ((ev->key() == Qt::Key_Down && ev->modifiers() & Qt::ControlModifier) |
| || ev->key() == Qt::Key_End) { |
| granularity = ScrollByDocument; |
| direction = ScrollDown; |
| } else { |
| switch (ev->key()) { |
| case Qt::Key_Up: |
| granularity = ScrollByLine; |
| direction = ScrollUp; |
| break; |
| case Qt::Key_Down: |
| granularity = ScrollByLine; |
| direction = ScrollDown; |
| break; |
| case Qt::Key_Left: |
| granularity = ScrollByLine; |
| direction = ScrollLeft; |
| break; |
| case Qt::Key_Right: |
| granularity = ScrollByLine; |
| direction = ScrollRight; |
| break; |
| default: |
| return false; |
| } |
| } |
| |
| return frame->eventHandler()->scrollRecursively(direction, granularity); |
| } |
| |
| void QWebPagePrivate::adjustPointForClicking(QMouseEvent*) |
| { |
| notImplemented(); |
| } |
| |
| #if !defined(QT_NO_GRAPHICSVIEW) |
| void QWebPagePrivate::adjustPointForClicking(QGraphicsSceneMouseEvent* ev) |
| { |
| QtPlatformPlugin platformPlugin; |
| QWebTouchModifier* touchModifier = platformPlugin.createTouchModifier(); |
| if (!touchModifier) |
| return; |
| |
| unsigned topPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Up); |
| unsigned rightPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Right); |
| unsigned bottomPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Down); |
| unsigned leftPadding = touchModifier->hitTestPaddingForTouch(QWebTouchModifier::Left); |
| |
| delete touchModifier; |
| touchModifier = 0; |
| |
| if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) |
| return; |
| |
| Document* startingDocument = page->mainFrame()->document(); |
| if (!startingDocument) |
| return; |
| |
| IntPoint originalPoint(QPointF(ev->pos()).toPoint()); |
| TouchAdjuster touchAdjuster(topPadding, rightPadding, bottomPadding, leftPadding); |
| IntPoint adjustedPoint = touchAdjuster.findCandidatePointForTouch(originalPoint, startingDocument); |
| if (adjustedPoint == IntPoint::zero()) |
| return; |
| |
| ev->setPos(QPointF(adjustedPoint)); |
| } |
| #endif |
| |
| bool QWebPagePrivate::touchEvent(QTouchEvent* event) |
| { |
| #if ENABLE(TOUCH_EVENTS) |
| WebCore::Frame* frame = QWebFramePrivate::core(mainFrame); |
| if (!frame->view()) |
| return false; |
| |
| // Always accept the QTouchEvent so that we'll receive also TouchUpdate and TouchEnd events |
| event->setAccepted(true); |
| |
| // Return whether the default action was cancelled in the JS event handler |
| return frame->eventHandler()->handleTouchEvent(PlatformTouchEvent(event)); |
| #else |
| event->ignore(); |
| return false; |
| #endif |
| } |
| |
| /*! |
| This method is used by the input method to query a set of properties of the page |
| to be able to support complex input method operations as support for surrounding |
| text and reconversions. |
| |
| \a property specifies which property is queried. |
| |
| \sa QWidget::inputMethodEvent(), QInputMethodEvent, QInputContext |
| */ |
| QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const |
| { |
| Frame* frame = d->page->focusController()->focusedFrame(); |
| if (!frame) |
| return QVariant(); |
| |
| WebCore::Editor* editor = frame->editor(); |
| |
| RenderObject* renderer = 0; |
| RenderTextControl* renderTextControl = 0; |
| |
| if (frame->selection()->rootEditableElement()) |
| renderer = frame->selection()->rootEditableElement()->shadowAncestorNode()->renderer(); |
| |
| if (renderer && renderer->isTextControl()) |
| renderTextControl = toRenderTextControl(renderer); |
| |
| switch (property) { |
| case Qt::ImMicroFocus: { |
| WebCore::FrameView* view = frame->view(); |
| if (view && view->needsLayout()) { |
| // We can't access absoluteCaretBounds() while the view needs to layout. |
| return QVariant(); |
| } |
| return QVariant(view->contentsToWindow(frame->selection()->absoluteCaretBounds())); |
| } |
| case Qt::ImFont: { |
| if (renderTextControl) { |
| RenderStyle* renderStyle = renderTextControl->style(); |
| return QVariant(QFont(renderStyle->font().font())); |
| } |
| return QVariant(QFont()); |
| } |
| case Qt::ImCursorPosition: { |
| if (editor->hasComposition()) |
| return QVariant(frame->selection()->end().offsetInContainerNode()); |
| return QVariant(frame->selection()->extent().offsetInContainerNode()); |
| } |
| case Qt::ImSurroundingText: { |
| if (renderTextControl) { |
| QString text = renderTextControl->text(); |
| RefPtr<Range> range = editor->compositionRange(); |
| if (range) |
| text.remove(range->startPosition().offsetInContainerNode(), TextIterator::rangeLength(range.get())); |
| return QVariant(text); |
| } |
| return QVariant(); |
| } |
| case Qt::ImCurrentSelection: { |
| if (!editor->hasComposition() && renderTextControl) { |
| int start = frame->selection()->start().offsetInContainerNode(); |
| int end = frame->selection()->end().offsetInContainerNode(); |
| if (end > start) |
| return QVariant(QString(renderTextControl->text()).mid(start, end - start)); |
| } |
| return QVariant(); |
| |
| } |
| case Qt::ImAnchorPosition: { |
| if (editor->hasComposition()) |
| return QVariant(frame->selection()->start().offsetInContainerNode()); |
| return QVariant(frame->selection()->base().offsetInContainerNode()); |
| } |
| case Qt::ImMaximumTextLength: { |
| if (frame->selection()->isContentEditable()) { |
| if (frame->document() && frame->document()->focusedNode()) { |
| if (frame->document()->focusedNode()->hasTagName(HTMLNames::inputTag)) { |
| HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(frame->document()->focusedNode()); |
| return QVariant(inputElement->maxLength()); |
| } |
| } |
| return QVariant(InputElement::s_maximumLength); |
| } |
| return QVariant(0); |
| } |
| default: |
| return QVariant(); |
| } |
| } |
| |
| /*! |
| \internal |
| */ |
| void QWebPagePrivate::setInspector(QWebInspector* insp) |
| { |
| if (inspector) |
| inspector->d->setFrontend(0); |
| |
| if (inspectorIsInternalOnly) { |
| QWebInspector* inspToDelete = inspector; |
| inspector = 0; |
| inspectorIsInternalOnly = false; |
| delete inspToDelete; // Delete after to prevent infinite recursion |
| } |
| |
| inspector = insp; |
| |
| // Give inspector frontend web view if previously created |
| if (inspector && inspectorFrontend) |
| inspector->d->setFrontend(inspectorFrontend); |
| } |
| |
| /*! |
| \internal |
| Returns the inspector and creates it if it wasn't created yet. |
| The instance created here will not be available through QWebPage's API. |
| */ |
| QWebInspector* QWebPagePrivate::getOrCreateInspector() |
| { |
| #if ENABLE(INSPECTOR) |
| if (!inspector) { |
| QWebInspector* insp = new QWebInspector; |
| insp->setPage(q); |
| inspectorIsInternalOnly = true; |
| |
| Q_ASSERT(inspector); // Associated through QWebInspector::setPage(q) |
| } |
| #endif |
| return inspector; |
| } |
| |
| /*! \internal */ |
| InspectorController* QWebPagePrivate::inspectorController() |
| { |
| #if ENABLE(INSPECTOR) |
| return page->inspectorController(); |
| #else |
| return 0; |
| #endif |
| } |
| |
| quint16 QWebPagePrivate::inspectorServerPort() |
| { |
| #if ENABLE(INSPECTOR) && !defined(QT_NO_PROPERTIES) |
| if (q && q->property("_q_webInspectorServerPort").isValid()) |
| return q->property("_q_webInspectorServerPort").toInt(); |
| #endif |
| return 0; |
| } |
| |
| static bool hasMouseListener(Element* element) |
| { |
| ASSERT(element); |
| return element->hasEventListeners(eventNames().clickEvent) |
| || element->hasEventListeners(eventNames().mousedownEvent) |
| || element->hasEventListeners(eventNames().mouseupEvent); |
| } |
| |
| static bool isClickableElement(Element* element, RefPtr<NodeList> list) |
| { |
| ASSERT(element); |
| bool isClickable = hasMouseListener(element); |
| if (!isClickable && list) { |
| Element* parent = element->parentElement(); |
| unsigned count = list->length(); |
| for (unsigned i = 0; i < count && parent; i++) { |
| if (list->item(i) != parent) |
| continue; |
| |
| isClickable = hasMouseListener(parent); |
| if (isClickable) |
| break; |
| |
| parent = parent->parentElement(); |
| } |
| } |
| |
| ExceptionCode ec = 0; |
| return isClickable |
| || element->webkitMatchesSelector("a,*:link,*:visited,*[role=button],button,input,select,label", ec) |
| || computedStyle(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer"; |
| } |
| |
| static bool isValidFrameOwner(Element* element) |
| { |
| ASSERT(element); |
| return element->isFrameOwnerElement() && static_cast<HTMLFrameOwnerElement*>(element)->contentFrame(); |
| } |
| |
| static Element* nodeToElement(Node* node) |
| { |
| if (node && node->isElementNode()) |
| return static_cast<Element*>(node); |
| return 0; |
| } |
| |
| QWebPagePrivate::TouchAdjuster::TouchAdjuster(unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding) |
| : m_topPadding(topPadding) |
| , m_rightPadding(rightPadding) |
| , m_bottomPadding(bottomPadding) |
| , m_leftPadding(leftPadding) |
| { |
| } |
| |
| IntPoint QWebPagePrivate::TouchAdjuster::findCandidatePointForTouch(const IntPoint& touchPoint, Document* document) const |
| { |
| if (!document) |
| return IntPoint(); |
| |
| int x = touchPoint.x(); |
| int y = touchPoint.y(); |
| |
| RefPtr<NodeList> intersectedNodes = document->nodesFromRect(x, y, m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding, false); |
| if (!intersectedNodes) |
| return IntPoint(); |
| |
| Element* closestClickableElement = 0; |
| IntRect largestIntersectionRect; |
| FrameView* view = document->frame()->view(); |
| |
| // Touch rect in contents coordinates. |
| IntRect touchRect(HitTestResult::rectForPoint(view->windowToContents(IntPoint(x, y)), m_topPadding, m_rightPadding, m_bottomPadding, m_leftPadding)); |
| |
| // Iterate over the list of nodes hit looking for the one whose bounding area |
| // has largest intersection with the touch area (point + padding). |
| for (unsigned i = 0; i < intersectedNodes->length(); i++) { |
| Node* currentNode = intersectedNodes->item(i); |
| |
| Element* currentElement = nodeToElement(currentNode); |
| if (!currentElement || (!isClickableElement(currentElement, 0) && !isValidFrameOwner(currentElement))) |
| continue; |
| |
| IntRect currentElementBoundingRect = currentElement->getRect(); |
| currentElementBoundingRect.intersect(touchRect); |
| |
| if (currentElementBoundingRect.isEmpty()) |
| continue; |
| |
| int currentIntersectionRectArea = currentElementBoundingRect.width() * currentElementBoundingRect.height(); |
| int largestIntersectionRectArea = largestIntersectionRect.width() * largestIntersectionRect.height(); |
| if (currentIntersectionRectArea > largestIntersectionRectArea) { |
| closestClickableElement = currentElement; |
| largestIntersectionRect = currentElementBoundingRect; |
| } |
| } |
| |
| if (largestIntersectionRect.isEmpty()) |
| return IntPoint(); |
| |
| // Handle the case when user taps a inner frame. It is done in three steps: |
| // 1) Transform the original touch point to the inner document coordinates; |
| // 1) Call nodesFromRect for the inner document in case; |
| // 3) Re-add the inner frame offset (location) before passing the new clicking |
| // position to WebCore. |
| if (closestClickableElement->isFrameOwnerElement()) { |
| // Adjust client coordinates' origin to be top left of inner frame viewport. |
| PassRefPtr<ClientRect> rect = closestClickableElement->getBoundingClientRect(); |
| IntPoint newTouchPoint = touchPoint; |
| IntSize offset = IntSize(rect->left(), rect->top()); |
| newTouchPoint -= offset; |
| |
| HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(closestClickableElement); |
| Document* childDocument = owner->contentFrame()->document(); |
| return findCandidatePointForTouch(newTouchPoint, childDocument); |
| } |
| return view->contentsToWindow(largestIntersectionRect).center(); |
| } |
| |
| /*! |
| \enum QWebPage::FindFlag |
| |
| This enum describes the options available to the findText() function. The options |
| can be OR-ed together from the following list: |
| |
| \value FindBackward Searches backwards instead of forwards. |
| \value FindCaseSensitively By default findText() works case insensitive. Specifying this option |
| changes the behaviour to a case sensitive find operation. |
| \value FindWrapsAroundDocument Makes findText() restart from the beginning of the document if the end |
| was reached and the text was not found. |
| \value HighlightAllOccurrences Highlights all existing occurrences of a specific string. |
| */ |
| |
| /*! |
| \enum QWebPage::LinkDelegationPolicy |
| |
| This enum defines the delegation policies a webpage can have when activating links and emitting |
| the linkClicked() signal. |
| |
| \value DontDelegateLinks No links are delegated. Instead, QWebPage tries to handle them all. |
| \value DelegateExternalLinks When activating links that point to documents not stored on the |
| local filesystem or an equivalent - such as the Qt resource system - then linkClicked() is emitted. |
| \value DelegateAllLinks Whenever a link is activated the linkClicked() signal is emitted. |
| |
| \sa QWebPage::linkDelegationPolicy |
| */ |
| |
| /*! |
| \enum QWebPage::NavigationType |
| |
| This enum describes the types of navigation available when browsing through hyperlinked |
| documents. |
| |
| \value NavigationTypeLinkClicked The user clicked on a link or pressed return on a focused link. |
| \value NavigationTypeFormSubmitted The user activated a submit button for an HTML form. |
| \value NavigationTypeBackOrForward Navigation to a previously shown document in the back or forward history is requested. |
| \value NavigationTypeReload The user activated the reload action. |
| \value NavigationTypeFormResubmitted An HTML form was submitted a second time. |
| \value NavigationTypeOther A navigation to another document using a method not listed above. |
| |
| \sa acceptNavigationRequest() |
| */ |
| |
| /*! |
| \enum QWebPage::WebAction |
| |
| This enum describes the types of action which can be performed on the web page. |
| |
| Actions only have an effect when they are applicable. The availability of |
| actions can be be determined by checking \l{QAction::}{isEnabled()} on the |
| action returned by action(). |
| |
| One method of enabling the text editing, cursor movement, and text selection actions |
| is by setting \l contentEditable to true. |
| |
| \value NoWebAction No action is triggered. |
| \value OpenLink Open the current link. |
| \value OpenLinkInNewWindow Open the current link in a new window. |
| \value OpenFrameInNewWindow Replicate the current frame in a new window. |
| \value DownloadLinkToDisk Download the current link to the disk. |
| \value CopyLinkToClipboard Copy the current link to the clipboard. |
| \value OpenImageInNewWindow Open the highlighted image in a new window. |
| \value DownloadImageToDisk Download the highlighted image to the disk. |
| \value CopyImageToClipboard Copy the highlighted image to the clipboard. |
| \value CopyImageUrlToClipboard Copy the highlighted image's URL to the clipboard. |
| \value Back Navigate back in the history of navigated links. |
| \value Forward Navigate forward in the history of navigated links. |
| \value Stop Stop loading the current page. |
| \value StopScheduledPageRefresh Stop all pending page refresh/redirect requests. |
| \value Reload Reload the current page. |
| \value ReloadAndBypassCache Reload the current page, but do not use any local cache. (Added in Qt 4.6) |
| \value Cut Cut the content currently selected into the clipboard. |
| \value Copy Copy the content currently selected into the clipboard. |
| \value Paste Paste content from the clipboard. |
| \value Undo Undo the last editing action. |
| \value Redo Redo the last editing action. |
| \value MoveToNextChar Move the cursor to the next character. |
| \value MoveToPreviousChar Move the cursor to the previous character. |
| \value MoveToNextWord Move the cursor to the next word. |
| \value MoveToPreviousWord Move the cursor to the previous word. |
| \value MoveToNextLine Move the cursor to the next line. |
| \value MoveToPreviousLine Move the cursor to the previous line. |
| \value MoveToStartOfLine Move the cursor to the start of the line. |
| \value MoveToEndOfLine Move the cursor to the end of the line. |
| \value MoveToStartOfBlock Move the cursor to the start of the block. |
| \value MoveToEndOfBlock Move the cursor to the end of the block. |
| \value MoveToStartOfDocument Move the cursor to the start of the document. |
| \value MoveToEndOfDocument Move the cursor to the end of the document. |
| \value SelectNextChar Select to the next character. |
| \value SelectPreviousChar Select to the previous character. |
| \value SelectNextWord Select to the next word. |
| \value SelectPreviousWord Select to the previous word. |
| \value SelectNextLine Select to the next line. |
| \value SelectPreviousLine Select to the previous line. |
| \value SelectStartOfLine Select to the start of the line. |
| \value SelectEndOfLine Select to the end of the line. |
| \value SelectStartOfBlock Select to the start of the block. |
| \value SelectEndOfBlock Select to the end of the block. |
| \value SelectStartOfDocument Select to the start of the document. |
| \value SelectEndOfDocument Select to the end of the document. |
| \value DeleteStartOfWord Delete to the start of the word. |
| \value DeleteEndOfWord Delete to the end of the word. |
| \value SetTextDirectionDefault Set the text direction to the default direction. |
| \value SetTextDirectionLeftToRight Set the text direction to left-to-right. |
| \value SetTextDirectionRightToLeft Set the text direction to right-to-left. |
| \value ToggleBold Toggle the formatting between bold and normal weight. |
| \value ToggleItalic Toggle the formatting between italic and normal style. |
| \value ToggleUnderline Toggle underlining. |
| \value InspectElement Show the Web Inspector with the currently highlighted HTML element. |
| \value InsertParagraphSeparator Insert a new paragraph. |
| \value InsertLineSeparator Insert a new line. |
| \value SelectAll Selects all content. |
| \value PasteAndMatchStyle Paste content from the clipboard with current style. |
| \value RemoveFormat Removes formatting and style. |
| \value ToggleStrikethrough Toggle the formatting between strikethrough and normal style. |
| \value ToggleSubscript Toggle the formatting between subscript and baseline. |
| \value ToggleSuperscript Toggle the formatting between supercript and baseline. |
| \value InsertUnorderedList Toggles the selection between an ordered list and a normal block. |
| \value InsertOrderedList Toggles the selection between an ordered list and a normal block. |
| \value Indent Increases the indentation of the currently selected format block by one increment. |
| \value Outdent Decreases the indentation of the currently selected format block by one increment. |
| \value AlignCenter Applies center alignment to content. |
| \value AlignJustified Applies full justification to content. |
| \value AlignLeft Applies left justification to content. |
| \value AlignRight Applies right justification to content. |
| |
| |
| \omitvalue WebActionCount |
| |
| */ |
| |
| /*! |
| \enum QWebPage::WebWindowType |
| |
| This enum describes the types of window that can be created by the createWindow() function. |
| |
| \value WebBrowserWindow The window is a regular web browser window. |
| \value WebModalDialog The window acts as modal dialog. |
| */ |
| |
| |
| /*! |
| \class QWebPage::ViewportAttributes |
| \since 4.7 |
| \brief The QWebPage::ViewportAttributes class describes hints that can be applied to a viewport. |
| |
| QWebPage::ViewportAttributes provides a description of a viewport, such as viewport geometry, |
| initial scale factor with limits, plus information about whether a user should be able |
| to scale the contents in the viewport or not, ie. by zooming. |
| |
| ViewportAttributes can be set by a web author using the viewport meta tag extension, documented |
| at \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Reference Library: Using the Viewport Meta Tag}. |
| |
| All values might not be set, as such when dealing with the hints, the developer needs to |
| check whether the values are valid. Negative values denote an invalid qreal value. |
| |
| \inmodule QtWebKit |
| */ |
| |
| /*! |
| Constructs an empty QWebPage::ViewportAttributes. |
| */ |
| QWebPage::ViewportAttributes::ViewportAttributes() |
| : d(0) |
| , m_initialScaleFactor(-1.0) |
| , m_minimumScaleFactor(-1.0) |
| , m_maximumScaleFactor(-1.0) |
| , m_devicePixelRatio(-1.0) |
| , m_isUserScalable(true) |
| , m_isValid(false) |
| { |
| |
| } |
| |
| /*! |
| Constructs a QWebPage::ViewportAttributes which is a copy from \a other . |
| */ |
| QWebPage::ViewportAttributes::ViewportAttributes(const QWebPage::ViewportAttributes& other) |
| : d(other.d) |
| , m_initialScaleFactor(other.m_initialScaleFactor) |
| , m_minimumScaleFactor(other.m_minimumScaleFactor) |
| , m_maximumScaleFactor(other.m_maximumScaleFactor) |
| , m_devicePixelRatio(other.m_devicePixelRatio) |
| , m_isUserScalable(other.m_isUserScalable) |
| , m_isValid(other.m_isValid) |
| , m_size(other.m_size) |
| { |
| |
| } |
| |
| /*! |
| Destroys the QWebPage::ViewportAttributes. |
| */ |
| QWebPage::ViewportAttributes::~ViewportAttributes() |
| { |
| |
| } |
| |
| /*! |
| Assigns the given QWebPage::ViewportAttributes to this viewport hints and returns a |
| reference to this. |
| */ |
| QWebPage::ViewportAttributes& QWebPage::ViewportAttributes::operator=(const QWebPage::ViewportAttributes& other) |
| { |
| if (this != &other) { |
| d = other.d; |
| m_initialScaleFactor = other.m_initialScaleFactor; |
| m_minimumScaleFactor = other.m_minimumScaleFactor; |
| m_maximumScaleFactor = other.m_maximumScaleFactor; |
| m_isUserScalable = other.m_isUserScalable; |
| m_isValid = other.m_isValid; |
| m_size = other.m_size; |
| } |
| |
| return *this; |
| } |
| |
| /*! \fn inline bool QWebPage::ViewportAttributes::isValid() const |
| Returns whether this is a valid ViewportAttributes or not. |
| |
| An invalid ViewportAttributes will have an empty QSize, negative values for scale factors and |
| true for the boolean isUserScalable. |
| */ |
| |
| /*! \fn inline QSize QWebPage::ViewportAttributes::size() const |
| Returns the size of the viewport. |
| */ |
| |
| /*! \fn inline qreal QWebPage::ViewportAttributes::initialScaleFactor() const |
| Returns the initial scale of the viewport as a multiplier. |
| */ |
| |
| /*! \fn inline qreal QWebPage::ViewportAttributes::minimumScaleFactor() const |
| Returns the minimum scale value of the viewport as a multiplier. |
| */ |
| |
| /*! \fn inline qreal QWebPage::ViewportAttributes::maximumScaleFactor() const |
| Returns the maximum scale value of the viewport as a multiplier. |
| */ |
| |
| /*! \fn inline bool QWebPage::ViewportAttributes::isUserScalable() const |
| Determines whether or not the scale can be modified by the user. |
| */ |
| |
| |
| /*! |
| \class QWebPage |
| \since 4.4 |
| \brief The QWebPage class provides an object to view and edit web documents. |
| |
| \inmodule QtWebKit |
| |
| QWebPage holds a main frame responsible for web content, settings, the history |
| of navigated links and actions. This class can be used, together with QWebFrame, |
| to provide functionality like QWebView in a widget-less environment. |
| |
| QWebPage's API is very similar to QWebView, as you are still provided with |
| common functions like action() (known as |
| \l{QWebView::pageAction()}{pageAction}() in QWebView), triggerAction(), |
| findText() and settings(). More QWebView-like functions can be found in the |
| main frame of QWebPage, obtained via the mainFrame() function. For example, |
| the \l{QWebFrame::load()}{load}(), \l{QWebFrame::setUrl()}{setUrl}() and |
| \l{QWebFrame::setHtml()}{setHtml}() functions for QWebPage can be accessed |
| using QWebFrame. |
| |
| The loadStarted() signal is emitted when the page begins to load.The |
| loadProgress() signal, on the other hand, is emitted whenever an element |
| of the web page completes loading, such as an embedded image, a script, |
| etc. Finally, the loadFinished() signal is emitted when the page contents |
| are loaded completely, independent of script execution or page rendering. |
| Its argument, either true or false, indicates whether or not the load |
| operation succeeded. |
| |
| \section1 Using QWebPage in a Widget-less Environment |
| |
| Before you begin painting a QWebPage object, you need to set the size of |
| the viewport by calling setViewportSize(). Then, you invoke the main |
| frame's render function (QWebFrame::render()). An example of this |
| is shown in the code snippet below. |
| |
| Suppose we have a \c Thumbnail class as follows: |
| |
| \snippet webkitsnippets/webpage/main.cpp 0 |
| |
| The \c Thumbnail's constructor takes in a \a url. We connect our QWebPage |
| object's \l{QWebPage::}{loadFinished()} signal to our private slot, |
| \c render(). |
| |
| \snippet webkitsnippets/webpage/main.cpp 1 |
| |
| The \c render() function shows how we can paint a thumbnail using a |
| QWebPage object. |
| |
| \snippet webkitsnippets/webpage/main.cpp 2 |
| |
| We begin by setting the \l{QWebPage::viewportSize()}{viewportSize} and |
| then we instantiate a QImage object, \c image, with the same size as our |
| \l{QWebPage::viewportSize()}{viewportSize}. This image is then sent |
| as a parameter to \c painter. Next, we render the contents of the main |
| frame and its subframes into \c painter. Finally, we save the scaled image. |
| |
| \sa QWebFrame |
| */ |
| |
| /*! |
| Constructs an empty QWebPage with parent \a parent. |
| */ |
| QWebPage::QWebPage(QObject *parent) |
| : QObject(parent) |
| , d(new QWebPagePrivate(this)) |
| { |
| setView(qobject_cast<QWidget*>(parent)); |
| |
| connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int))); |
| #ifndef NDEBUG |
| connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages())); |
| #endif |
| } |
| |
| /*! |
| Destroys the web page. |
| */ |
| QWebPage::~QWebPage() |
| { |
| d->createMainFrame(); |
| FrameLoader *loader = d->mainFrame->d->frame->loader(); |
| if (loader) |
| loader->detachFromParent(); |
| delete d; |
| } |
| |
| /*! |
| Returns the main frame of the page. |
| |
| The main frame provides access to the hierarchy of sub-frames and is also needed if you |
| want to explicitly render a web page into a given painter. |
| |
| \sa currentFrame() |
| */ |
| QWebFrame *QWebPage::mainFrame() const |
| { |
| d->createMainFrame(); |
| return d->mainFrame; |
| } |
| |
| /*! |
| Returns the frame currently active. |
| |
| \sa mainFrame(), frameCreated() |
| */ |
| QWebFrame *QWebPage::currentFrame() const |
| { |
| d->createMainFrame(); |
| WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame(); |
| return qobject_cast<QWebFrame*>(frame->loader()->networkingContext()->originatingObject()); |
| } |
| |
| |
| /*! |
| \since 4.6 |
| |
| Returns the frame at the given point \a pos, or 0 if there is no frame at |
| that position. |
| |
| \sa mainFrame(), currentFrame() |
| */ |
| QWebFrame* QWebPage::frameAt(const QPoint& pos) const |
| { |
| QWebFrame* webFrame = mainFrame(); |
| if (!webFrame->geometry().contains(pos)) |
| return 0; |
| QWebHitTestResult hitTestResult = webFrame->hitTestContent(pos); |
| return hitTestResult.frame(); |
| } |
| |
| /*! |
| Returns a pointer to the view's history of navigated web pages. |
| */ |
| QWebHistory *QWebPage::history() const |
| { |
| d->createMainFrame(); |
| return &d->history; |
| } |
| |
| /*! |
| Sets the \a view that is associated with the web page. |
| |
| \sa view() |
| */ |
| void QWebPage::setView(QWidget* view) |
| { |
| if (this->view() == view) |
| return; |
| |
| d->view = view; |
| setViewportSize(view ? view->size() : QSize(0, 0)); |
| |
| // If we have no client, we install a special client delegating |
| // the responsibility to the QWidget. This is the code path |
| // handling a.o. the "legacy" QWebView. |
| // |
| // If such a special delegate already exist, we substitute the view. |
| |
| if (d->client) { |
| if (d->client->isQWidgetClient()) |
| static_cast<PageClientQWidget*>(d->client.get())->view = view; |
| return; |
| } |
| |
| if (view) |
| d->client = new PageClientQWidget(view, this); |
| } |
| |
| /*! |
| Returns the view widget that is associated with the web page. |
| |
| \sa setView() |
| */ |
| QWidget *QWebPage::view() const |
| { |
| return d->view.data(); |
| } |
| |
| /*! |
| This function is called whenever a JavaScript program tries to print a \a message to the web browser's console. |
| |
| For example in case of evaluation errors the source URL may be provided in \a sourceID as well as the \a lineNumber. |
| |
| The default implementation prints nothing. |
| */ |
| void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID) |
| { |
| Q_UNUSED(sourceID) |
| |
| // Catch plugin logDestroy message for LayoutTests/plugins/open-and-close-window-with-plugin.html |
| // At this point DRT's WebPage has already been destroyed |
| if (QWebPagePrivate::drtRun) { |
| if (message == QLatin1String("PLUGIN: NPP_Destroy")) |
| fprintf (stdout, "CONSOLE MESSAGE: line %d: %s\n", lineNumber, message.toUtf8().constData()); |
| } |
| } |
| |
| /*! |
| This function is called whenever a JavaScript program running inside \a frame calls the alert() function with |
| the message \a msg. |
| |
| The default implementation shows the message, \a msg, with QMessageBox::information. |
| */ |
| void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg) |
| { |
| Q_UNUSED(frame) |
| #ifndef QT_NO_MESSAGEBOX |
| QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; |
| QMessageBox::information(parent, tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Ok); |
| #endif |
| } |
| |
| /*! |
| This function is called whenever a JavaScript program running inside \a frame calls the confirm() function |
| with the message, \a msg. Returns true if the user confirms the message; otherwise returns false. |
| |
| The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons. |
| */ |
| bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg) |
| { |
| Q_UNUSED(frame) |
| #ifdef QT_NO_MESSAGEBOX |
| return true; |
| #else |
| QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; |
| return QMessageBox::Yes == QMessageBox::information(parent, tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QMessageBox::Yes, QMessageBox::No); |
| #endif |
| } |
| |
| /*! |
| This function is called whenever a JavaScript program running inside \a frame tries to prompt the user for input. |
| The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue. |
| |
| If the prompt was cancelled by the user the implementation should return false; otherwise the |
| result should be written to \a result and true should be returned. If the prompt was not cancelled by the |
| user, the implementation should return true and the result string must not be null. |
| |
| The default implementation uses QInputDialog::getText(). |
| */ |
| bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result) |
| { |
| Q_UNUSED(frame) |
| bool ok = false; |
| #ifndef QT_NO_INPUTDIALOG |
| QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; |
| QString x = QInputDialog::getText(parent, tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), Qt::escape(msg), QLineEdit::Normal, defaultValue, &ok); |
| if (ok && result) |
| *result = x; |
| #endif |
| return ok; |
| } |
| |
| /*! |
| \fn bool QWebPage::shouldInterruptJavaScript() |
| \since 4.6 |
| This function is called when a JavaScript program is running for a long period of time. |
| |
| If the user wanted to stop the JavaScript the implementation should return true; otherwise false. |
| |
| The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons. |
| |
| \warning Because of binary compatibility constraints, this function is not virtual. If you want to |
| provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript() |
| slot in your subclass instead. QtWebKit will dynamically detect the slot and call it. |
| */ |
| bool QWebPage::shouldInterruptJavaScript() |
| { |
| #ifdef QT_NO_MESSAGEBOX |
| return false; |
| #else |
| QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; |
| 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); |
| #endif |
| } |
| |
| void QWebPage::setFeaturePermission(QWebFrame* frame, Feature feature, PermissionPolicy policy) |
| { |
| switch (feature) { |
| case Notifications: |
| #if ENABLE(NOTIFICATIONS) |
| if (policy == PermissionGrantedByUser) |
| NotificationPresenterClientQt::notificationPresenter()->allowNotificationForFrame(frame->d->frame); |
| #endif |
| break; |
| case Geolocation: |
| #if ENABLE(GEOLOCATION) |
| GeolocationPermissionClientQt::geolocationPermissionClient()->setPermission(frame, policy); |
| #endif |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| /*! |
| This function is called whenever WebKit wants to create a new window of the given \a type, for |
| example when a JavaScript program requests to open a document in a new window. |
| |
| If the new window can be created, the new window's QWebPage is returned; otherwise a null pointer is returned. |
| |
| If the view associated with the web page is a QWebView object, then the default implementation forwards |
| the request to QWebView's createWindow() function; otherwise it returns a null pointer. |
| |
| If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window. |
| |
| \note In the cases when the window creation is being triggered by JavaScript, apart from |
| reimplementing this method application must also set the JavaScriptCanOpenWindows attribute |
| of QWebSettings to true in order for it to get called. |
| |
| \sa acceptNavigationRequest(), QWebView::createWindow() |
| */ |
| QWebPage *QWebPage::createWindow(WebWindowType type) |
| { |
| QWebView *webView = qobject_cast<QWebView*>(view()); |
| if (webView) { |
| QWebView *newView = webView->createWindow(type); |
| if (newView) |
| return newView->page(); |
| } |
| return 0; |
| } |
| |
| /*! |
| This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is |
| called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues |
| correspond to the HTML object element attributes and child elements to configure the embeddable object. |
| */ |
| QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) |
| { |
| Q_UNUSED(classid) |
| Q_UNUSED(url) |
| Q_UNUSED(paramNames) |
| Q_UNUSED(paramValues) |
| return 0; |
| } |
| |
| static void extractContentTypeFromHash(const HashSet<String>& types, QStringList* list) |
| { |
| if (!list) |
| return; |
| |
| HashSet<String>::const_iterator endIt = types.end(); |
| for (HashSet<String>::const_iterator it = types.begin(); it != endIt; ++it) |
| *list << *it; |
| } |
| |
| static void extractContentTypeFromPluginVector(const Vector<PluginPackage*>& plugins, QStringList* list) |
| { |
| if (!list) |
| return; |
| |
| for (unsigned int i = 0; i < plugins.size(); ++i) { |
| MIMEToDescriptionsMap::const_iterator map_it = plugins[i]->mimeToDescriptions().begin(); |
| MIMEToDescriptionsMap::const_iterator map_end = plugins[i]->mimeToDescriptions().end(); |
| for (; map_it != map_end; ++map_it) |
| *list << map_it->first; |
| } |
| } |
| |
| /*! |
| * Returns the list of all content types supported by QWebPage. |
| */ |
| QStringList QWebPage::supportedContentTypes() const |
| { |
| QStringList mimeTypes; |
| |
| extractContentTypeFromHash(MIMETypeRegistry::getSupportedImageMIMETypes(), &mimeTypes); |
| extractContentTypeFromHash(MIMETypeRegistry::getSupportedNonImageMIMETypes(), &mimeTypes); |
| if (d->page->settings() && d->page->settings()->arePluginsEnabled()) |
| extractContentTypeFromPluginVector(PluginDatabase::installedPlugins()->plugins(), &mimeTypes); |
| |
| return mimeTypes; |
| } |
| |
| /*! |
| * Returns true if QWebPage can handle the given \a mimeType; otherwise, returns false. |
| */ |
| bool QWebPage::supportsContentType(const QString& mimeType) const |
| { |
| const String type = mimeType.toLower(); |
| if (MIMETypeRegistry::isSupportedImageMIMEType(type)) |
| return true; |
| |
| if (MIMETypeRegistry::isSupportedNonImageMIMEType(type)) |
| return true; |
| |
| if (d->page->settings() && d->page->settings()->arePluginsEnabled() |
| && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type)) |
| return true; |
| |
| return false; |
| } |
| |
| static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame) |
| { |
| return WebCore::FrameLoadRequest(frame->document()->securityOrigin(), |
| WebCore::ResourceRequest(url, frame->loader()->outgoingReferrer())); |
| } |
| |
| static void openNewWindow(const QUrl& url, WebCore::Frame* frame) |
| { |
| if (Page* oldPage = frame->page()) { |
| WindowFeatures features; |
| NavigationAction action; |
| FrameLoadRequest request = frameLoadRequest(url, frame); |
| if (Page* newPage = oldPage->chrome()->createWindow(frame, request, features, action)) { |
| newPage->mainFrame()->loader()->loadFrameRequest(request, false, false, 0, 0, SendReferrer); |
| newPage->chrome()->show(); |
| } |
| } |
| } |
| |
| static void collectChildFrames(QWebFrame* frame, QList<QWebFrame*>& list) |
| { |
| list << frame->childFrames(); |
| QListIterator<QWebFrame*> it(frame->childFrames()); |
| while (it.hasNext()) { |
| collectChildFrames(it.next(), list); |
| } |
| } |
| |
| /*! |
| This function can be called to trigger the specified \a action. |
| It is also called by QtWebKit if the user triggers the action, for example |
| through a context menu item. |
| |
| If \a action is a checkable action then \a checked specified whether the action |
| is toggled or not. |
| |
| \sa action() |
| */ |
| void QWebPage::triggerAction(WebAction action, bool) |
| { |
| WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame(); |
| if (!frame) |
| return; |
| WebCore::Editor *editor = frame->editor(); |
| const char *command = 0; |
| |
| switch (action) { |
| case OpenLink: |
| if (QWebFrame *targetFrame = d->hitTestResult.linkTargetFrame()) { |
| WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame; |
| targetFrame->d->frame->loader()->loadFrameRequest(frameLoadRequest(d->hitTestResult.linkUrl(), wcFrame.get()), |
| /*lockHistory*/ false, /*lockBackForwardList*/ false, /*event*/ 0, |
| /*FormState*/ 0, SendReferrer); |
| break; |
| } |
| // fall through |
| case OpenLinkInNewWindow: |
| openNewWindow(d->hitTestResult.linkUrl(), frame); |
| break; |
| case OpenFrameInNewWindow: { |
| KURL url = frame->loader()->documentLoader()->unreachableURL(); |
| if (url.isEmpty()) |
| url = frame->loader()->documentLoader()->url(); |
| openNewWindow(url, frame); |
| break; |
| } |
| case CopyLinkToClipboard: { |
| #if defined(Q_WS_X11) |
| bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode(); |
| Pasteboard::generalPasteboard()->setSelectionMode(true); |
| editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText()); |
| Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode); |
| #endif |
| editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText()); |
| break; |
| } |
| case OpenImageInNewWindow: |
| openNewWindow(d->hitTestResult.imageUrl(), frame); |
| break; |
| case DownloadImageToDisk: |
| frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.imageUrl(), frame->loader()->outgoingReferrer())); |
| break; |
| case DownloadLinkToDisk: |
| frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->hitTestResult.linkUrl(), frame->loader()->outgoingReferrer())); |
| break; |
| #ifndef QT_NO_CLIPBOARD |
| case CopyImageToClipboard: |
| QApplication::clipboard()->setPixmap(d->hitTestResult.pixmap()); |
| break; |
| case CopyImageUrlToClipboard: |
| QApplication::clipboard()->setText(d->hitTestResult.imageUrl().toString()); |
| break; |
| #endif |
| case Back: |
| d->page->goBack(); |
| break; |
| case Forward: |
| d->page->goForward(); |
| break; |
| case Stop: |
| mainFrame()->d->frame->loader()->stopForUserCancel(); |
| d->updateNavigationActions(); |
| break; |
| case Reload: |
| mainFrame()->d->frame->loader()->reload(/*endtoendreload*/false); |
| break; |
| case ReloadAndBypassCache: |
| mainFrame()->d->frame->loader()->reload(/*endtoendreload*/true); |
| break; |
| case SetTextDirectionDefault: |
| editor->setBaseWritingDirection(NaturalWritingDirection); |
| break; |
| case SetTextDirectionLeftToRight: |
| editor->setBaseWritingDirection(LeftToRightWritingDirection); |
| break; |
| case SetTextDirectionRightToLeft: |
| editor->setBaseWritingDirection(RightToLeftWritingDirection); |
| break; |
| case InspectElement: { |
| #if ENABLE(INSPECTOR) |
| if (!d->hitTestResult.isNull()) { |
| d->getOrCreateInspector(); // Make sure the inspector is created |
| d->inspector->show(); // The inspector is expected to be shown on inspection |
| d->page->inspectorController()->inspect(d->hitTestResult.d->innerNonSharedNode.get()); |
| } |
| #endif |
| break; |
| } |
| case StopScheduledPageRefresh: { |
| QWebFrame* topFrame = mainFrame(); |
| topFrame->d->frame->navigationScheduler()->cancel(); |
| QList<QWebFrame*> childFrames; |
| collectChildFrames(topFrame, childFrames); |
| QListIterator<QWebFrame*> it(childFrames); |
| while (it.hasNext()) |
| it.next()->d->frame->navigationScheduler()->cancel(); |
| break; |
| } |
| default: |
| command = QWebPagePrivate::editorCommandForWebActions(action); |
| break; |
| } |
| |
| if (command) |
| editor->command(command).execute(); |
| } |
| |
| QSize QWebPage::viewportSize() const |
| { |
| if (d->mainFrame && d->mainFrame->d->frame->view()) |
| return d->mainFrame->d->frame->view()->frameRect().size(); |
| |
| return d->viewportSize; |
| } |
| |
| /*! |
| \property QWebPage::viewportSize |
| \brief the size of the viewport |
| |
| The size affects for example the visibility of scrollbars |
| if the document is larger than the viewport. |
| |
| By default, for a newly-created Web page, this property contains a size with |
| zero width and height. |
| |
| \sa QWebFrame::render(), preferredContentsSize |
| */ |
| void QWebPage::setViewportSize(const QSize &size) const |
| { |
| d->viewportSize = size; |
| |
| QWebFrame *frame = mainFrame(); |
| if (frame->d->frame && frame->d->frame->view()) { |
| WebCore::FrameView* view = frame->d->frame->view(); |
| view->resize(size); |
| view->adjustViewSize(); |
| } |
| } |
| |
| static int getintenv(const char* variable) |
| { |
| bool ok; |
| int value = qgetenv(variable).toInt(&ok); |
| return (ok) ? value : -1; |
| } |
| |
| static QSize queryDeviceSizeForScreenContainingWidget(const QWidget* widget) |
| { |
| QDesktopWidget* desktop = QApplication::desktop(); |
| if (!desktop) |
| return QSize(); |
| |
| QSize size; |
| |
| if (widget) { |
| // Returns the available geometry of the screen which contains widget. |
| // NOTE: this must be the the full screen size including any fixed status areas etc. |
| size = desktop->availableGeometry(widget).size(); |
| } else |
| size = desktop->availableGeometry().size(); |
| |
| // This must be in portrait mode, adjust if not. |
| if (size.width() > size.height()) { |
| int width = size.width(); |
| size.setWidth(size.height()); |
| size.setHeight(width); |
| } |
| |
| return size; |
| } |
| |
| /*! |
| Computes the optimal viewport configuration given the \a availableSize, when |
| user interface components are disregarded. |
| |
| The configuration is also dependent on the device screen size which is obtained |
| automatically. For testing purposes the size can be overridden by setting two |
| environment variables QTWEBKIT_DEVICE_WIDTH and QTWEBKIT_DEVICE_HEIGHT, which |
| both needs to be set. |
| |
| The ViewportAttributes includes a pixel density ratio, which will also be exposed to |
| the web author though the -webkit-pixel-ratio media feature. This is the ratio |
| between 1 density-independent pixel (DPI) and physical pixels. |
| |
| A density-independent pixel is equivalent to one physical pixel on a 160 DPI screen, |
| so on our platform assumes that as the baseline density. |
| |
| The conversion of DIP units to screen pixels is quite simple: |
| |
| pixels = DIPs * (density / 160). |
| |
| Thus, on a 240 DPI screen, 1 DIPs would equal 1.5 physical pixels. |
| |
| An invalid instance will be returned in the case an empty size is passed to the |
| method. |
| |
| \note The density is automatically obtained from the DPI of the screen where the page |
| is being shown, but as many X11 servers are reporting wrong DPI, it is possible to |
| override it using QX11Info::setAppDpiY(). |
| */ |
| |
| QWebPage::ViewportAttributes QWebPage::viewportAttributesForSize(const QSize& availableSize) const |
| { |
| static int desktopWidth = 980; |
| |
| ViewportAttributes result; |
| |
| if (availableSize.isEmpty()) |
| return result; // Returns an invalid instance. |
| |
| int deviceWidth = getintenv("QTWEBKIT_DEVICE_WIDTH"); |
| int deviceHeight = getintenv("QTWEBKIT_DEVICE_HEIGHT"); |
| |
| // Both environment variables need to be set - or they will be ignored. |
| if (deviceWidth < 0 && deviceHeight < 0) { |
| QSize size = queryDeviceSizeForScreenContainingWidget((d->client) ? d->client->ownerWidget() : 0); |
| deviceWidth = size.width(); |
| deviceHeight = size.height(); |
| } |
| |
| WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(d->viewportArguments(), desktopWidth, deviceWidth, deviceHeight, qt_defaultDpi(), availableSize); |
| |
| result.m_isValid = true; |
| result.m_size = conf.layoutSize; |
| result.m_initialScaleFactor = conf.initialScale; |
| result.m_minimumScaleFactor = conf.minimumScale; |
| result.m_maximumScaleFactor = conf.maximumScale; |
| result.m_devicePixelRatio = conf.devicePixelRatio; |
| result.m_isUserScalable = static_cast<bool>(conf.userScalable); |
| |
| d->pixelRatio = conf.devicePixelRatio; |
| |
| return result; |
| } |
| |
| QSize QWebPage::preferredContentsSize() const |
| { |
| QWebFrame* frame = d->mainFrame; |
| if (frame) { |
| WebCore::FrameView* view = frame->d->frame->view(); |
| if (view && view->useFixedLayout()) |
| return d->mainFrame->d->frame->view()->fixedLayoutSize(); |
| } |
| |
| return d->fixedLayoutSize; |
| } |
| |
| /*! |
| \property QWebPage::preferredContentsSize |
| \since 4.6 |
| \brief a custom size used for laying out the page contents. |
| |
| By default all pages are laid out using the viewport of the page as the base. |
| |
| As pages mostly are designed for desktop usage, they often do not layout properly |
| on small devices as the contents require a certain view width. For this reason |
| it is common to use a different layout size and then scale the contents to fit |
| within the actual view. |
| |
| If this property is set to a valid size, this size is used for all layout needs |
| instead of the size of the viewport. |
| |
| Setting an invalid size, makes the page fall back to using the viewport size for layout. |
| |
| \sa viewportSize |
| */ |
| void QWebPage::setPreferredContentsSize(const QSize& size) const |
| { |
| // FIXME: Rename this method to setCustomLayoutSize |
| |
| d->fixedLayoutSize = size; |
| |
| QWebFrame* frame = mainFrame(); |
| if (!frame->d->frame || !frame->d->frame->view()) |
| return; |
| |
| WebCore::FrameView* view = frame->d->frame->view(); |
| |
| if (size.isValid()) { |
| view->setUseFixedLayout(true); |
| view->setFixedLayoutSize(size); |
| } else if (view->useFixedLayout()) |
| view->setUseFixedLayout(false); |
| |
| view->layout(); |
| } |
| |
| /* |
| This function is to be called after any (animated) scroll/pan has ended, in the case the application handles the |
| scrolling/panning of the web contents. This is commonly used in combination with tiling where is it common for |
| the application to pan the actual view, which then resizes itself to the size of the contents. |
| |
| \note Calling this function makes WebKit stop trying to calculate the visibleContentRect. To turn that on |
| again, call this method with an empty rect. |
| |
| \sa QGraphicsWebView::resizesToContents, QWebSettings::TiledBackingStoreEnabled |
| */ |
| void QWebPage::setActualVisibleContentRect(const QRect& rect) const |
| { |
| QWebFrame* frame = mainFrame(); |
| if (!frame->d->frame || !frame->d->frame->view()) |
| return; |
| |
| WebCore::FrameView* view = frame->d->frame->view(); |
| view->setActualVisibleContentRect(rect); |
| } |
| |
| /*! |
| \fn bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) |
| |
| This function is called whenever WebKit requests to navigate \a frame to the resource specified by \a request by means of |
| the specified navigation type \a type. |
| |
| If \a frame is a null pointer then navigation to a new window is requested. If the request is |
| accepted createWindow() will be called. |
| |
| The default implementation interprets the page's linkDelegationPolicy and emits linkClicked accordingly or returns true |
| to let QWebPage handle the navigation itself. |
| |
| \sa createWindow() |
| */ |
| bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) |
| { |
| Q_UNUSED(frame) |
| if (type == NavigationTypeLinkClicked) { |
| switch (d->linkPolicy) { |
| case DontDelegateLinks: |
| return true; |
| |
| case DelegateExternalLinks: |
| if (WebCore::SchemeRegistry::shouldTreatURLSchemeAsLocal(request.url().scheme())) |
| return true; |
| emit linkClicked(request.url()); |
| return false; |
| |
| case DelegateAllLinks: |
| emit linkClicked(request.url()); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /*! |
| \property QWebPage::hasSelection |
| \brief whether this page contains selected content or not. |
| |
| \sa selectionChanged() |
| */ |
| bool QWebPage::hasSelection() const |
| { |
| d->createMainFrame(); |
| WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame(); |
| if (frame) |
| return (frame->selection()->selection().selectionType() != VisibleSelection::NoSelection); |
| return false; |
| } |
| |
| /*! |
| \property QWebPage::selectedText |
| \brief the text currently selected |
| |
| By default, this property contains an empty string. |
| |
| \sa selectionChanged(), selectedHtml() |
| */ |
| QString QWebPage::selectedText() const |
| { |
| d->createMainFrame(); |
| WebCore::Frame* frame = d->page->focusController()->focusedOrMainFrame(); |
| if (frame->selection()->selection().selectionType() == VisibleSelection::NoSelection) |
| return QString(); |
| return frame->editor()->selectedText(); |
| } |
| |
| /*! |
| \since 4.8 |
| \property QWebPage::selectedHtml |
| \brief the HTML currently selected |
| |
| By default, this property contains an empty string. |
| |
| \sa selectionChanged(), selectedText() |
| */ |
| QString QWebPage::selectedHtml() const |
| { |
| d->createMainFrame(); |
| return d->page->focusController()->focusedOrMainFrame()->editor()->selectedRange()->toHTML(); |
| } |
| |
| #ifndef QT_NO_ACTION |
| /*! |
| Returns a QAction for the specified WebAction \a action. |
| |
| The action is owned by the QWebPage but you can customize the look by |
| changing its properties. |
| |
| QWebPage also takes care of implementing the action, so that upon |
| triggering the corresponding action is performed on the page. |
| |
| \sa triggerAction() |
| */ |
| QAction *QWebPage::action(WebAction action) const |
| { |
| if (action == QWebPage::NoWebAction) return 0; |
| if (d->actions[action]) |
| return d->actions[action]; |
| |
| QString text; |
| QIcon icon; |
| QStyle *style = d->client ? d->client->style() : qApp->style(); |
| bool checkable = false; |
| |
| switch (action) { |
| case OpenLink: |
| text = contextMenuItemTagOpenLink(); |
| break; |
| case OpenLinkInNewWindow: |
| text = contextMenuItemTagOpenLinkInNewWindow(); |
| break; |
| case OpenFrameInNewWindow: |
| text = contextMenuItemTagOpenFrameInNewWindow(); |
| break; |
| |
| case DownloadLinkToDisk: |
| text = contextMenuItemTagDownloadLinkToDisk(); |
| break; |
| case CopyLinkToClipboard: |
| text = contextMenuItemTagCopyLinkToClipboard(); |
| break; |
| |
| case OpenImageInNewWindow: |
| text = contextMenuItemTagOpenImageInNewWindow(); |
| break; |
| case DownloadImageToDisk: |
| text = contextMenuItemTagDownloadImageToDisk(); |
| break; |
| case CopyImageToClipboard: |
| text = contextMenuItemTagCopyImageToClipboard(); |
| break; |
| case CopyImageUrlToClipboard: |
| text = contextMenuItemTagCopyImageUrlToClipboard(); |
| break; |
| |
| case Back: |
| text = contextMenuItemTagGoBack(); |
| icon = style->standardIcon(QStyle::SP_ArrowBack); |
| break; |
| case Forward: |
| text = contextMenuItemTagGoForward(); |
| icon = style->standardIcon(QStyle::SP_ArrowForward); |
| break; |
| case Stop: |
| text = contextMenuItemTagStop(); |
| icon = style->standardIcon(QStyle::SP_BrowserStop); |
| break; |
| case Reload: |
| text = contextMenuItemTagReload(); |
| icon = style->standardIcon(QStyle::SP_BrowserReload); |
| break; |
| |
| case Cut: |
| text = contextMenuItemTagCut(); |
| break; |
| case Copy: |
| text = contextMenuItemTagCopy(); |
| break; |
| case Paste: |
| text = contextMenuItemTagPaste(); |
| break; |
| case SelectAll: |
| text = contextMenuItemTagSelectAll(); |
| break; |
| #ifndef QT_NO_UNDOSTACK |
| case Undo: { |
| QAction *a = undoStack()->createUndoAction(d->q); |
| d->actions[action] = a; |
| return a; |
| } |
| case Redo: { |
| QAction *a = undoStack()->createRedoAction(d->q); |
| d->actions[action] = a; |
| return a; |
| } |
| #endif // QT_NO_UNDOSTACK |
| case MoveToNextChar: |
| text = tr("Move the cursor to the next character"); |
| break; |
| case MoveToPreviousChar: |
| text = tr("Move the cursor to the previous character"); |
| break; |
| case MoveToNextWord: |
| text = tr("Move the cursor to the next word"); |
| break; |
| case MoveToPreviousWord: |
| text = tr("Move the cursor to the previous word"); |
| break; |
| case MoveToNextLine: |
| text = tr("Move the cursor to the next line"); |
| break; |
| case MoveToPreviousLine: |
| text = tr("Move the cursor to the previous line"); |
| break; |
| case MoveToStartOfLine: |
| text = tr("Move the cursor to the start of the line"); |
| break; |
| case MoveToEndOfLine: |
| text = tr("Move the cursor to the end of the line"); |
| break; |
| case MoveToStartOfBlock: |
| text = tr("Move the cursor to the start of the block"); |
| break; |
| case MoveToEndOfBlock: |
| text = tr("Move the cursor to the end of the block"); |
| break; |
| case MoveToStartOfDocument: |
| text = tr("Move the cursor to the start of the document"); |
| break; |
| case MoveToEndOfDocument: |
| text = tr("Move the cursor to the end of the document"); |
| break; |
| case SelectNextChar: |
| text = tr("Select to the next character"); |
| break; |
| case SelectPreviousChar: |
| text = tr("Select to the previous character"); |
| break; |
| case SelectNextWord: |
| text = tr("Select to the next word"); |
| break; |
| case SelectPreviousWord: |
| text = tr("Select to the previous word"); |
| break; |
| case SelectNextLine: |
| text = tr("Select to the next line"); |
| break; |
| case SelectPreviousLine: |
| text = tr("Select to the previous line"); |
| break; |
| case SelectStartOfLine: |
| text = tr("Select to the start of the line"); |
| break; |
| case SelectEndOfLine: |
| text = tr("Select to the end of the line"); |
| break; |
| case SelectStartOfBlock: |
| text = tr("Select to the start of the block"); |
| break; |
| case SelectEndOfBlock: |
| text = tr("Select to the end of the block"); |
| break; |
| case SelectStartOfDocument: |
| text = tr("Select to the start of the document"); |
| break; |
| case SelectEndOfDocument: |
| text = tr("Select to the end of the document"); |
| break; |
| case DeleteStartOfWord: |
| text = tr("Delete to the start of the word"); |
| break; |
| case DeleteEndOfWord: |
| text = tr("Delete to the end of the word"); |
| break; |
| |
| case SetTextDirectionDefault: |
| text = contextMenuItemTagDefaultDirection(); |
| break; |
| case SetTextDirectionLeftToRight: |
| text = contextMenuItemTagLeftToRight(); |
| checkable = true; |
| break; |
| case SetTextDirectionRightToLeft: |
| text = contextMenuItemTagRightToLeft(); |
| checkable = true; |
| break; |
| |
| case ToggleBold: |
| text = contextMenuItemTagBold(); |
| checkable = true; |
| break; |
| case ToggleItalic: |
| text = contextMenuItemTagItalic(); |
| checkable = true; |
| break; |
| case ToggleUnderline: |
| text = contextMenuItemTagUnderline(); |
| checkable = true; |
| break; |
| |
| case InspectElement: |
| text = contextMenuItemTagInspectElement(); |
| break; |
| |
| case InsertParagraphSeparator: |
| text = tr("Insert a new paragraph"); |
| break; |
| case InsertLineSeparator: |
| text = tr("Insert a new line"); |
| break; |
| |
| case PasteAndMatchStyle: |
| text = tr("Paste and Match Style"); |
| break; |
| case RemoveFormat: |
| text = tr("Remove formatting"); |
| break; |
| |
| case ToggleStrikethrough: |
| text = tr("Strikethrough"); |
| checkable = true; |
| break; |
| case ToggleSubscript: |
| text = tr("Subscript"); |
| checkable = true; |
| break; |
| case ToggleSuperscript: |
| text = tr("Superscript"); |
| checkable = true; |
| break; |
| case InsertUnorderedList: |
| text = tr("Insert Bulleted List"); |
| checkable = true; |
| break; |
| case InsertOrderedList: |
| text = tr("Insert Numbered List"); |
| checkable = true; |
| break; |
| case Indent: |
| text = tr("Indent"); |
| break; |
| case Outdent: |
| text = tr("Outdent"); |
| break; |
| case AlignCenter: |
| text = tr("Center"); |
| break; |
| case AlignJustified: |
| text = tr("Justify"); |
| break; |
| case AlignLeft: |
| text = tr("Align Left"); |
| break; |
| case AlignRight: |
| text = tr("Align Right"); |
| break; |
| |
| case NoWebAction: |
| return 0; |
| } |
| |
| if (text.isEmpty()) |
| return 0; |
| |
| QAction *a = new QAction(d->q); |
| a->setText(text); |
| a->setData(action); |
| a->setCheckable(checkable); |
| a->setIcon(icon); |
| |
| connect(a, SIGNAL(triggered(bool)), |
| this, SLOT(_q_webActionTriggered(bool))); |
| |
| d->actions[action] = a; |
| d->updateAction(action); |
| return a; |
| } |
| #endif // QT_NO_ACTION |
| |
| /*! |
| \property QWebPage::modified |
| \brief whether the page contains unsubmitted form data, or the contents have been changed. |
| |
| By default, this property is false. |
| |
| \sa contentsChanged(), contentEditable, undoStack() |
| */ |
| bool QWebPage::isModified() const |
| { |
| #ifdef QT_NO_UNDOSTACK |
| return false; |
| #else |
| if (!d->undoStack) |
| return false; |
| return d->undoStack->canUndo(); |
| #endif // QT_NO_UNDOSTACK |
| } |
| |
| #ifndef QT_NO_UNDOSTACK |
| /*! |
| Returns a pointer to the undo stack used for editable content. |
| |
| \sa modified |
| */ |
| QUndoStack *QWebPage::undoStack() const |
| { |
| if (!d->undoStack) |
| d->undoStack = new QUndoStack(const_cast<QWebPage *>(this)); |
| |
| return d->undoStack; |
| } |
| #endif // QT_NO_UNDOSTACK |
| |
| /*! \reimp |
| */ |
| bool QWebPage::event(QEvent *ev) |
| { |
| switch (ev->type()) { |
| case QEvent::Timer: |
| d->timerEvent(static_cast<QTimerEvent*>(ev)); |
| break; |
| case QEvent::MouseMove: |
| d->mouseMoveEvent(static_cast<QMouseEvent*>(ev)); |
| break; |
| case QEvent::MouseButtonPress: |
| d->mousePressEvent(static_cast<QMouseEvent*>(ev)); |
| break; |
| case QEvent::MouseButtonDblClick: |
| d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev)); |
| break; |
| case QEvent::MouseButtonRelease: |
| d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev)); |
| break; |
| #if !defined(QT_NO_GRAPHICSVIEW) |
| case QEvent::GraphicsSceneMouseMove: |
| d->mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(ev)); |
| break; |
| case QEvent::GraphicsSceneMousePress: |
| d->mousePressEvent(static_cast<QGraphicsSceneMouseEvent*>(ev)); |
| break; |
| case QEvent::GraphicsSceneMouseDoubleClick: |
| d->mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent*>(ev)); |
| break; |
| case QEvent::GraphicsSceneMouseRelease: |
| d->mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent*>(ev)); |
| break; |
| #endif |
| #ifndef QT_NO_CONTEXTMENU |
| case QEvent::ContextMenu: |
| d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)->globalPos()); |
| break; |
| #if !defined(QT_NO_GRAPHICSVIEW) |
| case QEvent::GraphicsSceneContextMenu: |
| d->contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(ev)->screenPos()); |
| break; |
| #endif |
| #endif |
| #ifndef QT_NO_WHEELEVENT |
| case QEvent::Wheel: |
| d->wheelEvent(static_cast<QWheelEvent*>(ev)); |
| break; |
| #if !defined(QT_NO_GRAPHICSVIEW) |
| case QEvent::GraphicsSceneWheel: |
| d->wheelEvent(static_cast<QGraphicsSceneWheelEvent*>(ev)); |
| break; |
| #endif |
| #endif |
| case QEvent::KeyPress: |
| d->keyPressEvent(static_cast<QKeyEvent*>(ev)); |
| break; |
| case QEvent::KeyRelease: |
| d->keyReleaseEvent(static_cast<QKeyEvent*>(ev)); |
| break; |
| case QEvent::FocusIn: |
| d->focusInEvent(static_cast<QFocusEvent*>(ev)); |
| break; |
| case QEvent::FocusOut: |
| d->focusOutEvent(static_cast<QFocusEvent*>(ev)); |
| break; |
| #ifndef QT_NO_DRAGANDDROP |
| case QEvent::DragEnter: |
| d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev)); |
| break; |
| case QEvent::DragLeave: |
| d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev)); |
| break; |
| case QEvent::DragMove: |
| d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev)); |
| break; |
| case QEvent::Drop: |
| d->dropEvent(static_cast<QDropEvent*>(ev)); |
| break; |
| #if !defined(QT_NO_GRAPHICSVIEW) |
| case QEvent::GraphicsSceneDragEnter: |
| d->dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev)); |
| break; |
| case QEvent::GraphicsSceneDragMove: |
| d->dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev)); |
| break; |
| case QEvent::GraphicsSceneDragLeave: |
| d->dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev)); |
| break; |
| case QEvent::GraphicsSceneDrop: |
| d->dropEvent(static_cast<QGraphicsSceneDragDropEvent*>(ev)); |
| break; |
| #endif |
| |
| #endif |
| case QEvent::InputMethod: |
| d->inputMethodEvent(static_cast<QInputMethodEvent*>(ev)); |
| break; |
| case QEvent::ShortcutOverride: |
| d->shortcutOverrideEvent(static_cast<QKeyEvent*>(ev)); |
| break; |
| case QEvent::Leave: |
| d->leaveEvent(ev); |
| break; |
| case QEvent::TouchBegin: |
| case QEvent::TouchUpdate: |
| case QEvent::TouchEnd: |
| // Return whether the default action was cancelled in the JS event handler |
| return d->touchEvent(static_cast<QTouchEvent*>(ev)); |
| #ifndef QT_NO_PROPERTIES |
| case QEvent::DynamicPropertyChange: |
| d->dynamicPropertyChangeEvent(static_cast<QDynamicPropertyChangeEvent*>(ev)); |
| break; |
| #endif |
| default: |
| return QObject::event(ev); |
| } |
| |
| return true; |
| } |
| |
| /*! |
| Similar to QWidget::focusNextPrevChild() it focuses the next focusable web element |
| if \a next is true; otherwise the previous element is focused. |
| |
| Returns true if it can find a new focusable element, or false if it can't. |
| */ |
| bool QWebPage::focusNextPrevChild(bool next) |
| { |
| QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier)); |
| d->keyPressEvent(&ev); |
| bool hasFocusedNode = false; |
| Frame *frame = d->page->focusController()->focusedFrame(); |
| if (frame) { |
| Document *document = frame->document(); |
| hasFocusedNode = document && document->focusedNode(); |
| } |
| //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode; |
| return hasFocusedNode; |
| } |
| |
| /*! |
| \property QWebPage::contentEditable |
| \brief whether the content in this QWebPage is editable or not |
| \since 4.5 |
| |
| If this property is enabled the contents of the page can be edited by the user through a visible |
| cursor. If disabled (the default) only HTML elements in the web page with their |
| \c{contenteditable} attribute set are editable. |
| |
| \sa modified, contentsChanged(), WebAction |
| */ |
| void QWebPage::setContentEditable(bool editable) |
| { |
| if (isContentEditable() != editable) { |
| d->page->setEditable(editable); |
| d->page->setTabKeyCyclesThroughElements(!editable); |
| if (d->mainFrame) { |
| WebCore::Frame* frame = d->mainFrame->d->frame; |
| if (editable) { |
| frame->editor()->applyEditingStyleToBodyElement(); |
| // FIXME: mac port calls this if there is no selectedDOMRange |
| //frame->setSelectionFromNone(); |
| } |
| } |
| |
| d->updateEditorActions(); |
| } |
| } |
| |
| bool QWebPage::isContentEditable() const |
| { |
| return d->page->isEditable(); |
| } |
| |
| /*! |
| \property QWebPage::forwardUnsupportedContent |
| \brief whether QWebPage should forward unsupported content |
| |
| If enabled, the unsupportedContent() signal is emitted with a network reply that |
| can be used to read the content. |
| |
| If disabled, the download of such content is aborted immediately. |
| |
| By default unsupported content is not forwarded. |
| */ |
| |
| void QWebPage::setForwardUnsupportedContent(bool forward) |
| { |
| d->forwardUnsupportedContent = forward; |
| } |
| |
| bool QWebPage::forwardUnsupportedContent() const |
| { |
| return d->forwardUnsupportedContent; |
| } |
| |
| /*! |
| \property QWebPage::linkDelegationPolicy |
| \brief how QWebPage should delegate the handling of links through the |
| linkClicked() signal |
| |
| The default is to delegate no links. |
| */ |
| |
| void QWebPage::setLinkDelegationPolicy(LinkDelegationPolicy policy) |
| { |
| d->linkPolicy = policy; |
| } |
| |
| QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const |
| { |
| return d->linkPolicy; |
| } |
| |
| #ifndef QT_NO_CONTEXTMENU |
| /*! |
| Filters the context menu event, \a event, through handlers for scrollbars and |
| custom event handlers in the web page. Returns true if the event was handled; |
| otherwise false. |
| |
| A web page may swallow a context menu event through a custom event handler, allowing for context |
| menus to be implemented in HTML/JavaScript. This is used by \l{http://maps.google.com/}{Google |
| Maps}, for example. |
| */ |
| bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event) |
| { |
| d->page->contextMenuController()->clearContextMenu(); |
| |
| if (QWebFrame* webFrame = frameAt(event->pos())) { |
| Frame* frame = QWebFramePrivate::core(webFrame); |
| if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).pos())) |
| return scrollbar->contextMenu(PlatformMouseEvent(event, 1)); |
| } |
| |
| WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame(); |
| focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1)); |
| ContextMenu *menu = d->page->contextMenuController()->contextMenu(); |
| // If the website defines its own handler then sendContextMenuEvent takes care of |
| // calling/showing it and the context menu pointer will be zero. This is the case |
| // on maps.google.com for example. |
| |
| return !menu; |
| } |
| #endif // QT_NO_CONTEXTMENU |
| |
| /*! |
| Updates the page's actions depending on the position \a pos. For example if \a pos is over an image |
| element the CopyImageToClipboard action is enabled. |
| */ |
| void QWebPage::updatePositionDependentActions(const QPoint &pos) |
| { |
| #ifndef QT_NO_ACTION |
| // First we disable all actions, but keep track of which ones were originally enabled. |
| QBitArray originallyEnabledWebActions(QWebPage::WebActionCount); |
| for (int i = ContextMenuItemTagNoAction; i < ContextMenuItemBaseApplicationTag; ++i) { |
| QWebPage::WebAction action = webActionForContextMenuAction(WebCore::ContextMenuAction(i)); |
| if (QAction *a = this->action(action)) { |
| originallyEnabledWebActions.setBit(action, a->isEnabled()); |
| a->setEnabled(false); |
| } |
| } |
| #endif // QT_NO_ACTION |
| |
| d->createMainFrame(); |
| WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame(); |
| HitTestResult result = focusedFrame->eventHandler()->hitTestResultAtPoint(focusedFrame->view()->windowToContents(pos), /*allowShadowContent*/ false); |
| |
| if (result.scrollbar()) |
| d->hitTestResult = QWebHitTestResult(); |
| else |
| d->hitTestResult = QWebHitTestResult(new QWebHitTestResultPrivate(result)); |
| |
| d->page->contextMenuController()->setHitTestResult(result); |
| d->page->contextMenuController()->populate(); |
| |
| #if ENABLE(INSPECTOR) |
| if (d->page->inspectorController()->enabled()) |
| d->page->contextMenuController()->addInspectElementItem(); |
| #endif |
| |
| QBitArray visitedWebActions(QWebPage::WebActionCount); |
| |
| #ifndef QT_NO_CONTEXTMENU |
| delete d->currentContextMenu; |
| |
| // Then we let createContextMenu() enable the actions that are put into the menu |
| d->currentContextMenu = d->createContextMenu(d->page->contextMenuController()->contextMenu(), d->page->contextMenuController()->contextMenu()->platformDescription(), &visitedWebActions); |
| #endif // QT_NO_CONTEXTMENU |
| |
| #ifndef QT_NO_ACTION |
| // Finally, we restore the original enablement for the actions that were not put into the menu. |
| originallyEnabledWebActions &= ~visitedWebActions; // Mask out visited actions (they're part of the menu) |
| for (int i = 0; i < QWebPage::WebActionCount; ++i) { |
| if (originallyEnabledWebActions.at(i)) { |
| if (QAction *a = this->action(QWebPage::WebAction(i))) |
| a->setEnabled(true); |
| } |
| } |
| #endif // QT_NO_ACTION |
| |
| // This whole process ensures that any actions put into to the context menu has the right |
| // enablement, while also keeping the correct enablement for actions that were left out of |
| // the menu. |
| |
| } |
| |
| |
| |
| /*! |
| \enum QWebPage::Extension |
| |
| This enum describes the types of extensions that the page can support. Before using these extensions, you |
| should verify that the extension is supported by calling supportsExtension(). |
| |
| \value ChooseMultipleFilesExtension Whether the web page supports multiple file selection. |
| This extension is invoked when the web content requests one or more file names, for example |
| as a result of the user clicking on a "file upload" button in a HTML form where multiple |
| file selection is allowed. |
| |
| \value ErrorPageExtension Whether the web page can provide an error page when loading fails. |
| (introduced in Qt 4.6) |
| |
| \sa ChooseMultipleFilesExtensionOption, ChooseMultipleFilesExtensionReturn, ErrorPageExtensionOption, ErrorPageExtensionReturn |
| */ |
| |
| /*! |
| \enum QWebPage::ErrorDomain |
| \since 4.6 |
| |
| This enum describes the domain of an ErrorPageExtensionOption object (i.e. the layer in which the error occurred). |
| |
| \value QtNetwork The error occurred in the QtNetwork layer; the error code is of type QNetworkReply::NetworkError. |
| \value Http The error occurred in the HTTP layer; the error code is a HTTP status code (see QNetworkRequest::HttpStatusCodeAttribute). |
| \value WebKit The error is an internal WebKit error. |
| */ |
| |
| /*! |
| \class QWebPage::ExtensionOption |
| \since 4.4 |
| \brief The ExtensionOption class provides an extended input argument to QWebPage's extension support. |
| |
| \inmodule QtWebKit |
| |
| \sa QWebPage::extension() QWebPage::ExtensionReturn |
| */ |
| |
| |
| /*! |
| \class QWebPage::ExtensionReturn |
| \since 4.4 |
| \brief The ExtensionReturn class provides an output result from a QWebPage's extension. |
| |
| \inmodule QtWebKit |
| |
| \sa QWebPage::extension() QWebPage::ExtensionOption |
| */ |
| |
| /*! |
| \class QWebPage::ErrorPageExtensionOption |
| \since 4.6 |
| \brief The ErrorPageExtensionOption class describes the option |
| for the error page extension. |
| |
| \inmodule QtWebKit |
| |
| The ErrorPageExtensionOption class holds the \a url for which an error occurred as well as |
| the associated \a frame. |
| |
| The error itself is reported by an error \a domain, the \a error code as well as \a errorString. |
| |
| \sa QWebPage::extension() QWebPage::ErrorPageExtensionReturn |
| */ |
| |
| /*! |
| \variable QWebPage::ErrorPageExtensionOption::url |
| \brief the url for which an error occurred |
| */ |
| |
| /*! |
| \variable QWebPage::ErrorPageExtensionOption::frame |
| \brief the frame associated with the error |
| */ |
| |
| /*! |
| \variable QWebPage::ErrorPageExtensionOption::domain |
| \brief the domain that reported the error |
| */ |
| |
| /*! |
| \variable QWebPage::ErrorPageExtensionOption::error |
| \brief the error code. Interpretation of the value depends on the \a domain |
| \sa QWebPage::ErrorDomain |
| */ |
| |
| /*! |
| \variable QWebPage::ErrorPageExtensionOption::errorString |
| \brief a string that describes the error |
| */ |
| |
| /*! |
| \class QWebPage::ErrorPageExtensionReturn |
| \since 4.6 |
| \brief The ErrorPageExtensionReturn describes the error page, which will be shown for the |
| frame for which the error occured. |
| |
| \inmodule QtWebKit |
| |
| The ErrorPageExtensionReturn class holds the data needed for creating an error page. Some are |
| optional such as \a contentType, which defaults to "text/html", as well as the \a encoding, which |
| is assumed to be UTF-8 if not indicated otherwise. |
| |
| The error page is stored in the \a content byte array, as HTML content. In order to convert a |
| QString to a byte array, the QString::toUtf8() method can be used. |
| |
| External objects such as stylesheets or images referenced in the HTML are located relative to |
| \a baseUrl. |
| |
| \sa QWebPage::extension() QWebPage::ErrorPageExtensionOption, QString::toUtf8() |
| */ |
| |
| /*! |
| \fn QWebPage::ErrorPageExtensionReturn::ErrorPageExtensionReturn() |
| |
| Constructs a new error page object. |
| */ |
| |
| |
| /*! |
| \variable QWebPage::ErrorPageExtensionReturn::contentType |
| \brief the error page's content type |
| */ |
| |
| /*! |
| \variable QWebPage::ErrorPageExtensionReturn::encoding |
| \brief the error page encoding |
| */ |
| |
| /*! |
| \variable QWebPage::ErrorPageExtensionReturn::baseUrl |
| \brief the base url |
| |
| External objects such as stylesheets or images referenced in the HTML are located relative to this url. |
| */ |
| |
| /*! |
| \variable QWebPage::ErrorPageExtensionReturn::content |
| \brief the HTML content of the error page |
| */ |
| |
| /*! |
| \class QWebPage::ChooseMultipleFilesExtensionOption |
| \since 4.5 |
| \brief The ChooseMultipleFilesExtensionOption class describes the option |
| for the multiple files selection extension. |
| |
| \inmodule QtWebKit |
| |
| The ChooseMultipleFilesExtensionOption class holds the frame originating the request |
| and the suggested filenames which might be provided. |
| |
| \sa QWebPage::extension() QWebPage::chooseFile(), QWebPage::ChooseMultipleFilesExtensionReturn |
| */ |
| |
| /*! |
| \variable QWebPage::ChooseMultipleFilesExtensionOption::parentFrame |
| \brief The frame in which the request originated |
| */ |
| |
| /*! |
| \variable QWebPage::ChooseMultipleFilesExtensionOption::suggestedFileNames |
| \brief The suggested filenames |
| */ |
| |
| /*! |
| \variable QWebPage::ChooseMultipleFilesExtensionReturn::fileNames |
| \brief The selected filenames |
| */ |
| |
| /*! |
| \class QWebPage::ChooseMultipleFilesExtensionReturn |
| \since 4.5 |
| \brief The ChooseMultipleFilesExtensionReturn describes the return value |
| for the multiple files selection extension. |
| |
| \inmodule QtWebKit |
| |
| The ChooseMultipleFilesExtensionReturn class holds the filenames selected by the user |
| when the extension is invoked. |
| |
| \sa QWebPage::extension() QWebPage::ChooseMultipleFilesExtensionOption |
| */ |
| |
| /*! |
| This virtual function can be reimplemented in a QWebPage subclass to provide support for extensions. The \a option |
| argument is provided as input to the extension; the output results can be stored in \a output. |
| |
| The behavior of this function is determined by \a extension. The \a option |
| and \a output values are typically casted to the corresponding types (for |
| example, ChooseMultipleFilesExtensionOption and |
| ChooseMultipleFilesExtensionReturn for ChooseMultipleFilesExtension). |
| |
| You can call supportsExtension() to check if an extension is supported by the page. |
| |
| Returns true if the extension was called successfully; otherwise returns false. |
| |
| \sa supportsExtension(), Extension |
| */ |
| bool QWebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) |
| { |
| #ifndef QT_NO_FILEDIALOG |
| if (extension == ChooseMultipleFilesExtension) { |
| // FIXME: do not ignore suggestedFiles |
| QStringList suggestedFiles = static_cast<const ChooseMultipleFilesExtensionOption*>(option)->suggestedFileNames; |
| QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; |
| QStringList names = QFileDialog::getOpenFileNames(parent, QString::null); |
| static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names; |
| return true; |
| } |
| #endif |
| |
| return false; |
| } |
| |
| /*! |
| This virtual function returns true if the web page supports \a extension; otherwise false is returned. |
| |
| \sa extension() |
| */ |
| bool QWebPage::supportsExtension(Extension extension) const |
| { |
| #ifndef QT_NO_FILEDIALOG |
| return extension == ChooseMultipleFilesExtension; |
| #else |
| Q_UNUSED(extension); |
| return false; |
| #endif |
| } |
| |
| /*! |
| Finds the specified string, \a subString, in the page, using the given \a options. |
| |
| If the HighlightAllOccurrences flag is passed, the function will highlight all occurrences |
| that exist in the page. All subsequent calls will extend the highlight, rather than |
| replace it, with occurrences of the new string. |
| |
| If the HighlightAllOccurrences flag is not passed, the function will select an occurrence |
| and all subsequent calls will replace the current occurrence with the next one. |
| |
| To clear the selection, just pass an empty string. |
| |
| Returns true if \a subString was found; otherwise returns false. |
| */ |
| bool QWebPage::findText(const QString &subString, FindFlags options) |
| { |
| ::TextCaseSensitivity caseSensitivity = ::TextCaseInsensitive; |
| if (options & FindCaseSensitively) |
| caseSensitivity = ::TextCaseSensitive; |
| |
| if (options & HighlightAllOccurrences) { |
| if (subString.isEmpty()) { |
| d->page->unmarkAllTextMatches(); |
| return true; |
| } else |
| return d->page->markAllMatchesForText(subString, caseSensitivity, true, 0); |
| } else { |
| if (subString.isEmpty()) { |
| d->page->mainFrame()->selection()->clear(); |
| Frame* frame = d->page->mainFrame()->tree()->firstChild(); |
| while (frame) { |
| frame->selection()->clear(); |
| frame = frame->tree()->traverseNextWithWrap(false); |
| } |
| } |
| ::FindDirection direction = ::FindDirectionForward; |
| if (options & FindBackward) |
| direction = ::FindDirectionBackward; |
| |
| const bool shouldWrap = options & FindWrapsAroundDocument; |
| |
| return d->page->findString(subString, caseSensitivity, direction, shouldWrap); |
| } |
| } |
| |
| /*! |
| Returns a pointer to the page's settings object. |
| |
| \sa QWebSettings::globalSettings() |
| */ |
| QWebSettings *QWebPage::settings() const |
| { |
| return d->settings; |
| } |
| |
| /*! |
| This function is called when the web content requests a file name, for example |
| as a result of the user clicking on a "file upload" button in a HTML form. |
| |
| A suggested filename may be provided in \a suggestedFile. The frame originating the |
| request is provided as \a parentFrame. |
| |
| \sa ChooseMultipleFilesExtension |
| */ |
| QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& suggestedFile) |
| { |
| Q_UNUSED(parentFrame) |
| #ifndef QT_NO_FILEDIALOG |
| QWidget* parent = (d->client) ? d->client->ownerWidget() : 0; |
| return QFileDialog::getOpenFileName(parent, QString::null, suggestedFile); |
| #else |
| return QString::null; |
| #endif |
| } |
| |
| /*! |
| Sets the QNetworkAccessManager \a manager responsible for serving network requests for this |
| QWebPage. |
| |
| \note It is currently not supported to change the network access manager after the |
| QWebPage has used it. The results of doing this are undefined. |
| |
| \sa networkAccessManager() |
| */ |
| void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager) |
| { |
| if (manager == d->networkManager) |
| return; |
| if (d->networkManager && d->networkManager->parent() == this) |
| delete d->networkManager; |
| d->networkManager = manager; |
| } |
| |
| /*! |
| Returns the QNetworkAccessManager that is responsible for serving network |
| requests for this QWebPage. |
| |
| \sa setNetworkAccessManager() |
| */ |
| QNetworkAccessManager *QWebPage::networkAccessManager() const |
| { |
| if (!d->networkManager) { |
| QWebPage *that = const_cast<QWebPage *>(this); |
| that->d->networkManager = new QNetworkAccessManager(that); |
| } |
| return d->networkManager; |
| } |
| |
| /*! |
| Sets the QWebPluginFactory \a factory responsible for creating plugins embedded into this |
| QWebPage. |
| |
| Note: The plugin factory is only used if the QWebSettings::PluginsEnabled attribute is enabled. |
| |
| \sa pluginFactory() |
| */ |
| void QWebPage::setPluginFactory(QWebPluginFactory *factory) |
| { |
| d->pluginFactory = factory; |
| } |
| |
| /*! |
| Returns the QWebPluginFactory that is responsible for creating plugins embedded into |
| this QWebPage. If no plugin factory is installed a null pointer is returned. |
| |
| \sa setPluginFactory() |
| */ |
| QWebPluginFactory *QWebPage::pluginFactory() const |
| { |
| return d->pluginFactory; |
| } |
| |
| /*! |
| This function is called when a user agent for HTTP requests is needed. You can reimplement this |
| function to dynamically return different user agents for different URLs, based on the \a url parameter. |
| |
| The default implementation returns the following value: |
| |
| "Mozilla/5.0 (%Platform%%Security%%Subplatform%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion%" |
| |
| On mobile platforms such as Symbian S60 and Maemo, "Mobile Safari" is used instead of "Safari". |
| |
| In this string the following values are replaced at run-time: |
| \list |
| \o %Platform% expands to the windowing system followed by "; " if it is not Windows (e.g. "X11; "). |
| \o %Security% expands to "N; " if SSL is disabled. |
| \o %Subplatform% expands to the operating system version (e.g. "Windows NT 6.1" or "Intel Mac OS X 10.5"). |
| \o %WebKitVersion% is the version of WebKit the application was compiled against. |
| \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version. |
| \endlist |
| */ |
| QString QWebPage::userAgentForUrl(const QUrl&) const |
| { |
| // splitting the string in three and user QStringBuilder is better than using QString::arg() |
| static QString firstPart; |
| static QString secondPart; |
| static QString thirdPart; |
| |
| if (firstPart.isNull() || secondPart.isNull() || thirdPart.isNull()) { |
| QString firstPartTemp; |
| firstPartTemp.reserve(150); |
| firstPartTemp += QString::fromLatin1("Mozilla/5.0 (" |
| |
| // Platform |
| #ifdef Q_WS_MAC |
| "Macintosh; " |
| #elif defined Q_WS_QWS |
| "QtEmbedded; " |
| #elif defined Q_WS_MAEMO_5 |
| "Maemo" |
| #elif defined Q_WS_MAEMO_6 |
| "MeeGo" |
| #elif defined Q_WS_WIN |
| // Nothing |
| #elif defined Q_WS_X11 |
| "X11; " |
| #elif defined Q_OS_SYMBIAN |
| "Symbian" |
| #else |
| "Unknown; " |
| #endif |
| ); |
| |
| #if defined Q_OS_SYMBIAN |
| QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion(); |
| switch (symbianVersion) { |
| case QSysInfo::SV_9_2: |
| firstPartTemp += QString::fromLatin1("OS/9.2; "); |
| break; |
| case QSysInfo::SV_9_3: |
| firstPartTemp += QString::fromLatin1("OS/9.3; "); |
| break; |
| case QSysInfo::SV_9_4: |
| firstPartTemp += QString::fromLatin1("OS/9.4; "); |
| break; |
| case QSysInfo::SV_SF_2: |
| firstPartTemp += QString::fromLatin1("/2; "); |
| break; |
| case QSysInfo::SV_SF_3: |
| firstPartTemp += QString::fromLatin1("/3; "); |
| break; |
| case QSysInfo::SV_SF_4: |
| firstPartTemp += QString::fromLatin1("/4; "); |
| break; |
| default: |
| firstPartTemp += QString::fromLatin1("; "); |
| break; |
| } |
| #endif |
| |
| #if defined(QT_NO_OPENSSL) |
| // No SSL support |
| firstPartTemp += QString::fromLatin1("N; "); |
| #endif |
| |
| // Operating system |
| #ifdef Q_OS_AIX |
| firstPartTemp += QString::fromLatin1("AIX"); |
| #elif defined Q_OS_WIN32 |
| firstPartTemp += windowsVersionForUAString(); |
| #elif defined Q_OS_DARWIN |
| #ifdef __i386__ || __x86_64__ |
| firstPartTemp += QString::fromLatin1("Intel Mac OS X"); |
| #else |
| firstPartTemp += QString::fromLatin1("PPC Mac OS X"); |
| #endif |
| |
| #elif defined Q_OS_BSDI |
| firstPartTemp += QString::fromLatin1("BSD"); |
| #elif defined Q_OS_BSD4 |
| firstPartTemp += QString::fromLatin1("BSD Four"); |
| #elif defined Q_OS_CYGWIN |
| firstPartTemp += QString::fromLatin1("Cygwin"); |
| #elif defined Q_OS_DGUX |
| firstPartTemp += QString::fromLatin1("DG/UX"); |
| #elif defined Q_OS_DYNIX |
| firstPartTemp += QString::fromLatin1("DYNIX/ptx"); |
| #elif defined Q_OS_FREEBSD |
| firstPartTemp += QString::fromLatin1("FreeBSD"); |
| #elif defined Q_OS_HPUX |
| firstPartTemp += QString::fromLatin1("HP-UX"); |
| #elif defined Q_OS_HURD |
| firstPartTemp += QString::fromLatin1("GNU Hurd"); |
| #elif defined Q_OS_IRIX |
| firstPartTemp += QString::fromLatin1("SGI Irix"); |
| #elif defined Q_OS_LINUX |
| #if !defined(Q_WS_MAEMO_5) && !defined(Q_WS_MAEMO_6) |
| |
| #if defined(__x86_64__) |
| firstPartTemp += QString::fromLatin1("Linux x86_64"); |
| #elif defined(__i386__) |
| firstPartTemp += QString::fromLatin1("Linux i686"); |
| #else |
| firstPartTemp += QString::fromLatin1("Linux"); |
| #endif |
| #endif |
| |
| #elif defined Q_OS_LYNX |
| firstPartTemp += QString::fromLatin1("LynxOS"); |
| #elif defined Q_OS_NETBSD |
| firstPartTemp += QString::fromLatin1("NetBSD"); |
| #elif defined Q_OS_OS2 |
| firstPartTemp += QString::fromLatin1("OS/2"); |
| #elif defined Q_OS_OPENBSD |
| firstPartTemp += QString::fromLatin1("OpenBSD"); |
| #elif defined Q_OS_OS2EMX |
| firstPartTemp += QString::fromLatin1("OS/2"); |
| #elif defined Q_OS_OSF |
| firstPartTemp += QString::fromLatin1("HP Tru64 UNIX"); |
| #elif defined Q_OS_QNX6 |
| firstPartTemp += QString::fromLatin1("QNX RTP Six"); |
| #elif defined Q_OS_QNX |
| firstPartTemp += QString::fromLatin1("QNX"); |
| #elif defined Q_OS_RELIANT |
| firstPartTemp += QString::fromLatin1("Reliant UNIX"); |
| #elif defined Q_OS_SCO |
| firstPartTemp += QString::fromLatin1("SCO OpenServer"); |
| #elif defined Q_OS_SOLARIS |
| firstPartTemp += QString::fromLatin1("Sun Solaris"); |
| #elif defined Q_OS_ULTRIX |
| firstPartTemp += QString::fromLatin1("DEC Ultrix"); |
| #elif defined Q_OS_SYMBIAN |
| firstPartTemp += QLatin1Char(' '); |
| QSysInfo::S60Version s60Version = QSysInfo::s60Version(); |
| switch (s60Version) { |
| case QSysInfo::SV_S60_3_1: |
| firstPartTemp += QString::fromLatin1("Series60/3.1"); |
| break; |
| case QSysInfo::SV_S60_3_2: |
| firstPartTemp += QString::fromLatin1("Series60/3.2"); |
| break; |
| case QSysInfo::SV_S60_5_0: |
| firstPartTemp += QString::fromLatin1("Series60/5.0"); |
| break; |
| default: |
| break; |
| } |
| #elif defined Q_OS_UNIX |
| firstPartTemp += QString::fromLatin1("UNIX BSD/SYSV system"); |
| #elif defined Q_OS_UNIXWARE |
| firstPartTemp += QString::fromLatin1("UnixWare Seven, Open UNIX Eight"); |
| #else |
| firstPartTemp += QString::fromLatin1("Unknown"); |
| #endif |
| |
| #if ENABLE(QT_USERAGENT_DEVICEMODEL) |
| // adding Model Number |
| QtMobility::QSystemDeviceInfo systemDeviceInfo; |
| |
| QString model = systemDeviceInfo.model(); |
| if (!model.isEmpty()) { |
| if (!firstPartTemp.endsWith("; ")) |
| firstPartTemp += QString::fromLatin1("; "); |
| firstPartTemp += systemDeviceInfo.model(); |
| } |
| #endif |
| firstPartTemp.squeeze(); |
| firstPart = firstPartTemp; |
| |
| QString secondPartTemp; |
| secondPartTemp.reserve(150); |
| secondPartTemp += QString::fromLatin1(") "); |
| |
| // webkit/qt version |
| secondPartTemp += QString::fromLatin1("AppleWebKit/"); |
| secondPartTemp += qWebKitVersion(); |
| secondPartTemp += QString::fromLatin1(" (KHTML, like Gecko) "); |
| |
| |
| // Application name split the third part |
| secondPartTemp.squeeze(); |
| secondPart = secondPartTemp; |
| |
| QString thirdPartTemp; |
| thirdPartTemp.reserve(150); |
| #if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) |
| thirdPartTemp += QLatin1String(" Mobile Safari/"); |
| #else |
| thirdPartTemp += QLatin1String(" Safari/"); |
| #endif |
| thirdPartTemp += qWebKitVersion(); |
| thirdPartTemp.squeeze(); |
| thirdPart = thirdPartTemp; |
| Q_ASSERT(!firstPart.isNull()); |
| Q_ASSERT(!secondPart.isNull()); |
| Q_ASSERT(!thirdPart.isNull()); |
| } |
| |
| // Application name/version |
| QString appName = QCoreApplication::applicationName(); |
| if (!appName.isEmpty()) { |
| QString appVer = QCoreApplication::applicationVersion(); |
| if (!appVer.isEmpty()) |
| appName.append(QLatin1Char('/') + appVer); |
| } else { |
| // Qt version |
| appName = QString::fromLatin1("Qt/") + QString::fromLatin1(qVersion()); |
| } |
| |
| return firstPart + secondPart + appName + thirdPart; |
| } |
| |
| |
| void QWebPagePrivate::_q_onLoadProgressChanged(int) |
| { |
| m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad(); |
| m_bytesReceived = page->progress()->totalBytesReceived(); |
| } |
| |
| |
| /*! |
| Returns the total number of bytes that were received from the network to render the current page, |
| including extra content such as embedded images. |
| |
| \sa bytesReceived() |
| */ |
| quint64 QWebPage::totalBytes() const |
| { |
| return d->m_totalBytes; |
| } |
| |
| |
| /*! |
| Returns the number of bytes that were received from the network to render the current page. |
| |
| \sa totalBytes(), loadProgress() |
| */ |
| quint64 QWebPage::bytesReceived() const |
| { |
| return d->m_bytesReceived; |
| } |
| |
| /*! |
| \since 4.7 |
| \fn void QWebPage::viewportChangeRequested() |
| |
| Page authors can provide the supplied values by using the viewport meta tag. More information |
| 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}. |
| |
| \sa QWebPage::ViewportAttributes, setPreferredContentsSize(), QGraphicsWebView::setScale() |
| */ |
| |
| /*! |
| \fn void QWebPage::loadStarted() |
| |
| This signal is emitted when a page starts loading content. |
| |
| \sa loadFinished() |
| */ |
| |
| /*! |
| \fn void QWebPage::loadProgress(int progress) |
| |
| This signal is emitted when the global progress status changes. |
| The current value is provided by \a progress and scales from 0 to 100, |
| which is the default range of QProgressBar. |
| It accumulates changes from all the child frames. |
| |
| \sa bytesReceived() |
| */ |
| |
| /*! |
| \fn void QWebPage::loadFinished(bool ok) |
| |
| This signal is emitted when the page finishes loading content. This signal |
| is independant of script execution or page rendering. |
| \a ok will indicate whether the load was successful or any error occurred. |
| |
| \sa loadStarted(), ErrorPageExtension |
| */ |
| |
| /*! |
| \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent) |
| |
| This signal is emitted when the mouse hovers over a link. |
| |
| \a link contains the link url. |
| \a title is the link element's title, if it is specified in the markup. |
| \a textContent provides text within the link element, e.g., text inside an HTML anchor tag. |
| |
| When the mouse leaves the link element the signal is emitted with empty parameters. |
| |
| \sa linkClicked() |
| */ |
| |
| /*! |
| \fn void QWebPage::statusBarMessage(const QString& text) |
| |
| This signal is emitted when the statusbar \a text is changed by the page. |
| */ |
| |
| /*! |
| \fn void QWebPage::frameCreated(QWebFrame *frame) |
| |
| This signal is emitted whenever the page creates a new \a frame. |
| |
| \sa currentFrame() |
| */ |
| |
| /*! |
| \fn void QWebPage::selectionChanged() |
| |
| This signal is emitted whenever the selection changes, either interactively |
| or programmatically (e.g. by calling triggerAction() with a selection action). |
| |
| \sa selectedText() |
| */ |
| |
| /*! |
| \fn void QWebPage::contentsChanged() |
| \since 4.5 |
| |
| This signal is emitted whenever the text in form elements changes |
| as well as other editable content. |
| |
| \sa contentEditable, modified, QWebFrame::toHtml(), QWebFrame::toPlainText() |
| */ |
| |
| /*! |
| \fn void QWebPage::geometryChangeRequested(const QRect& geom) |
| |
| This signal is emitted whenever the document wants to change the position and size of the |
| page to \a geom. This can happen for example through JavaScript. |
| */ |
| |
| /*! |
| \fn void QWebPage::repaintRequested(const QRect& dirtyRect) |
| |
| This signal is emitted whenever this QWebPage should be updated. It's useful |
| when rendering a QWebPage without a QWebView or QGraphicsWebView. |
| \a dirtyRect contains the area that needs to be updated. To paint the QWebPage get |
| the mainFrame() and call the render(QPainter*, const QRegion&) method with the |
| \a dirtyRect as the second parameter. |
| |
| \sa mainFrame() |
| \sa view() |
| */ |
| |
| /*! |
| \fn void QWebPage::scrollRequested(int dx, int dy, const QRect& rectToScroll) |
| |
| This signal is emitted whenever the content given by \a rectToScroll needs |
| to be scrolled \a dx and \a dy downwards and no view was set. |
| |
| \sa view() |
| */ |
| |
| /*! |
| \fn void QWebPage::windowCloseRequested() |
| |
| This signal is emitted whenever the page requests the web browser window to be closed, |
| for example through the JavaScript \c{window.close()} call. |
| */ |
| |
| /*! |
| \fn void QWebPage::printRequested(QWebFrame *frame) |
| |
| This signal is emitted whenever the page requests the web browser to print \a frame, |
| for example through the JavaScript \c{window.print()} call. |
| |
| \sa QWebFrame::print(), QPrintPreviewDialog |
| */ |
| |
| /*! |
| \fn void QWebPage::unsupportedContent(QNetworkReply *reply) |
| |
| This signal is emitted when WebKit cannot handle a link the user navigated to or a |
| web server's response includes a "Content-Disposition" header with the 'attachment' |
| directive. If "Content-Disposition" is present in \a reply, the web server is indicating |
| that the client should prompt the user to save the content regardless of content-type. |
| See RFC 2616 sections 19.5.1 for details about Content-Disposition. |
| |
| At signal emission time the meta-data of the QNetworkReply \a reply is available. |
| |
| \note The receiving slot is responsible for deleting the QNetworkReply \a reply. |
| |
| \note This signal is only emitted if the forwardUnsupportedContent property is set to true. |
| |
| \sa downloadRequested() |
| */ |
| |
| /*! |
| \fn void QWebPage::downloadRequested(const QNetworkRequest &request) |
| |
| This signal is emitted when the user decides to download a link. The url of |
| the link as well as additional meta-information is contained in \a request. |
| |
| \sa unsupportedContent() |
| */ |
| |
| /*! |
| \fn void QWebPage::microFocusChanged() |
| |
| This signal is emitted when for example the position of the cursor in an editable form |
| element changes. It is used to inform input methods about the new on-screen position where |
| the user is able to enter text. This signal is usually connected to the |
| QWidget::updateMicroFocus() slot. |
| */ |
| |
| /*! |
| \fn void QWebPage::linkClicked(const QUrl &url) |
| |
| This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy |
| property is set to delegate the link handling for the specified \a url. |
| |
| By default no links are delegated and are handled by QWebPage instead. |
| |
| \note This signal possibly won't be emitted for clicked links which use |
| JavaScript to trigger navigation. |
| |
| \sa linkHovered() |
| */ |
| |
| /*! |
| \fn void QWebPage::toolBarVisibilityChangeRequested(bool visible) |
| |
| This signal is emitted whenever the visibility of the toolbar in a web browser |
| window that hosts QWebPage should be changed to \a visible. |
| */ |
| |
| /*! |
| \fn void QWebPage::statusBarVisibilityChangeRequested(bool visible) |
| |
| This signal is emitted whenever the visibility of the statusbar in a web browser |
| window that hosts QWebPage should be changed to \a visible. |
| */ |
| |
| /*! |
| \fn void QWebPage::menuBarVisibilityChangeRequested(bool visible) |
| |
| This signal is emitted whenever the visibility of the menubar in a web browser |
| window that hosts QWebPage should be changed to \a visible. |
| */ |
| |
| /*! |
| \fn void QWebPage::databaseQuotaExceeded(QWebFrame* frame, QString databaseName); |
| \since 4.5 |
| |
| This signal is emitted whenever the web site shown in \a frame is asking to store data |
| to the database \a databaseName and the quota allocated to that web site is exceeded. |
| |
| \sa QWebDatabase |
| */ |
| /*! |
| \fn void QWebPage::applicationCacheQuotaExceeded(QWebSecurityOrigin* origin, quint64 defaultOriginQuota); |
| |
| This signal is emitted whenever the web site is asking to store data to the application cache |
| database databaseName and the quota allocated to that web site is exceeded. |
| |
| */ |
| |
| /*! |
| \since 4.5 |
| \fn void QWebPage::saveFrameStateRequested(QWebFrame* frame, QWebHistoryItem* item); |
| |
| This signal is emitted shortly before the history of navigated pages |
| in \a frame is changed, for example when navigating back in the history. |
| |
| The provided QWebHistoryItem, \a item, holds the history entry of the frame before |
| the change. |
| |
| A potential use-case for this signal is to store custom data in |
| the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData(). |
| */ |
| |
| /*! |
| \since 4.5 |
| \fn void QWebPage::restoreFrameStateRequested(QWebFrame* frame); |
| |
| This signal is emitted when the load of \a frame is finished and the application may now update its state accordingly. |
| */ |
| |
| /*! |
| \fn QWebPagePrivate* QWebPage::handle() const |
| \internal |
| */ |
| |
| #include "moc_qwebpage.cpp" |