diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini
index 93e574d8..3e9785f3 100644
--- a/src/resources/vnote.ini
+++ b/src/resources/vnote.ini
@@ -20,10 +20,16 @@ enable_mermaid=false
enable_mathjax=false
; -1 - calculate the factor
web_zoom_factor=-1
+
; Syntax highlight within code blocks in edit mode
enable_code_block_highlight=true
+
+; Enable image preview in edit mode
enable_preview_images=true
+; Enable image preview constraint in edit mode to constrain the widht of the preview
+enable_preview_image_constraint=false
+
[session]
tools_dock_checked=true
diff --git a/src/translations/vnote_zh_CN.qm b/src/translations/vnote_zh_CN.qm
index a237559f..f390e172 100644
Binary files a/src/translations/vnote_zh_CN.qm and b/src/translations/vnote_zh_CN.qm differ
diff --git a/src/translations/vnote_zh_CN.ts b/src/translations/vnote_zh_CN.ts
index 7de4d36c..8cc39c8f 100644
--- a/src/translations/vnote_zh_CN.ts
+++ b/src/translations/vnote_zh_CN.ts
@@ -694,7 +694,7 @@
-
+
&Edit
编辑 (&E)
@@ -789,229 +789,239 @@
编辑模式中启用图片预览
-
+
+ Constrain The Width Of Previewed Images
+ 限制预览图片宽度
+
+
+
+ Constrain the width of previewed images to the edit window in edit mode
+ 编辑模式中根据编辑窗口大小限制预览图片的宽度
+
+
+
&View
查看 (&V)
-
+
&File
文件 (&F)
-
+
&Import Notes From Files
导入文件 (&I)
-
+
Import notes from files into current directory
从文件中导入笔记到当前目录
-
+
Settings
设置
-
+
View and change settings for VNote
查看并更改VNote的配置
-
+
Exit
退出
-
+
Exit VNote
退出VNote
-
+
Insert &Image
插入图片 (&I)
-
-
+
+
Find/Replace
查找/替换
-
+
Open Find/Replace dialog to search in current note
打开查找/替换对话框以在当前笔记中查找
-
+
Find Next
查找下一个
-
+
Find next occurence
查找下一处出现
-
+
Find Previous
查找上一个
-
+
Find previous occurence
查找上一处出现
-
+
Replace
替换
-
+
Replace current occurence
替换当前出现
-
+
Replace && Find
替换并查找
-
+
Replace current occurence and find the next one
替换当前出现并查找下一个
-
+
Replace All
全部替换
-
+
Replace all occurences in current note
替换当前笔记中的所有出现
-
+
Highlight Searched Pattern
高亮查找模式
-
+
Highlight all occurences of searched pattern
高亮查找模式的所有出现
-
+
&Expand Tab
扩展Tab (&E)
-
+
Expand entered Tab to spaces
将输入的Tab扩展为空格
-
+
Expand Tab to 2 spaces
扩展Tab为2个空格
-
+
Expand Tab to 4 spaces
扩展Tab为4个空格
-
+
Expand Tab to 8 spaces
扩展Tab为8个空格
-
+
Auto Indent
自动缩进
-
+
Indent automatically when inserting a new line
插入新行时自动缩进
-
+
Auto List
自动列表
-
+
Continue the list automatically when inserting a new line
插入新行时自动继续列表
-
+
Highlight Selected Words
高亮选定字词
-
+
Highlight all occurences of selected words
高亮选定字词的所有出现
-
+
Select Files (HTML or Markdown) To Import
选择需要导入的文件(HTML或Markdown)
-
+
Import Notes From File
导入文件
-
+
Imported notes: %1 succeed, %2 failed.
已导入笔记: %1 成功, %2 失败。
-
+
Use system's background color configuration for Markdown rendering
使用系统的背景色设置对Markdown进行渲染
-
+
Set as the background color for Markdown rendering
使用该背景色对Markdown进行渲染
-
-
+
+
&Add Style
添加样式 (&A)
-
+
Open the folder to add your custom CSS style files
打开样式文件夹以添加自定义CSS样式文件
-
+
Editor &Style
编辑器样式 (&S)
-
+
Open the folder to add your custom MDHL style files
打开样式文件夹以添加自定义MDHL样式文件
-
+
Set as the editor style
使用该样式设置编辑器
-
+
2 Spaces
2个空格
@@ -1086,103 +1096,103 @@
编辑模式中启用代码块语法高亮
-
+
Insert an image from file into current note
从文件中插入图片到当前笔记
-
+
4 Spaces
4个空格
-
+
8 Spaces
8个空格
-
+
Highlight Cursor Line
高亮光标所在行
-
+
Highlight current cursor line
高亮当前光标所在行
-
+
Tab Stop Width
Tab Stop宽度
-
+
Tools
工具
-
+
Outline
大纲
-
+
Fail to import files maybe due to name conflicts.
导入文件失败 (可能是因为名字冲突)。
-
+
v%1
v %1
-
+
VNote is a Vim-inspired note-taking application for Markdown.
VNote是一个受Vim启发而开发的专注于Markdown的笔记软件。
-
+
Visit https://github.com/tamlok/vnote.git for more information.
更多信息请访问 https://github.com/tamlok/vnote.git。
-
+
About VNote
关于VNote
-
+
&Rendering Background
渲染背景 (&R)
-
-
+
+
System
默认
-
+
Rendering &Style
渲染样式 (&S)
-
+
Set as the CSS style for Markdown rendering
使用该CSS样式对Markdown进行渲染
-
+
&Background Color
背景颜色 (&B)
-
+
Use system's background color configuration for editor
为编辑器使用系统的背景色设置
-
+
Set as the background color for editor
使用该背景色设置编辑器
diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp
index ba219966..be0387d5 100644
--- a/src/vconfigmanager.cpp
+++ b/src/vconfigmanager.cpp
@@ -126,6 +126,9 @@ void VConfigManager::initialize()
m_enablePreviewImages = getConfigFromSettings("global",
"enable_preview_images").toBool();
+
+ m_enablePreviewImageConstraint = getConfigFromSettings("global",
+ "enable_preview_image_constraint").toBool();
}
void VConfigManager::readPredefinedColorsFromSettings()
diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h
index 35e70edc..54cf483a 100644
--- a/src/vconfigmanager.h
+++ b/src/vconfigmanager.h
@@ -160,6 +160,9 @@ public:
inline bool getEnablePreviewImages() const;
inline void setEnablePreviewImages(bool p_enabled);
+ inline bool getEnablePreviewImageConstraint() const;
+ inline void setEnablePreviewImageConstraint(bool p_enabled);
+
// Get the folder the ini file exists.
QString getConfigFolder() const;
@@ -270,6 +273,9 @@ private:
// Preview images in edit mode.
bool m_enablePreviewImages;
+ // Constrain the width of image preview in edit mode.
+ bool m_enablePreviewImageConstraint;
+
// The name of the config file in each directory, obsolete.
// Use c_dirConfigFile instead.
static const QString c_obsoleteDirConfigFile;
@@ -711,4 +717,20 @@ inline void VConfigManager::setEnablePreviewImages(bool p_enabled)
m_enablePreviewImages);
}
+inline bool VConfigManager::getEnablePreviewImageConstraint() const
+{
+ return m_enablePreviewImageConstraint;
+}
+
+inline void VConfigManager::setEnablePreviewImageConstraint(bool p_enabled)
+{
+ if (m_enablePreviewImageConstraint == p_enabled) {
+ return;
+ }
+
+ m_enablePreviewImageConstraint = p_enabled;
+ setConfigToSettings("global", "enable_preview_image_constraint",
+ m_enablePreviewImageConstraint);
+}
+
#endif // VCONFIGMANAGER_H
diff --git a/src/vimagepreviewer.cpp b/src/vimagepreviewer.cpp
index 4510199d..5f1cff59 100644
--- a/src/vimagepreviewer.cpp
+++ b/src/vimagepreviewer.cpp
@@ -15,10 +15,13 @@ extern VConfigManager vconfig;
enum ImageProperty { ImagePath = 1 };
+const int VImagePreviewer::c_minImageWidth = 100;
+
VImagePreviewer::VImagePreviewer(VMdEdit *p_edit, int p_timeToPreview)
: QObject(p_edit), m_edit(p_edit), m_document(p_edit->document()),
m_file(p_edit->getFile()), m_enablePreview(true), m_isPreviewing(false),
- m_requestCearBlocks(false), m_requestRefreshBlocks(false)
+ m_requestCearBlocks(false), m_requestRefreshBlocks(false),
+ m_updatePending(false), m_imageWidth(c_minImageWidth)
{
m_timer = new QTimer(this);
m_timer->setSingleShot(true);
@@ -49,6 +52,11 @@ void VImagePreviewer::timerTimeout()
return;
}
+ if (m_isPreviewing) {
+ m_updatePending = true;
+ return;
+ }
+
previewImages();
}
@@ -70,6 +78,9 @@ void VImagePreviewer::previewImages()
return;
}
+ // Get the width of the m_edit.
+ m_imageWidth = qMax(m_edit->size().width() - 50, c_minImageWidth);
+
m_isPreviewing = true;
QTextBlock block = m_document->begin();
while (block.isValid() && m_enablePreview) {
@@ -101,6 +112,12 @@ void VImagePreviewer::previewImages()
refresh();
}
+ if (m_updatePending) {
+ m_updatePending = false;
+ m_timer->stop();
+ m_timer->start();
+ }
+
emit m_edit->statusChanged();
}
@@ -224,6 +241,9 @@ QTextBlock VImagePreviewer::insertImagePreviewBlock(QTextBlock &p_block,
QTextImageFormat imgFormat;
imgFormat.setName(imageName);
imgFormat.setProperty(ImagePath, p_imagePath);
+
+ updateImageWidth(imgFormat);
+
cursor.insertImage(imgFormat);
cursor.endEditBlock();
@@ -240,13 +260,18 @@ void VImagePreviewer::updateImagePreviewBlock(QTextBlock &p_block,
QTextImageFormat format = fetchFormatFromPreviewBlock(p_block);
V_ASSERT(format.isValid());
QString curPath = format.property(ImagePath).toString();
+ QString imageName;
if (curPath == p_imagePath) {
+ if (updateImageWidth(format)) {
+ goto update;
+ }
+
return;
}
// Update it with the new image.
- QString imageName = imageCacheResourceName(p_imagePath);
+ imageName = imageCacheResourceName(p_imagePath);
if (imageName.isEmpty()) {
// Delete current preview block.
removeBlock(p_block);
@@ -255,6 +280,10 @@ void VImagePreviewer::updateImagePreviewBlock(QTextBlock &p_block,
format.setName(imageName);
format.setProperty(ImagePath, p_imagePath);
+
+ updateImageWidth(format);
+
+update:
updateFormatInPreviewBlock(p_block, format);
}
@@ -391,7 +420,10 @@ QTextImageFormat VImagePreviewer::fetchFormatFromPreviewBlock(QTextBlock &p_bloc
void VImagePreviewer::updateFormatInPreviewBlock(QTextBlock &p_block,
const QTextImageFormat &p_format)
{
+ bool modified = m_edit->isModified();
+
QTextCursor cursor(p_block);
+ cursor.beginEditBlock();
int shift = p_block.text().indexOf(QChar::ObjectReplacementCharacter);
if (shift > 0) {
cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, shift);
@@ -403,6 +435,9 @@ void VImagePreviewer::updateFormatInPreviewBlock(QTextBlock &p_block,
V_ASSERT(cursor.charFormat().toImageFormat().isValid());
cursor.setCharFormat(p_format);
+ cursor.endEditBlock();
+
+ m_edit->setModified(modified);
}
QString VImagePreviewer::imageCacheResourceName(const QString &p_imagePath)
@@ -411,7 +446,7 @@ QString VImagePreviewer::imageCacheResourceName(const QString &p_imagePath)
auto it = m_imageCache.find(p_imagePath);
if (it != m_imageCache.end()) {
- return it.value();
+ return it.value().m_name;
}
// Add it to the resource cache even if it may exist there.
@@ -431,7 +466,7 @@ QString VImagePreviewer::imageCacheResourceName(const QString &p_imagePath)
QString name(imagePathToCacheResourceName(p_imagePath));
m_document->addResource(QTextDocument::ImageResource, name, image);
- m_imageCache.insert(p_imagePath, name);
+ m_imageCache.insert(p_imagePath, ImageInfo(name, image.width()));
return name;
}
@@ -454,7 +489,7 @@ void VImagePreviewer::imageDownloaded(const QByteArray &p_data, const QString &p
m_timer->stop();
QString name(imagePathToCacheResourceName(p_url));
m_document->addResource(QTextDocument::ImageResource, name, image);
- m_imageCache.insert(p_url, name);
+ m_imageCache.insert(p_url, ImageInfo(name, image.width()));
qDebug() << "downloaded image cache insert" << p_url << name;
@@ -487,5 +522,31 @@ QImage VImagePreviewer::fetchCachedImageFromPreviewBlock(QTextBlock &p_block)
return QImage();
}
- return m_document->resource(QTextDocument::ImageResource, it.value()).value();
+ return m_document->resource(QTextDocument::ImageResource, it.value().m_name).value();
+}
+
+bool VImagePreviewer::updateImageWidth(QTextImageFormat &p_format)
+{
+ QString path = p_format.property(ImagePath).toString();
+ auto it = m_imageCache.find(path);
+
+ if (it != m_imageCache.end()) {
+ int newWidth = it.value().m_width;
+ if (vconfig.getEnablePreviewImageConstraint()) {
+ newWidth = qMin(m_imageWidth, it.value().m_width);
+ }
+
+ if (newWidth != p_format.width()) {
+ p_format.setWidth(newWidth);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void VImagePreviewer::update()
+{
+ m_timer->stop();
+ m_timer->start();
}
diff --git a/src/vimagepreviewer.h b/src/vimagepreviewer.h
index 7620ee93..afd17adc 100644
--- a/src/vimagepreviewer.h
+++ b/src/vimagepreviewer.h
@@ -30,12 +30,25 @@ public:
// Then re-preview all the blocks.
void refresh();
+ void update();
+
private slots:
void timerTimeout();
void handleContentChange(int p_position, int p_charsRemoved, int p_charsAdded);
void imageDownloaded(const QByteArray &p_data, const QString &p_url);
private:
+ struct ImageInfo
+ {
+ ImageInfo(const QString &p_name, int p_width)
+ : m_name(p_name), m_width(p_width)
+ {
+ }
+
+ QString m_name;
+ int m_width;
+ };
+
void previewImages();
bool isValidImagePreviewBlock(QTextBlock &p_block);
@@ -77,6 +90,9 @@ private:
QString imagePathToCacheResourceName(const QString &p_imagePath);
+ // Return true if and only if there is update.
+ bool updateImageWidth(QTextImageFormat &p_format);
+
VMdEdit *m_edit;
QTextDocument *m_document;
VFile *m_file;
@@ -85,11 +101,17 @@ private:
bool m_isPreviewing;
bool m_requestCearBlocks;
bool m_requestRefreshBlocks;
+ bool m_updatePending;
// Map from image full path to QUrl identifier in the QTextDocument's cache.
- QHash m_imageCache;;
+ QHash m_imageCache;;
VDownloader *m_downloader;
+
+ // The preview width.
+ int m_imageWidth;
+
+ static const int c_minImageWidth;
};
#endif // VIMAGEPREVIEWER_H
diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp
index 50b87689..b0e41e3e 100644
--- a/src/vmainwindow.cpp
+++ b/src/vmainwindow.cpp
@@ -390,6 +390,14 @@ void VMainWindow::initMarkdownMenu()
// TODO: add the action to the menu after handling the UNDO history well.
// markdownMenu->addAction(previewImageAct);
previewImageAct->setChecked(vconfig.getEnablePreviewImages());
+
+ QAction *previewWidthAct = new QAction(tr("Constrain The Width Of Previewed Images"), this);
+ previewWidthAct->setToolTip(tr("Constrain the width of previewed images to the edit window in edit mode"));
+ previewWidthAct->setCheckable(true);
+ connect(previewWidthAct, &QAction::triggered,
+ this, &VMainWindow::enableImagePreviewConstraint);
+ markdownMenu->addAction(previewWidthAct);
+ previewWidthAct->setChecked(vconfig.getEnablePreviewImageConstraint());
}
void VMainWindow::initViewMenu()
@@ -1288,6 +1296,11 @@ void VMainWindow::enableImagePreview(bool p_checked)
vconfig.setEnablePreviewImages(p_checked);
}
+void VMainWindow::enableImagePreviewConstraint(bool p_checked)
+{
+ vconfig.setEnablePreviewImageConstraint(p_checked);
+}
+
void VMainWindow::shortcutHelp()
{
QString locale = VUtils::getLocale();
diff --git a/src/vmainwindow.h b/src/vmainwindow.h
index 9f4a555b..530e84ef 100644
--- a/src/vmainwindow.h
+++ b/src/vmainwindow.h
@@ -77,6 +77,7 @@ private slots:
void changeAutoList(bool p_checked);
void enableCodeBlockHighlight(bool p_checked);
void enableImagePreview(bool p_checked);
+ void enableImagePreviewConstraint(bool p_checked);
protected:
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
diff --git a/src/vmdedit.cpp b/src/vmdedit.cpp
index 8470ff54..3101ebea 100644
--- a/src/vmdedit.cpp
+++ b/src/vmdedit.cpp
@@ -387,3 +387,10 @@ QImage VMdEdit::selectedImage()
}
return image;
}
+
+void VMdEdit::resizeEvent(QResizeEvent *p_event)
+{
+ m_imagePreviewer->update();
+
+ VEdit::resizeEvent(p_event);
+}
diff --git a/src/vmdedit.h b/src/vmdedit.h
index b1e0ddec..7358acaf 100644
--- a/src/vmdedit.h
+++ b/src/vmdedit.h
@@ -52,6 +52,7 @@ protected:
bool canInsertFromMimeData(const QMimeData *source) const Q_DECL_OVERRIDE;
void insertFromMimeData(const QMimeData *source) Q_DECL_OVERRIDE;
void updateFontAndPalette() Q_DECL_OVERRIDE;
+ void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE;
private:
void initInitImages();