diff --git a/src/vwebview.cpp b/src/vwebview.cpp index 05ea4d5c..0505d33f 100644 --- a/src/vwebview.cpp +++ b/src/vwebview.cpp @@ -6,15 +6,65 @@ #include #include #include +#include +#include +#include +#include #include "vfile.h" +// We set the property of the clipboard to mark that the URL copied in the +// clipboard has been altered. +static const QString c_ClipboardPropertyMark = "CopiedImageURLAltered"; + VWebView::VWebView(VFile *p_file, QWidget *p_parent) - : QWebEngineView(p_parent), m_file(p_file) + : QWebEngineView(p_parent), m_file(p_file), m_actionHooked(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); @@ -22,7 +72,7 @@ void VWebView::contextMenuEvent(QContextMenuEvent *p_event) if (!hasSelection() && m_file && m_file->isModifiable()) { QAction *editAct= new QAction(QIcon(":/resources/icons/edit_note.svg"), - tr("&Edit"), this); + tr("&Edit"), menu); editAct->setToolTip(tr("Edit current note")); connect(editAct, &QAction::triggered, this, &VWebView::handleEditAction); @@ -33,6 +83,21 @@ void VWebView::contextMenuEvent(QContextMenuEvent *p_event) } } + // We need to replace the "Copy Image" action, because the default one use + // 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); + 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); + } +#endif + menu->exec(p_event->globalPos()); delete menu; } @@ -41,3 +106,39 @@ void VWebView::handleEditAction() { emit editNote(); } + +void VWebView::copyImage() +{ + Q_ASSERT(m_actionHooked); + + // triggerPageAction(QWebEnginePage::CopyImageUrlToClipboard) will not really + // trigger the corresponding action. It just do the stuff directly. + QAction *copyImageUrlAct = pageAction(QWebEnginePage::CopyImageUrlToClipboard); + copyImageUrlAct->trigger(); + + QCoreApplication::processEvents(); + + QClipboard *clipboard = QApplication::clipboard(); + if (clipboard->property(c_ClipboardPropertyMark.toLatin1()).toBool()) { + const QMimeData *mimeData = clipboard->mimeData(); + QString imgPath; + if (mimeData->hasUrls()) { + QList urls = mimeData->urls(); + if (urls[0].isLocalFile()) { + imgPath = urls[0].toLocalFile(); + } + } + + if (!imgPath.isEmpty()) { + QImage img(imgPath); + if (!img.isNull()) { + clipboard->setImage(img, QClipboard::Clipboard); + qDebug() << "clipboard copy image via URL" << imgPath; + return; + } + } + } + + // Fall back. + triggerPageAction(QWebEnginePage::CopyImageToClipboard); +} diff --git a/src/vwebview.h b/src/vwebview.h index 3780397d..9bf9c328 100644 --- a/src/vwebview.h +++ b/src/vwebview.h @@ -21,8 +21,15 @@ protected: private slots: void handleEditAction(); + // Copy the clicked image. + // Used to replace the default CopyImageToClipboard action. + void copyImage(); + private: VFile *m_file; + + // Whether this view has hooked the Copy Image Url action. + bool m_actionHooked; }; #endif // VWEBVIEW_H