Просмотр исходного кода

MdEditor: support copy in-place preview

Le Tan 7 лет назад
Родитель
Сommit
1ce8c05da9
7 измененных файлов с 124 добавлено и 34 удалено
  1. 14 0
      src/utils/vclipboardutils.cpp
  2. 5 0
      src/utils/vclipboardutils.h
  3. 86 33
      src/vmdeditor.cpp
  4. 6 1
      src/vmdeditor.h
  5. 5 0
      src/vtextblockdata.h
  6. 5 0
      src/vtextedit.cpp
  7. 3 0
      src/vtextedit.h

+ 14 - 0
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)

+ 5 - 0
src/utils/vclipboardutils.h

@@ -2,6 +2,7 @@
 #define VCLIPBOARDUTILS_H
 
 #include <QImage>
+#include <QPixmap>
 #include <QClipboard>
 
 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,

+ 86 - 33
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);
+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;
+    }
 
-    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);
+    const QVector<VPreviewInfo *> &previews = data->getPreviews();
+    if (previews.isEmpty()) {
+        return false;
+    }
 
-    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);
+    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;
+        }
     }
 
-    p_menu->insertSeparator(p_before ? p_before : NULL);
+    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;
 }

+ 6 - 1
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);
 

+ 5 - 0
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)")

+ 5 - 0
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) {

+ 3 - 0
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);