MdEditor: support copy in-place preview

This commit is contained in:
Le Tan 2018-08-19 12:06:50 +08:00
parent f98c2f5382
commit 1ce8c05da9
7 changed files with 126 additions and 36 deletions

View File

@ -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)

View File

@ -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,

View File

@ -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<VPreviewInfo *> &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;
}

View File

@ -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);

View File

@ -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)")

View File

@ -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) {

View File

@ -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);