From 1ce8c05da9b3d0e3905718c3f5ca7d57ea2e11be Mon Sep 17 00:00:00 2001 From: Le Tan Date: Sun, 19 Aug 2018 12:06:50 +0800 Subject: [PATCH] MdEditor: support copy in-place preview --- src/utils/vclipboardutils.cpp | 14 ++++ src/utils/vclipboardutils.h | 5 ++ src/vmdeditor.cpp | 123 ++++++++++++++++++++++++---------- src/vmdeditor.h | 7 +- src/vtextblockdata.h | 5 ++ src/vtextedit.cpp | 5 ++ src/vtextedit.h | 3 + 7 files changed, 126 insertions(+), 36 deletions(-) diff --git a/src/utils/vclipboardutils.cpp b/src/utils/vclipboardutils.cpp index 79062ca1..4a498b70 100644 --- a/src/utils/vclipboardutils.cpp +++ b/src/utils/vclipboardutils.cpp @@ -35,6 +35,20 @@ void VClipboardUtils::setImageLoop(QClipboard *p_clipboard, } } +void VClipboardUtils::setImageToClipboard(QClipboard *p_clipboard, + const QPixmap &p_image, + QClipboard::Mode p_mode) +{ + QImage img(p_image.toImage()); + +#if defined(Q_OS_WIN) + // On Windows, setImage() may fail. We will repeatedly retry until succeed. + setImageLoop(p_clipboard, img, p_mode); +#else + p_clipboard->setImage(img, p_mode); +#endif +} + void VClipboardUtils::setMimeDataToClipboard(QClipboard *p_clipboard, QMimeData *p_mimeData, QClipboard::Mode p_mode) diff --git a/src/utils/vclipboardutils.h b/src/utils/vclipboardutils.h index a4f52b99..7ec28e8b 100644 --- a/src/utils/vclipboardutils.h +++ b/src/utils/vclipboardutils.h @@ -2,6 +2,7 @@ #define VCLIPBOARDUTILS_H #include +#include #include class QMimeData; @@ -14,6 +15,10 @@ public: const QImage &p_image, QClipboard::Mode p_mode = QClipboard::Clipboard); + static void setImageToClipboard(QClipboard *p_clipboard, + const QPixmap &p_image, + QClipboard::Mode p_mode = QClipboard::Clipboard); + static void setImageAndLinkToClipboard(QClipboard *p_clipboard, const QImage &p_image, const QString &p_link, diff --git a/src/vmdeditor.cpp b/src/vmdeditor.cpp index e4c5e450..8382a325 100644 --- a/src/vmdeditor.cpp +++ b/src/vmdeditor.cpp @@ -303,7 +303,9 @@ void VMdEditor::contextMenuEvent(QContextMenuEvent *p_event) if (textCursor().hasSelection()) { initCopyAsMenu(actions.isEmpty() ? NULL : actions.last(), menu.data()); } else { - initLinkMenu(actions.isEmpty() ? NULL : actions[0], menu.data(), p_event->pos()); + initLinkAndPreviewMenu(actions.isEmpty() ? NULL : actions[0], + menu.data(), + p_event->pos()); QAction *saveExitAct = new QAction(VIconUtils::menuIcon(":/resources/icons/save_exit.svg"), tr("&Save Changes And Read"), @@ -1462,7 +1464,7 @@ int VMdEditor::lineNumberAreaWidth() const return VTextEdit::lineNumberAreaWidth(); } -void VMdEditor::initLinkMenu(QAction *p_before, QMenu *p_menu, const QPoint &p_pos) +void VMdEditor::initLinkAndPreviewMenu(QAction *p_before, QMenu *p_menu, const QPoint &p_pos) { QTextCursor cursor = cursorForPosition(p_pos); int pos = cursor.position(); @@ -1536,6 +1538,9 @@ void VMdEditor::initLinkMenu(QAction *p_before, QMenu *p_menu, const QPoint &p_p } }); p_menu->insertAction(p_before, copyImageAct); + } else { + // Copy in-place preview. + initInPlacePreviewMenu(p_before, p_menu, block, pos); } p_menu->insertSeparator(p_before ? p_before : NULL); @@ -1560,43 +1565,91 @@ void VMdEditor::initLinkMenu(QAction *p_before, QMenu *p_menu, const QPoint &p_p } } - if (linkText.isEmpty()) { + if (!linkText.isEmpty()) { + QString linkUrl = VUtils::linkUrlToPath(m_file->fetchBasePath(), linkText); + bool isLocalFile = QFileInfo::exists(linkUrl); + + QAction *viewLinkAct = new QAction(tr("View Link"), p_menu); + connect(viewLinkAct, &QAction::triggered, + this, [this, linkUrl]() { + QDesktopServices::openUrl(VUtils::pathToUrl(linkUrl)); + }); + p_menu->insertAction(p_before, viewLinkAct); + + QAction *copyLinkAct = new QAction(tr("Copy Link URL"), p_menu); + connect(copyLinkAct, &QAction::triggered, + this, [this, linkUrl]() { + QClipboard *clipboard = QApplication::clipboard(); + VClipboardUtils::setLinkToClipboard(clipboard, + linkUrl, + QClipboard::Clipboard); + }); + p_menu->insertAction(p_before, copyLinkAct); + + if (isLocalFile) { + QAction *copyLinkPathAct = new QAction(tr("Copy Link Path"), p_menu); + connect(copyLinkPathAct, &QAction::triggered, + this, [this, linkUrl]() { + QClipboard *clipboard = QApplication::clipboard(); + QMimeData *data = new QMimeData(); + data->setText(linkUrl); + VClipboardUtils::setMimeDataToClipboard(clipboard, + data, + QClipboard::Clipboard); + }); + p_menu->insertAction(p_before, copyLinkPathAct); + } + + p_menu->insertSeparator(p_before ? p_before : NULL); return; } - QString linkUrl = VUtils::linkUrlToPath(m_file->fetchBasePath(), linkText); - bool isLocalFile = QFileInfo::exists(linkUrl); + if (initInPlacePreviewMenu(p_before, p_menu, block, pos)) { + p_menu->insertSeparator(p_before ? p_before : NULL); + } +} - QAction *viewLinkAct = new QAction(tr("View Link"), p_menu); - connect(viewLinkAct, &QAction::triggered, - this, [this, linkUrl]() { - QDesktopServices::openUrl(VUtils::pathToUrl(linkUrl)); - }); - p_menu->insertAction(p_before, viewLinkAct); - - QAction *copyLinkAct = new QAction(tr("Copy Link URL"), p_menu); - connect(copyLinkAct, &QAction::triggered, - this, [this, linkUrl]() { - QClipboard *clipboard = QApplication::clipboard(); - VClipboardUtils::setLinkToClipboard(clipboard, - linkUrl, - QClipboard::Clipboard); - }); - p_menu->insertAction(p_before, copyLinkAct); - - if (isLocalFile) { - QAction *copyLinkPathAct = new QAction(tr("Copy Link Path"), p_menu); - connect(copyLinkPathAct, &QAction::triggered, - this, [this, linkUrl]() { - QClipboard *clipboard = QApplication::clipboard(); - QMimeData *data = new QMimeData(); - data->setText(linkUrl); - VClipboardUtils::setMimeDataToClipboard(clipboard, - data, - QClipboard::Clipboard); - }); - p_menu->insertAction(p_before, copyLinkPathAct); +bool VMdEditor::initInPlacePreviewMenu(QAction *p_before, + QMenu *p_menu, + const QTextBlock &p_block, + int p_pos) +{ + VTextBlockData *data = VTextBlockData::blockData(p_block); + if (!data) { + return false; } - p_menu->insertSeparator(p_before ? p_before : NULL); + const QVector &previews = data->getPreviews(); + if (previews.isEmpty()) { + return false; + } + + QPixmap image; + int pib = p_pos - p_block.position(); + for (auto info : previews) { + const VPreviewedImageInfo &pii = info->m_imageInfo; + if (pii.contains(pib)) { + const QPixmap *img = findImage(pii.m_imageName); + if (img) { + image = *img; + } + + break; + } + } + + if (image.isNull()) { + return false; + } + + QAction *copyImageAct = new QAction(tr("Copy In-Place Preview"), p_menu); + connect(copyImageAct, &QAction::triggered, + this, [this, image]() { + QClipboard *clipboard = QApplication::clipboard(); + VClipboardUtils::setImageToClipboard(clipboard, + image, + QClipboard::Clipboard); + }); + p_menu->insertAction(p_before, copyImageAct); + return true; } diff --git a/src/vmdeditor.h b/src/vmdeditor.h index 8902ad66..02e4f08f 100644 --- a/src/vmdeditor.h +++ b/src/vmdeditor.h @@ -277,7 +277,12 @@ private: void initPasteAsBlockQuoteMenu(QMenu *p_menu); - void initLinkMenu(QAction *p_before, QMenu *p_menu, const QPoint &p_pos); + void initLinkAndPreviewMenu(QAction *p_before, QMenu *p_menu, const QPoint &p_pos); + + bool initInPlacePreviewMenu(QAction *p_before, + QMenu *p_menu, + const QTextBlock &p_block, + int p_pos); void insertImageLink(const QString &p_text, const QString &p_url); diff --git a/src/vtextblockdata.h b/src/vtextblockdata.h index 26e6de10..8043cb4a 100644 --- a/src/vtextblockdata.h +++ b/src/vtextblockdata.h @@ -68,6 +68,11 @@ struct VPreviewedImageInfo return !(m_endPos <= a.m_startPos || m_startPos >= a.m_endPos); } + bool contains(int p_positionInBlock) const + { + return p_positionInBlock >= m_startPos && p_positionInBlock < m_endPos; + } + QString toString() const { return QString("previewed image (%1): [%2, %3] padding %4 inline %5 (%6,%7) bg(%8)") diff --git a/src/vtextedit.cpp b/src/vtextedit.cpp index 2b664076..18315280 100644 --- a/src/vtextedit.cpp +++ b/src/vtextedit.cpp @@ -362,6 +362,11 @@ QSize VTextEdit::imageSize(const QString &p_imageName) const return QSize(); } +const QPixmap *VTextEdit::findImage(const QString &p_name) const +{ + return m_imageMgr->findImage(p_name); +} + void VTextEdit::addImage(const QString &p_imageName, const QPixmap &p_image) { if (m_blockImageEnabled) { diff --git a/src/vtextedit.h b/src/vtextedit.h index 6db3841e..9eef9fa8 100644 --- a/src/vtextedit.h +++ b/src/vtextedit.h @@ -49,6 +49,9 @@ public: // Get the image size from the resource manager. QSize imageSize(const QString &p_imageName) const; + // Get the image from the resource manager. + const QPixmap *findImage(const QString &p_name) const; + // Add an image to the resources. void addImage(const QString &p_imageName, const QPixmap &p_image);