From e38ec22263c0d44e3130ad6663a80e91c35f3a6f Mon Sep 17 00:00:00 2001 From: Le Tan Date: Fri, 16 Mar 2018 21:38:53 +0800 Subject: [PATCH] editor: add PasteAsBlockQuote menu action --- src/utils/veditutils.cpp | 26 ++++++++++++++++++ src/utils/veditutils.h | 6 ++++ src/vmdeditor.cpp | 59 +++++++++++++++++++++++++++++++++++----- src/vmdeditor.h | 2 ++ 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/src/utils/veditutils.cpp b/src/utils/veditutils.cpp index 7dcab885..b36a8f53 100644 --- a/src/utils/veditutils.cpp +++ b/src/utils/veditutils.cpp @@ -962,3 +962,29 @@ void VEditUtils::insertBlock(QTextCursor &p_cursor, p_cursor.movePosition(QTextCursor::EndOfBlock); } + +void VEditUtils::insertBeforeEachLine(QString &p_text, const QString &p_str) +{ + int pos = 0; + while (pos < p_text.size()) { + int idx = p_text.indexOf("\n", pos); + if (idx == -1) { + break; + } + + ++idx; + if (idx == p_text.size()) { + break; + } + + p_text.insert(idx, p_str); + pos = idx + p_str.size(); + } + + p_text.prepend(p_str); +} + +bool VEditUtils::isEmptyBlock(const QTextBlock &p_block) +{ + return p_block.length() == 1; +} diff --git a/src/utils/veditutils.h b/src/utils/veditutils.h index 175bac85..112b2699 100644 --- a/src/utils/veditutils.h +++ b/src/utils/veditutils.h @@ -189,6 +189,12 @@ public: static void insertBlock(QTextCursor &p_cursor, bool p_above); + // Insert @p_str in the front of each line of @p_text. + static void insertBeforeEachLine(QString &p_text, const QString &p_str); + + // Whether @p_block is empty. + static bool isEmptyBlock(const QTextBlock &p_block); + private: VEditUtils() {} }; diff --git a/src/vmdeditor.cpp b/src/vmdeditor.cpp index ad189bc3..8f42d23f 100644 --- a/src/vmdeditor.cpp +++ b/src/vmdeditor.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "vdocument.h" #include "utils/veditutils.h" @@ -272,7 +274,7 @@ void VMdEditor::makeBlockVisible(const QTextBlock &p_block) void VMdEditor::contextMenuEvent(QContextMenuEvent *p_event) { - QMenu *menu = createStandardContextMenu(); + QScopedPointer menu(createStandardContextMenu()); menu->setToolTipsVisible(true); VEditTab *editTab = dynamic_cast(parent()); @@ -281,11 +283,11 @@ void VMdEditor::contextMenuEvent(QContextMenuEvent *p_event) const QList actions = menu->actions(); if (textCursor().hasSelection()) { - initCopyAsMenu(actions.isEmpty() ? NULL : actions.last(), menu); + initCopyAsMenu(actions.isEmpty() ? NULL : actions.last(), menu.data()); } else { QAction *saveExitAct = new QAction(VIconUtils::menuIcon(":/resources/icons/save_exit.svg"), tr("&Save Changes And Read"), - menu); + menu.data()); saveExitAct->setToolTip(tr("Save changes and exit edit mode")); connect(saveExitAct, &QAction::triggered, this, [this]() { @@ -294,7 +296,7 @@ void VMdEditor::contextMenuEvent(QContextMenuEvent *p_event) QAction *discardExitAct = new QAction(VIconUtils::menuIcon(":/resources/icons/discard_exit.svg"), tr("&Discard Changes And Read"), - menu); + menu.data()); discardExitAct->setToolTip(tr("Discard changes and exit edit mode")); connect(discardExitAct, &QAction::triggered, this, [this]() { @@ -303,15 +305,20 @@ void VMdEditor::contextMenuEvent(QContextMenuEvent *p_event) menu->insertAction(actions.isEmpty() ? NULL : actions[0], discardExitAct); menu->insertAction(discardExitAct, saveExitAct); + + if (!actions.isEmpty()) { + menu->insertSeparator(actions[0]); + } } - if (!actions.isEmpty()) { - menu->insertSeparator(actions[0]); + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); + if (mimeData->hasText()) { + initPasteAsBlockQuoteMenu(menu.data()); } } menu->exec(p_event->globalPos()); - delete menu; } void VMdEditor::mousePressEvent(QMouseEvent *p_event) @@ -1219,6 +1226,44 @@ void VMdEditor::initCopyAsMenu(QAction *p_before, QMenu *p_menu) } } +void VMdEditor::initPasteAsBlockQuoteMenu(QMenu *p_menu) +{ + QAction *pbqAct = new QAction(tr("Paste As Block &Quote"), p_menu); + pbqAct->setToolTip(tr("Paste text from clipboard as block quote")); + connect(pbqAct, &QAction::triggered, + this, [this]() { + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); + QString text = mimeData->text(); + + QTextCursor cursor = textCursor(); + cursor.removeSelectedText(); + QTextBlock block = cursor.block(); + QString indent = VEditUtils::fetchIndentSpaces(block); + + // Insert '> ' in front of each line. + VEditUtils::insertBeforeEachLine(text, indent + QStringLiteral("> ")); + + if (VEditUtils::isSpaceBlock(block)) { + if (!indent.isEmpty()) { + // Remove the indent. + cursor.movePosition(QTextCursor::StartOfBlock); + cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + cursor.removeSelectedText(); + } + } else { + // Insert a new block. + VEditUtils::insertBlock(cursor, false); + } + + cursor.insertText(text); + setTextCursor(cursor); + }); + + p_menu->addSeparator(); + p_menu->addAction(pbqAct); +} + void VMdEditor::insertImageLink(const QString &p_text, const QString &p_url) { VInsertLinkDialog dialog(tr("Insert Image Link"), diff --git a/src/vmdeditor.h b/src/vmdeditor.h index aa77d6ef..0aeb33d8 100644 --- a/src/vmdeditor.h +++ b/src/vmdeditor.h @@ -236,6 +236,8 @@ private: void initCopyAsMenu(QAction *p_before, QMenu *p_menu); + void initPasteAsBlockQuoteMenu(QMenu *p_menu); + void insertImageLink(const QString &p_text, const QString &p_url); HGMarkdownHighlighter *m_mdHighlighter;