diff options
Diffstat (limited to 'src/webenginewidgets/api')
-rw-r--r-- | src/webenginewidgets/api/qwebenginecertificateerror.cpp | 2 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginecertificateerror.h | 1 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginecontextmenudata.cpp | 41 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginecontextmenudata.h | 2 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginedownloaditem.cpp | 32 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginedownloaditem.h | 9 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginedownloaditem_p.h | 1 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.cpp | 230 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage.h | 18 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginepage_p.h | 7 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebengineprofile.cpp | 90 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebengineprofile.h | 5 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginescript.cpp | 3 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginescriptcollection.cpp | 2 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginesettings.cpp | 7 | ||||
-rw-r--r-- | src/webenginewidgets/api/qwebenginesettings.h | 5 |
16 files changed, 383 insertions, 72 deletions
diff --git a/src/webenginewidgets/api/qwebenginecertificateerror.cpp b/src/webenginewidgets/api/qwebenginecertificateerror.cpp index 289bb7ec0..a0641c9dd 100644 --- a/src/webenginewidgets/api/qwebenginecertificateerror.cpp +++ b/src/webenginewidgets/api/qwebenginecertificateerror.cpp @@ -104,6 +104,8 @@ QWebEngineCertificateError::~QWebEngineCertificateError() \value CertificateWeakKey The certificate contains a weak key. \value CertificateNameConstraintViolation The certificate claimed DNS names that are in violation of name constraints. \value CertificateValidityTooLong The certificate has a validity period that is too long. (Added in Qt 5.7) + \value CertificateTransparencyRequired Certificate Transparency was required for this connection, but the server + did not provide CT information that complied with the policy. (Added in Qt 5.8) */ /*! diff --git a/src/webenginewidgets/api/qwebenginecertificateerror.h b/src/webenginewidgets/api/qwebenginecertificateerror.h index 7cb6341bc..82ac281be 100644 --- a/src/webenginewidgets/api/qwebenginecertificateerror.h +++ b/src/webenginewidgets/api/qwebenginecertificateerror.h @@ -70,6 +70,7 @@ public: CertificateWeakKey = -211, CertificateNameConstraintViolation = -212, CertificateValidityTooLong = -213, + CertificateTransparencyRequired = -214, }; Error error() const; diff --git a/src/webenginewidgets/api/qwebenginecontextmenudata.cpp b/src/webenginewidgets/api/qwebenginecontextmenudata.cpp index 4d72071e5..5d68ed0ec 100644 --- a/src/webenginewidgets/api/qwebenginecontextmenudata.cpp +++ b/src/webenginewidgets/api/qwebenginecontextmenudata.cpp @@ -135,7 +135,7 @@ void QWebEngineContextMenuData::reset() */ QPoint QWebEngineContextMenuData::position() const { - return d ? d->pos : QPoint(); + return d ? d->position() : QPoint(); } /*! @@ -143,7 +143,7 @@ QPoint QWebEngineContextMenuData::position() const */ QString QWebEngineContextMenuData::linkText() const { - return d ? d->linkText : QString(); + return d ? d->linkText() : QString(); } /*! @@ -151,7 +151,7 @@ QString QWebEngineContextMenuData::linkText() const */ QUrl QWebEngineContextMenuData::linkUrl() const { - return d ? d->linkUrl : QUrl(); + return d ? d->linkUrl() : QUrl(); } /*! @@ -159,7 +159,7 @@ QUrl QWebEngineContextMenuData::linkUrl() const */ QString QWebEngineContextMenuData::selectedText() const { - return d ? d->selectedText : QString(); + return d ? d->selectedText() : QString(); } /*! @@ -167,7 +167,7 @@ QString QWebEngineContextMenuData::selectedText() const */ QUrl QWebEngineContextMenuData::mediaUrl() const { - return d ? d->mediaUrl : QUrl(); + return d ? d->mediaUrl() : QUrl(); } /*! @@ -175,7 +175,7 @@ QUrl QWebEngineContextMenuData::mediaUrl() const */ QWebEngineContextMenuData::MediaType QWebEngineContextMenuData::mediaType() const { - return d ? static_cast<QWebEngineContextMenuData::MediaType>(d->mediaType) : MediaTypeNone; + return d ? static_cast<QWebEngineContextMenuData::MediaType>(d->mediaType()) : MediaTypeNone; } /*! @@ -183,7 +183,34 @@ QWebEngineContextMenuData::MediaType QWebEngineContextMenuData::mediaType() cons */ bool QWebEngineContextMenuData::isContentEditable() const { - return d ? d->isEditable : false; + return d ? d->isEditable() : false; +} + +/*! + If the context is a word considered misspelled by the spell-checker, returns the misspelled word. + + For possible replacements of the word, see spellCheckerSuggestions(). + + \since 5.8 +*/ +QString QWebEngineContextMenuData::misspelledWord() const +{ + if (d) + return d->misspelledWord(); + return QString(); +} + +/*! + If the context is a word considered misspelled by the spell-checker, returns a list of suggested replacements + for misspelledWord(). + + \since 5.8 +*/ +QStringList QWebEngineContextMenuData::spellCheckerSuggestions() const +{ + if (d) + return d->spellCheckerSuggestions(); + return QStringList(); } /*! diff --git a/src/webenginewidgets/api/qwebenginecontextmenudata.h b/src/webenginewidgets/api/qwebenginecontextmenudata.h index 8e85fee16..97cfe9f65 100644 --- a/src/webenginewidgets/api/qwebenginecontextmenudata.h +++ b/src/webenginewidgets/api/qwebenginecontextmenudata.h @@ -76,6 +76,8 @@ public: QUrl mediaUrl() const; MediaType mediaType() const; bool isContentEditable() const; + QString misspelledWord() const; + QStringList spellCheckerSuggestions() const; private: void reset(); diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp index bfb0dd0e8..b777a0898 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp +++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp @@ -80,6 +80,7 @@ QWebEngineDownloadItemPrivate::QWebEngineDownloadItemPrivate(QWebEngineProfilePr , downloadId(-1) , downloadState(QWebEngineDownloadItem::DownloadCancelled) , savePageFormat(QWebEngineDownloadItem::MimeHtmlSaveFormat) + , type(QWebEngineDownloadItem::Attachment) , downloadUrl(url) , totalBytes(-1) , receivedBytes(0) @@ -218,6 +219,25 @@ quint32 QWebEngineDownloadItem::id() const */ /*! + \enum QWebEngineDownloadItem::DownloadType + \since 5.8 + + Describes the requested download's type. + + \value Attachment The web server's response includes a + \c Content-Disposition header with the \c attachment directive. If \c Content-Disposition + is present in the reply, the web server is indicating that the client should prompt the + user to save the content regardless of the content type. + See \l {RFC 2616 section 19.5.1} for details. + \value DownloadAttribute The user clicked a link with the \c download + attribute. See \l {HTML download attribute} for details. + \value UserRequested The user initiated the download, for example by + selecting a web action. + \value SavePage Saving of the current page was requested (for example by + the \l{QWebEnginePage::WebAction}{QWebEnginePage::SavePage} web action). +*/ + +/*! Returns the download item's current state. \sa QWebEngineDownloadItem::DownloadState @@ -342,6 +362,18 @@ void QWebEngineDownloadItem::setSavePageFormat(QWebEngineDownloadItem::SavePageF d->savePageFormat = format; } +/*! + Returns the requested download's type. + \since 5.8 + + */ + +QWebEngineDownloadItem::DownloadType QWebEngineDownloadItem::type() const +{ + Q_D(const QWebEngineDownloadItem); + return d->type; +} + QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p, QObject *parent) : QObject(parent) , d_ptr(p) diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.h b/src/webenginewidgets/api/qwebenginedownloaditem.h index 80b5c06c5..4b58748ad 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.h +++ b/src/webenginewidgets/api/qwebenginedownloaditem.h @@ -72,6 +72,14 @@ public: }; Q_ENUM(SavePageFormat) + enum DownloadType { + Attachment = 0, + DownloadAttribute, + UserRequested, + SavePage + }; + Q_ENUM(DownloadType) + quint32 id() const; DownloadState state() const; qint64 totalBytes() const; @@ -83,6 +91,7 @@ public: bool isFinished() const; SavePageFormat savePageFormat() const; void setSavePageFormat(SavePageFormat format); + DownloadType type() const; public Q_SLOTS: void accept(); diff --git a/src/webenginewidgets/api/qwebenginedownloaditem_p.h b/src/webenginewidgets/api/qwebenginedownloaditem_p.h index ddb3b443a..9ddb45444 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem_p.h +++ b/src/webenginewidgets/api/qwebenginedownloaditem_p.h @@ -72,6 +72,7 @@ public: quint32 downloadId; QWebEngineDownloadItem::DownloadState downloadState; QWebEngineDownloadItem::SavePageFormat savePageFormat; + QWebEngineDownloadItem::DownloadType type; QString downloadPath; const QUrl downloadUrl; QString mimeType; diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index e84c91bd7..0188cfef8 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -90,6 +90,8 @@ QT_BEGIN_NAMESPACE using namespace QtWebEngineCore; +static const int MaxTooltipLength = 1024; + static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition) { switch (disposition) { @@ -390,6 +392,13 @@ void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &re m_callbacks.invoke(requestId, result); } +#ifndef QT_NO_PRINTER +void QWebEnginePagePrivate::didPrintPageOnPrinter(quint64 requestId, bool result) +{ + m_callbacks.invoke(requestId, result); +} +#endif + void QWebEnginePagePrivate::passOnFocus(bool reverse) { if (view) @@ -489,6 +498,9 @@ void QWebEnginePagePrivate::updateAction(QWebEnginePage::WebAction action) const case QWebEnginePage::ReloadAndBypassCache: enabled = !isLoading; break; + case QWebEnginePage::ViewSource: + enabled = adapter->canViewSource(); + break; default: break; } @@ -504,6 +516,7 @@ void QWebEnginePagePrivate::updateNavigationActions() updateAction(QWebEnginePage::Stop); updateAction(QWebEnginePage::Reload); updateAction(QWebEnginePage::ReloadAndBypassCache); + updateAction(QWebEnginePage::ViewSource); } #ifndef QT_NO_ACTION @@ -788,6 +801,29 @@ void QWebEnginePage::setBackgroundColor(const QColor &color) } /*! + * Save the currently loaded web page to disk. + * + * The web page is saved to \a filePath in the specified \a{format}. + * + * This is a short cut for the following actions: + * \list + * \li Trigger the Save web action. + * \li Accept the next download item and set the specified file path and save format. + * \endlist + * + * This function issues an asynchronous download request for the web page and returns immediately. + * + * \sa QWebEngineDownloadItem::SavePageFormat + * \since 5.8 + */ +void QWebEnginePage::save(const QString &filePath, + QWebEngineDownloadItem::SavePageFormat format) const +{ + Q_D(const QWebEnginePage); + d->adapter->save(filePath, format); +} + +/*! \property QWebEnginePage::audioMuted \brief whether the current page audio is muted. \since 5.7 @@ -972,6 +1008,9 @@ QAction *QWebEnginePage::action(WebAction action) const case SavePage: text = tr("Save &Page"); break; + case ViewSource: + text = tr("&View Page Source"); + break; case NoWebAction: case WebActionCount: Q_UNREACHABLE(); @@ -1036,122 +1075,122 @@ void QWebEnginePage::triggerAction(WebAction action, bool) d->adapter->unselect(); break; case OpenLinkInThisWindow: - if (menuData.linkUrl.isValid()) - setUrl(menuData.linkUrl); + if (menuData.linkUrl().isValid()) + setUrl(menuData.linkUrl()); break; case OpenLinkInNewWindow: - if (menuData.linkUrl.isValid()) { + if (menuData.linkUrl().isValid()) { QWebEnginePage *newPage = createWindow(WebBrowserWindow); if (newPage) - newPage->setUrl(menuData.linkUrl); + newPage->setUrl(menuData.linkUrl()); } break; case OpenLinkInNewTab: - if (menuData.linkUrl.isValid()) { + if (menuData.linkUrl().isValid()) { QWebEnginePage *newPage = createWindow(WebBrowserTab); if (newPage) - newPage->setUrl(menuData.linkUrl); + newPage->setUrl(menuData.linkUrl()); } break; case OpenLinkInNewBackgroundTab: - if (menuData.linkUrl.isValid()) { + if (menuData.linkUrl().isValid()) { QWebEnginePage *newPage = createWindow(WebBrowserBackgroundTab); if (newPage) - newPage->setUrl(menuData.linkUrl); + newPage->setUrl(menuData.linkUrl()); } break; case CopyLinkToClipboard: - if (menuData.linkUrl.isValid()) { - QString urlString = menuData.linkUrl.toString(QUrl::FullyEncoded); - QString title = menuData.linkText.toHtmlEscaped(); + if (menuData.linkUrl().isValid()) { + QString urlString = menuData.linkUrl().toString(QUrl::FullyEncoded); + QString title = menuData.linkText().toHtmlEscaped(); QMimeData *data = new QMimeData(); data->setText(urlString); QString html = QStringLiteral("<a href=\"") + urlString + QStringLiteral("\">") + title + QStringLiteral("</a>"); data->setHtml(html); - data->setUrls(QList<QUrl>() << menuData.linkUrl); + data->setUrls(QList<QUrl>() << menuData.linkUrl()); qApp->clipboard()->setMimeData(data); } break; case DownloadLinkToDisk: - if (menuData.linkUrl.isValid()) - d->adapter->download(menuData.linkUrl, menuData.suggestedFileName); + if (menuData.linkUrl().isValid()) + d->adapter->download(menuData.linkUrl(), menuData.suggestedFileName()); break; case CopyImageToClipboard: - if (menuData.hasImageContent && - (menuData.mediaType == WebEngineContextMenuData::MediaTypeImage || - menuData.mediaType == WebEngineContextMenuData::MediaTypeCanvas)) + if (menuData.hasImageContent() && + (menuData.mediaType() == WebEngineContextMenuData::MediaTypeImage || + menuData.mediaType() == WebEngineContextMenuData::MediaTypeCanvas)) { - d->adapter->copyImageAt(menuData.pos); + d->adapter->copyImageAt(menuData.position()); } break; case CopyImageUrlToClipboard: - if (menuData.mediaUrl.isValid() && menuData.mediaType == WebEngineContextMenuData::MediaTypeImage) { - QString urlString = menuData.mediaUrl.toString(QUrl::FullyEncoded); - QString title = menuData.linkText; + if (menuData.mediaUrl().isValid() && menuData.mediaType() == WebEngineContextMenuData::MediaTypeImage) { + QString urlString = menuData.mediaUrl().toString(QUrl::FullyEncoded); + QString title = menuData.linkText(); if (!title.isEmpty()) title = QStringLiteral(" alt=\"%1\"").arg(title.toHtmlEscaped()); QMimeData *data = new QMimeData(); data->setText(urlString); QString html = QStringLiteral("<img src=\"") + urlString + QStringLiteral("\"") + title + QStringLiteral("></img>"); data->setHtml(html); - data->setUrls(QList<QUrl>() << menuData.mediaUrl); + data->setUrls(QList<QUrl>() << menuData.mediaUrl()); qApp->clipboard()->setMimeData(data); } break; case DownloadImageToDisk: case DownloadMediaToDisk: - if (menuData.mediaUrl.isValid()) - d->adapter->download(menuData.mediaUrl, menuData.suggestedFileName); + if (menuData.mediaUrl().isValid()) + d->adapter->download(menuData.mediaUrl(), menuData.suggestedFileName()); break; case CopyMediaUrlToClipboard: - if (menuData.mediaUrl.isValid() && - (menuData.mediaType == WebEngineContextMenuData::MediaTypeAudio || - menuData.mediaType == WebEngineContextMenuData::MediaTypeVideo)) + if (menuData.mediaUrl().isValid() && + (menuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio || + menuData.mediaType() == WebEngineContextMenuData::MediaTypeVideo)) { - QString urlString = menuData.mediaUrl.toString(QUrl::FullyEncoded); + QString urlString = menuData.mediaUrl().toString(QUrl::FullyEncoded); QMimeData *data = new QMimeData(); data->setText(urlString); - if (menuData.mediaType == WebEngineContextMenuData::MediaTypeAudio) + if (menuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio) data->setHtml(QStringLiteral("<audio src=\"") + urlString + QStringLiteral("\"></audio>")); else data->setHtml(QStringLiteral("<video src=\"") + urlString + QStringLiteral("\"></video>")); - data->setUrls(QList<QUrl>() << menuData.mediaUrl); + data->setUrls(QList<QUrl>() << menuData.mediaUrl()); qApp->clipboard()->setMimeData(data); } break; case ToggleMediaControls: - if (menuData.mediaUrl.isValid() && menuData.mediaFlags & WebEngineContextMenuData::MediaCanToggleControls) { - bool enable = !(menuData.mediaFlags & WebEngineContextMenuData::MediaControls); - d->adapter->executeMediaPlayerActionAt(menuData.pos, WebContentsAdapter::MediaPlayerControls, enable); + if (menuData.mediaUrl().isValid() && menuData.mediaFlags() & WebEngineContextMenuData::MediaCanToggleControls) { + bool enable = !(menuData.mediaFlags() & WebEngineContextMenuData::MediaControls); + d->adapter->executeMediaPlayerActionAt(menuData.position(), WebContentsAdapter::MediaPlayerControls, enable); } break; case ToggleMediaLoop: - if (menuData.mediaUrl.isValid() && - (menuData.mediaType == WebEngineContextMenuData::MediaTypeAudio || - menuData.mediaType == WebEngineContextMenuData::MediaTypeVideo)) + if (menuData.mediaUrl().isValid() && + (menuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio || + menuData.mediaType() == WebEngineContextMenuData::MediaTypeVideo)) { - bool enable = !(menuData.mediaFlags & WebEngineContextMenuData::MediaLoop); - d->adapter->executeMediaPlayerActionAt(menuData.pos, WebContentsAdapter::MediaPlayerLoop, enable); + bool enable = !(menuData.mediaFlags() & WebEngineContextMenuData::MediaLoop); + d->adapter->executeMediaPlayerActionAt(menuData.position(), WebContentsAdapter::MediaPlayerLoop, enable); } break; case ToggleMediaPlayPause: - if (menuData.mediaUrl.isValid() && - (menuData.mediaType == WebEngineContextMenuData::MediaTypeAudio || - menuData.mediaType == WebEngineContextMenuData::MediaTypeVideo)) + if (menuData.mediaUrl().isValid() && + (menuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio || + menuData.mediaType() == WebEngineContextMenuData::MediaTypeVideo)) { - bool enable = (menuData.mediaFlags & WebEngineContextMenuData::MediaPaused); - d->adapter->executeMediaPlayerActionAt(menuData.pos, WebContentsAdapter::MediaPlayerPlay, enable); + bool enable = (menuData.mediaFlags() & WebEngineContextMenuData::MediaPaused); + d->adapter->executeMediaPlayerActionAt(menuData.position(), WebContentsAdapter::MediaPlayerPlay, enable); } break; case ToggleMediaMute: - if (menuData.mediaUrl.isValid() && menuData.mediaFlags & WebEngineContextMenuData::MediaHasAudio) { + if (menuData.mediaUrl().isValid() && menuData.mediaFlags() & WebEngineContextMenuData::MediaHasAudio) { // Make sure to negate the value, so that toggling actually works. - bool enable = !(menuData.mediaFlags & WebEngineContextMenuData::MediaMuted); - d->adapter->executeMediaPlayerActionAt(menuData.pos, WebContentsAdapter::MediaPlayerMute, enable); + bool enable = !(menuData.mediaFlags() & WebEngineContextMenuData::MediaMuted); + d->adapter->executeMediaPlayerActionAt(menuData.position(), WebContentsAdapter::MediaPlayerMute, enable); } break; case InspectElement: - d->adapter->inspectElementAt(menuData.pos); + d->adapter->inspectElementAt(menuData.position()); break; case ExitFullScreen: d->adapter->exitFullScreen(); @@ -1162,6 +1201,17 @@ void QWebEnginePage::triggerAction(WebAction action, bool) case SavePage: d->adapter->save(); break; + case ViewSource: + // This is a workaround to make the ViewSource action working in a context menu. + // The WebContentsAdapter::viewSource() method deletes a + // RenderWidgetHostViewQtDelegateWidget instance which passes the control to the event + // loop. If the QMenu::aboutToHide() signal is connected to the QObject::deleteLater() + // slot the QMenu is deleted by the event handler while the ViewSource action is still not + // completed. This may lead to a crash. To avoid this the WebContentsAdapter::viewSource() + // method is called indirectly via the QTimer::singleShot() function which schedules the + // the viewSource() call after the QMenu's destruction. + QTimer::singleShot(0, this, [d](){ d->adapter->viewSource(); }); + break; case NoWebAction: break; case WebActionCount: @@ -1170,6 +1220,22 @@ void QWebEnginePage::triggerAction(WebAction action, bool) } } +/*! + * \since 5.8 + * Replace the current misspelled word with \a replacement. + * + * The current misspelled word can be found in QWebEngineContextMenuData::misspelledWord(), + * and suggested replacements in QWebEngineContextMenuData::spellCheckerSuggestions(). + * + * \sa contextMenuData(), + */ + +void QWebEnginePage::replaceMisspelledWord(const QString &replacement) +{ + Q_D(QWebEnginePage); + d->adapter->replaceMisspelling(replacement); +} + void QWebEnginePage::findText(const QString &subString, FindFlags options, const QWebEngineCallback<bool> &resultCallback) { Q_D(QWebEnginePage); @@ -1206,7 +1272,7 @@ bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData return false; contextData.reset(); - QContextMenuEvent event(QContextMenuEvent::Mouse, data.pos, view->mapToGlobal(data.pos)); + QContextMenuEvent event(QContextMenuEvent::Mouse, data.position(), view->mapToGlobal(data.position())); switch (view->contextMenuPolicy()) { case Qt::PreventContextMenu: return false; @@ -1216,7 +1282,7 @@ bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData break; case Qt::CustomContextMenu: contextData = data; - Q_EMIT view->customContextMenuRequested(data.pos); + Q_EMIT view->customContextMenuRequested(data.position()); break; case Qt::ActionsContextMenu: if (view->actions().count()) { @@ -1351,6 +1417,16 @@ bool QWebEnginePagePrivate::isEnabled() const return true; } +void QWebEnginePagePrivate::setToolTip(const QString &toolTipText) +{ + if (view) { + QString wrappedTip; + if (!toolTipText.isEmpty()) + wrappedTip = QLatin1String("<p>") % toolTipText.toHtmlEscaped().left(MaxTooltipLength) % QLatin1String("</p>"); + view->setToolTip(wrappedTip); + } +} + QMenu *QWebEnginePage::createStandardContextMenu() { Q_D(QWebEnginePage); @@ -1361,13 +1437,25 @@ QMenu *QWebEnginePage::createStandardContextMenu() QAction *action = 0; const WebEngineContextMenuData &contextMenuData = *d->contextData.d; - if (!contextMenuData.linkText.isEmpty() && contextMenuData.linkUrl.isValid()) { + if (contextMenuData.isEditable() && !contextMenuData.spellCheckerSuggestions().isEmpty()) { + QPointer<QWebEnginePage> thisRef(this); + for (int i=0; i < contextMenuData.spellCheckerSuggestions().count() && i < 4; i++) { + QAction *action = new QAction(menu); + QString replacement = contextMenuData.spellCheckerSuggestions().at(i); + QObject::connect(action, &QAction::triggered, [thisRef, replacement] { if (thisRef) thisRef->replaceMisspelledWord(replacement); }); + action->setText(replacement); + menu->addAction(action); + } + menu->addSeparator(); + } + + if (!contextMenuData.linkText().isEmpty() && contextMenuData.linkUrl().isValid()) { action = QWebEnginePage::action(OpenLinkInThisWindow); action->setText(tr("Follow Link")); menu->addAction(action); menu->addAction(QWebEnginePage::action(DownloadLinkToDisk)); } - if (contextMenuData.selectedText.isEmpty()) { + if (contextMenuData.selectedText().isEmpty()) { action = new QAction(QIcon::fromTheme(QStringLiteral("go-previous")), tr("&Back"), menu); connect(action, &QAction::triggered, d->view, &QWebEngineView::back); action->setEnabled(d->adapter->canGoBack()); @@ -1381,16 +1469,18 @@ QMenu *QWebEnginePage::createStandardContextMenu() action = new QAction(QIcon::fromTheme(QStringLiteral("view-refresh")), tr("&Reload"), menu); connect(action, &QAction::triggered, d->view, &QWebEngineView::reload); menu->addAction(action); + + menu->addAction(QWebEnginePage::action(ViewSource)); } else { menu->addAction(QWebEnginePage::action(Copy)); menu->addAction(QWebEnginePage::action(Unselect)); } - if (!contextMenuData.linkText.isEmpty() && contextMenuData.linkUrl.isValid()) { + if (!contextMenuData.linkText().isEmpty() && contextMenuData.linkUrl().isValid()) { menu->addAction(QWebEnginePage::action(CopyLinkToClipboard)); } - if (contextMenuData.mediaUrl.isValid()) { - switch (contextMenuData.mediaType) { + if (contextMenuData.mediaUrl().isValid()) { + switch (contextMenuData.mediaType()) { case WebEngineContextMenuData::MediaTypeImage: menu->addAction(QWebEnginePage::action(DownloadImageToDisk)); menu->addAction(QWebEnginePage::action(CopyImageUrlToClipboard)); @@ -1405,15 +1495,15 @@ QMenu *QWebEnginePage::createStandardContextMenu() menu->addAction(QWebEnginePage::action(CopyMediaUrlToClipboard)); menu->addAction(QWebEnginePage::action(ToggleMediaPlayPause)); menu->addAction(QWebEnginePage::action(ToggleMediaLoop)); - if (contextMenuData.mediaFlags & WebEngineContextMenuData::MediaHasAudio) + if (contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaHasAudio) menu->addAction(QWebEnginePage::action(ToggleMediaMute)); - if (contextMenuData.mediaFlags & WebEngineContextMenuData::MediaCanToggleControls) + if (contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaCanToggleControls) menu->addAction(QWebEnginePage::action(ToggleMediaControls)); break; default: break; } - } else if (contextMenuData.mediaType == WebEngineContextMenuData::MediaTypeCanvas) { + } else if (contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeCanvas) { menu->addAction(QWebEnginePage::action(CopyImageToClipboard)); } @@ -1471,7 +1561,7 @@ static inline QWebEnginePage::FileSelectionMode toPublic(FilePickerController::F return static_cast<QWebEnginePage::FileSelectionMode>(mode); } -void QWebEnginePagePrivate::runFileChooser(FilePickerController *controller) +void QWebEnginePagePrivate::runFileChooser(QSharedPointer<FilePickerController> controller) { Q_Q(QWebEnginePage); @@ -1481,8 +1571,6 @@ void QWebEnginePagePrivate::runFileChooser(FilePickerController *controller) controller->accepted(selectedFileNames); else controller->rejected(); - - delete controller; } WebEngineSettings *QWebEnginePagePrivate::webEngineSettings() const @@ -1779,6 +1867,28 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res d->m_callbacks.registerCallback(requestId, resultCallback); } +#ifndef QT_NO_PRINTER +/*! + \fn void QWebEnginePage::print(QPrinter *printer, FunctorOrLambda resultCallback) + Renders the current content of the page into a temporary PDF document, then prints it using \a printer. + + The settings for creating and printing the PDF document will be retrieved from the \a printer + object. + It is the users responsibility to ensure the \a printer remains valid until \a resultCallback + has been called. + + The \a resultCallback must take a boolean as parameter. If printing was successful, this + boolean will have the value \c true, otherwise, its value will be \c false. + \since 5.8 +*/ +void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback) +{ + Q_D(QWebEnginePage); + quint64 requestId = d->adapter->printOnPrinterCallbackResult(printer); + d->m_callbacks.registerCallback(requestId, resultCallback); +} +#endif // QT_NO_PRINTER + /*! \since 5.7 diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index 2ac8e0f3e..e85f9b30e 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -42,6 +42,7 @@ #include <QtWebEngineWidgets/qtwebenginewidgetsglobal.h> #include <QtWebEngineWidgets/qwebenginecertificateerror.h> +#include <QtWebEngineWidgets/qwebenginedownloaditem.h> #include <QtWebEngineCore/qwebenginecallback.h> #include <QtCore/qobject.h> @@ -53,6 +54,9 @@ QT_BEGIN_NAMESPACE class QMenu; +#ifndef QT_NO_PRINTER +class QPrinter; +#endif class QWebChannel; class QWebEngineContextMenuData; class QWebEngineFullScreenRequest; @@ -123,6 +127,7 @@ public: Unselect, SavePage, OpenLinkInNewBackgroundTab, + ViewSource, WebActionCount }; @@ -206,6 +211,8 @@ public: #endif virtual void triggerAction(WebAction action, bool checked = false); + void replaceMisspelledWord(const QString &replacement); + virtual bool event(QEvent*); #ifdef Q_QDOC void findText(const QString &subString, FindFlags options = FindFlags()); @@ -261,6 +268,9 @@ public: QColor backgroundColor() const; void setBackgroundColor(const QColor &color); + void save(const QString &filePath, QWebEngineDownloadItem::SavePageFormat format + = QWebEngineDownloadItem::MimeHtmlSaveFormat) const; + bool isAudioMuted() const; void setAudioMuted(bool muted); bool recentlyAudible() const; @@ -272,6 +282,14 @@ public: void printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &layout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF())); #endif +#ifndef QT_NO_PRINTER +#ifdef Q_QDOC + void print(QPrinter *printer, FunctorOrLambda resultCallback); +#else + void print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback); +#endif // QDOC +#endif // QT_NO_PRINTER + const QWebEngineContextMenuData &contextMenuData() const; Q_SIGNALS: diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 96640a63a..8d78429d8 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -112,13 +112,16 @@ public: virtual void requestFullScreenMode(const QUrl &origin, bool fullscreen) Q_DECL_OVERRIDE; virtual bool isFullScreenMode() const Q_DECL_OVERRIDE; virtual void javascriptDialog(QSharedPointer<QtWebEngineCore::JavaScriptDialogController>) Q_DECL_OVERRIDE; - virtual void runFileChooser(QtWebEngineCore::FilePickerController *controller) Q_DECL_OVERRIDE; + virtual void runFileChooser(QSharedPointer<QtWebEngineCore::FilePickerController>) Q_DECL_OVERRIDE; virtual void showColorDialog(QSharedPointer<QtWebEngineCore::ColorChooserController>) Q_DECL_OVERRIDE; virtual void didRunJavaScript(quint64 requestId, const QVariant& result) Q_DECL_OVERRIDE; virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) Q_DECL_OVERRIDE; virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) Q_DECL_OVERRIDE; virtual void didFindText(quint64 requestId, int matchCount) Q_DECL_OVERRIDE; virtual void didPrintPage(quint64 requestId, const QByteArray &result) Q_DECL_OVERRIDE; +#ifndef QT_NO_PRINTER + virtual void didPrintPageOnPrinter(quint64 requestId, bool result) Q_DECL_OVERRIDE; +#endif virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE; virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE; virtual void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) Q_DECL_OVERRIDE; @@ -141,6 +144,7 @@ public: void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) Q_DECL_OVERRIDE; virtual bool isEnabled() const Q_DECL_OVERRIDE; + virtual void setToolTip(const QString &toolTipText) Q_DECL_OVERRIDE; const QObject *holdingQObject() const Q_DECL_OVERRIDE; virtual QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextAdapter() Q_DECL_OVERRIDE; @@ -173,6 +177,7 @@ public: QWebChannel *webChannel; unsigned int webChannelWorldId; QUrl iconUrl; + bool m_navigationActionTriggered; mutable QtWebEngineCore::CallbackDirectory m_callbacks; mutable QAction *actions[QWebEnginePage::WebActionCount]; diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index 664323034..886a7207e 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -96,6 +96,11 @@ using QtWebEngineCore::BrowserContextAdapter; A QWebEngineUrlSchemeHandler can be registered for a profile by installUrlSchemeHandler() to add support for custom URL schemes. Requests for the scheme are then issued to QWebEngineUrlSchemeHandler::requestStarted() as QWebEngineUrlRequestJob objects. + + Spellchecking HTML form fields can be enabled per profile by using the setSpellCheckEnabled() + method and the current languages used for spellchecking can be set by using the + setSpellCheckLanguages() method. + */ /*! @@ -180,10 +185,12 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) Q_ASSERT(!m_ongoingDownloads.contains(info.id)); QWebEngineDownloadItemPrivate *itemPrivate = new QWebEngineDownloadItemPrivate(this, info.url); itemPrivate->downloadId = info.id; - itemPrivate->downloadState = QWebEngineDownloadItem::DownloadRequested; + itemPrivate->downloadState = info.accepted ? QWebEngineDownloadItem::DownloadInProgress + : QWebEngineDownloadItem::DownloadRequested; itemPrivate->downloadPath = info.path; itemPrivate->mimeType = info.mimeType; itemPrivate->savePageFormat = static_cast<QWebEngineDownloadItem::SavePageFormat>(info.savePageFormat); + itemPrivate->type = static_cast<QWebEngineDownloadItem::DownloadType>(info.downloadType); QWebEngineDownloadItem *download = new QWebEngineDownloadItem(itemPrivate, q); @@ -556,6 +563,87 @@ QWebEngineProfile *QWebEngineProfile::defaultProfile() } /*! + \since 5.8 + + Sets the current list of \a languages for the spell checker. + Each language should match the name of the \c .bdic dictionary. + For example, the language \c en-US will load the \c en-US.bdic + dictionary file. + + Qt WebEngine checks for the \c qtwebengine_dictionaries subdirectory + first in the local directory and if it is not found, in the Qt + installation directory. + + On macOS, depending on how Qt WebEngine is configured at build time, there are two possibilities + how spellchecking data is found: + + \list + \li Hunspell dictionaries (default) - .bdic dictionaries are used, just like on other + platforms + \li Native dictionaries - the macOS spellchecking APIs are used (which means the results + will depend on the installed OS dictionaries) + \endlist + + Thus, in the macOS Hunspell case, Qt WebEngine will look in the \e qtwebengine_dictionaries + subdirectory located inside the application bundle \c Resources directory, and also in the + \c Resources directory located inside the Qt framework bundle. + + To summarize, in case of Hunspell usage, the following paths are considered: + + \list + \li QCoreApplication::applicationDirPath()/qtwebengine_dictionaries + or QCoreApplication::applicationDirPath()/../Contents/Resources/qtwebengine_dictionaries + (on macOS) + \li [QLibraryInfo::DataPath]/qtwebengine_dictionaries + or path/to/QtWebEngineCore.framework/Resources/qtwebengine_dictionaries (Qt framework + bundle on macOS) + \endlist + + For more information about how to compile \c .bdic dictionaries, see the + \l{WebEngine Widgets Spellchecker Example}{Spellchecker Example}. + +*/ +void QWebEngineProfile::setSpellCheckLanguages(const QStringList &languages) +{ + Q_D(QWebEngineProfile); + d->browserContext()->setSpellCheckLanguages(languages); +} + +/*! + \since 5.8 + + Returns the list of languages used by the spell checker. +*/ +QStringList QWebEngineProfile::spellCheckLanguages() const +{ + const Q_D(QWebEngineProfile); + return d->browserContext()->spellCheckLanguages(); +} + +/*! + \since 5.8 + + Enables spell checker if \a enable is \c true, otherwise disables it. + \sa isSpellCheckEnabled() + */ +void QWebEngineProfile::setSpellCheckEnabled(bool enable) +{ + Q_D(QWebEngineProfile); + d->browserContext()->setSpellCheckEnabled(enable); +} +/*! + \since 5.8 + + Returns \c true if the spell checker is enabled; otherwise returns \c false. + \sa setSpellCheckEnabled() + */ +bool QWebEngineProfile::isSpellCheckEnabled() const +{ + const Q_D(QWebEngineProfile); + return d->browserContext()->isSpellCheckEnabled(); +} + +/*! Returns the default settings for all pages in this profile. */ QWebEngineSettings *QWebEngineProfile::settings() const diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h index d981fa5bb..1ce4bfe17 100644 --- a/src/webenginewidgets/api/qwebengineprofile.h +++ b/src/webenginewidgets/api/qwebengineprofile.h @@ -121,6 +121,11 @@ public: void clearHttpCache(); + void setSpellCheckLanguages(const QStringList &languages); + QStringList spellCheckLanguages() const; + void setSpellCheckEnabled(bool enabled); + bool isSpellCheckEnabled() const; + static QWebEngineProfile *defaultProfile(); Q_SIGNALS: diff --git a/src/webenginewidgets/api/qwebenginescript.cpp b/src/webenginewidgets/api/qwebenginescript.cpp index 73dd5075e..04a9d979a 100644 --- a/src/webenginewidgets/api/qwebenginescript.cpp +++ b/src/webenginewidgets/api/qwebenginescript.cpp @@ -61,7 +61,8 @@ using QtWebEngineCore::UserScript; not accessible from a different one. ScriptWorldId provides some predefined IDs for this purpose. - \note Chromium extensions, such as \c @include, \c @match, and \c @exclude, are not supported. + The following \l Greasemonkey attributes are supported since Qt 5.8: + \c @exclude, \c @include, \c @name, \c @match, and \c @run-at. Use QWebEnginePage::scripts() and QWebEngineProfile::scripts() to access the collection of scripts associated with a single page or a diff --git a/src/webenginewidgets/api/qwebenginescriptcollection.cpp b/src/webenginewidgets/api/qwebenginescriptcollection.cpp index 4b77b4699..8d393924f 100644 --- a/src/webenginewidgets/api/qwebenginescriptcollection.cpp +++ b/src/webenginewidgets/api/qwebenginescriptcollection.cpp @@ -40,7 +40,7 @@ #include "qwebenginescriptcollection.h" #include "qwebenginescriptcollection_p.h" -#include "user_resource_controller_host.h" +#include "renderer_host/user_resource_controller_host.h" using QtWebEngineCore::UserScript; diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp index dfca16287..50002e3e6 100644 --- a/src/webenginewidgets/api/qwebenginesettings.cpp +++ b/src/webenginewidgets/api/qwebenginesettings.cpp @@ -89,6 +89,13 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web return WebEngineSettings::AutoLoadIconsForPage; case QWebEngineSettings::TouchIconsEnabled: return WebEngineSettings::TouchIconsEnabled; + case QWebEngineSettings::FocusOnNavigationEnabled: + return WebEngineSettings::FocusOnNavigationEnabled; + case QWebEngineSettings::PrintElementBackgrounds: + return WebEngineSettings::PrintElementBackgrounds; + case QWebEngineSettings::AllowRunningInsecureContent: + return WebEngineSettings::AllowRunningInsecureContent; + default: return WebEngineSettings::UnsupportedInCoreSettings; } diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h index 8eda50ee2..e3fb83ff5 100644 --- a/src/webenginewidgets/api/qwebenginesettings.h +++ b/src/webenginewidgets/api/qwebenginesettings.h @@ -85,7 +85,10 @@ public: WebGLEnabled, Accelerated2dCanvasEnabled, AutoLoadIconsForPage, - TouchIconsEnabled + TouchIconsEnabled, + FocusOnNavigationEnabled, + PrintElementBackgrounds, + AllowRunningInsecureContent }; enum FontSize { |