diff --git a/src/vwebview.cpp b/src/vwebview.cpp index 0152207d..ed1a6098 100644 --- a/src/vwebview.cpp +++ b/src/vwebview.cpp @@ -19,60 +19,39 @@ static const QString c_ClipboardPropertyMark = "CopiedImageURLAltered"; VWebView::VWebView(VFile *p_file, QWidget *p_parent) - : QWebEngineView(p_parent), m_file(p_file), m_actionHooked(false) + : QWebEngineView(p_parent), + m_file(p_file), + m_copyImageUrlActionHooked(false), + m_copyActionHooked(false) { setAcceptDrops(false); } void VWebView::contextMenuEvent(QContextMenuEvent *p_event) { -#if defined(Q_OS_WIN) - if (!m_actionHooked) { - m_actionHooked = true; - - // "Copy Image URL" action will put the encoded URL to the clipboard as text - // and the URL as URLs. If the URL contains Chinese, OneNote or Word could not - // recognize it. - // We need to change it to only-space-encoded text. - QAction *copyImageUrlAct = pageAction(QWebEnginePage::CopyImageUrlToClipboard); - connect(copyImageUrlAct, &QAction::triggered, - this, [this](){ - // To avoid failure of setting clipboard mime data. - QCoreApplication::processEvents(); - - QClipboard *clipboard = QApplication::clipboard(); - const QMimeData *mimeData = clipboard->mimeData(); - clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), false); - if (clipboard->ownsClipboard() - && mimeData->hasText() - && mimeData->hasUrls()) { - QString text = mimeData->text(); - QList urls = mimeData->urls(); - if (urls.size() == 1 - && urls[0].isLocalFile() - && urls[0].toEncoded() == text) { - QString spaceOnlyText = urls[0].toString(QUrl::EncodeSpaces); - if (spaceOnlyText != text) { - // Set new mime data. - QMimeData *data = new QMimeData(); - data->setUrls(urls); - data->setText(spaceOnlyText); - clipboard->setMimeData(data); - - clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), true); - qDebug() << "clipboard copy image URL altered" << spaceOnlyText; - } - } - } - }); - } -#endif - QMenu *menu = page()->createStandardContextMenu(); menu->setToolTipsVisible(true); const QList actions = menu->actions(); +#if defined(Q_OS_WIN) + if (!m_copyImageUrlActionHooked) { + // "Copy Image URL" action will put the encoded URL to the clipboard as text + // and the URL as URLs. If the URL contains Chinese, OneNote or Word could not + // recognize it. + // We need to change it to only-space-encoded text. + QAction *copyImageUrlAct = getPageAction(actions, QWebEnginePage::CopyImageUrlToClipboard); + if (actions.contains(copyImageUrlAct)) { + connect(copyImageUrlAct, &QAction::triggered, + this, &VWebView::handleCopyImageUrlAction); + + m_copyImageUrlActionHooked = true; + + qDebug() << "hooked CopyImageUrl action" << copyImageUrlAct; + } + } +#endif + if (!hasSelection() && m_file && m_file->isModifiable()) { QAction *editAct= new QAction(VIconUtils::menuIcon(":/resources/icons/edit_note.svg"), tr("&Edit"), menu); @@ -90,17 +69,19 @@ void VWebView::contextMenuEvent(QContextMenuEvent *p_event) // the fully-encoded URL to fetch the image while Windows seems to not // recognize it. #if defined(Q_OS_WIN) - QAction *defaultCopyImageAct = pageAction(QWebEnginePage::CopyImageToClipboard); + QAction *defaultCopyImageAct = getPageAction(actions, QWebEnginePage::CopyImageToClipboard); if (defaultCopyImageAct && actions.contains(defaultCopyImageAct)) { QAction *copyImageAct = new QAction(defaultCopyImageAct->text(), menu); copyImageAct->setToolTip(defaultCopyImageAct->toolTip()); connect(copyImageAct, &QAction::triggered, this, &VWebView::copyImage); menu->insertAction(defaultCopyImageAct, copyImageAct); - menu->removeAction(defaultCopyImageAct); + defaultCopyImageAct->setVisible(false); } #endif + hideUnusedActions(menu); + menu->exec(p_event->globalPos()); delete menu; } @@ -112,7 +93,7 @@ void VWebView::handleEditAction() void VWebView::copyImage() { - Q_ASSERT(m_actionHooked); + Q_ASSERT(m_copyImageUrlActionHooked); // triggerPageAction(QWebEnginePage::CopyImageUrlToClipboard) will not really // trigger the corresponding action. It just do the stuff directly. @@ -145,3 +126,120 @@ void VWebView::copyImage() // Fall back. triggerPageAction(QWebEnginePage::CopyImageToClipboard); } + +void VWebView::handleCopyImageUrlAction() +{ + // To avoid failure of setting clipboard mime data. + QCoreApplication::processEvents(); + + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); + clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), false); + if (clipboard->ownsClipboard() + && mimeData->hasText() + && mimeData->hasUrls()) { + QString text = mimeData->text(); + QList urls = mimeData->urls(); + if (urls.size() == 1 + && urls[0].isLocalFile() + && urls[0].toEncoded() == text) { + QString spaceOnlyText = urls[0].toString(QUrl::EncodeSpaces); + if (spaceOnlyText != text) { + // Set new mime data. + QMimeData *data = new QMimeData(); + data->setUrls(urls); + data->setText(spaceOnlyText); + clipboard->setMimeData(data); + + clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), true); + qDebug() << "clipboard copy image URL altered" << spaceOnlyText; + } + } + } +} + +void VWebView::hideUnusedActions(QMenu *p_menu) +{ + const QList actions = p_menu->actions(); + + QList unusedActions; + + // Back. + QAction *act = getPageAction(actions, QWebEnginePage::Back); + unusedActions.append(act); + + // Forward. + act = getPageAction(actions, QWebEnginePage::Forward); + unusedActions.append(act); + + // Reload. + act = getPageAction(actions, QWebEnginePage::Reload); + unusedActions.append(act); + + // ViewSource. + act = getPageAction(actions, QWebEnginePage::ViewSource); + unusedActions.append(act); + + // DownloadImageToDisk. + act = getPageAction(actions, QWebEnginePage::DownloadImageToDisk); + unusedActions.append(act); + + for (auto it : unusedActions) { + if (it) { + it->setVisible(false); + } + } +} + +void VWebView::handleCopyAction() +{ + // To avoid failure of setting clipboard mime data. + QCoreApplication::processEvents(); + + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); + clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), false); + qDebug() << clipboard->ownsClipboard() << mimeData->hasHtml(); + if (clipboard->ownsClipboard() + && mimeData->hasHtml()) { + QString html = mimeData->html(); + if (html.startsWith("")) { + return; + } + + html = QString("%1").arg(html); + + // Set new mime data. + QMimeData *data = new QMimeData(); + data->setHtml(html); + + if (mimeData->hasUrls()) { + data->setUrls(mimeData->urls()); + } + + if (mimeData->hasText()) { + data->setText(mimeData->text()); + } + + clipboard->setMimeData(data); + clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), true); + qDebug() << "clipboard copy Html altered" << html; + } +} + +QAction *VWebView::getPageAction(const QList &p_actions, + QWebEnginePage::WebAction p_webAction) +{ + QAction *act = pageAction(p_webAction); + if (act && !p_actions.contains(act)) { + QString text = act->text(); + for (auto it : p_actions) { + if (it->text().endsWith(text)) { + act = it; + break; + } + } + } + + return act; +} diff --git a/src/vwebview.h b/src/vwebview.h index 9bf9c328..269e5601 100644 --- a/src/vwebview.h +++ b/src/vwebview.h @@ -4,6 +4,7 @@ #include class VFile; +class QMenu; class VWebView : public QWebEngineView { @@ -21,15 +22,27 @@ protected: private slots: void handleEditAction(); + void handleCopyImageUrlAction(); + + void handleCopyAction(); + // Copy the clicked image. // Used to replace the default CopyImageToClipboard action. void copyImage(); private: + void hideUnusedActions(QMenu *p_menu); + + // pageAction() may not return exactly the action in use. + QAction *getPageAction(const QList &p_actions, + QWebEnginePage::WebAction p_webAction); + VFile *m_file; // Whether this view has hooked the Copy Image Url action. - bool m_actionHooked; + bool m_copyImageUrlActionHooked; + + bool m_copyActionHooked; }; #endif // VWEBVIEW_H