Editor: support auto scrolling cursor line into center

This commit is contained in:
Le Tan 2018-10-30 20:47:41 +08:00
parent f3ff862cfb
commit aeb2263be3
15 changed files with 293 additions and 81 deletions

View File

@ -299,6 +299,17 @@ enable_tab_highlight=false
; Download images in parsed HTML text
parse_paste_local_image=true
; Enable extra buffer at the bottom of the editor to avoid placing
; cursor at the bottom
enable_extra_buffer=true
; Auto scroll cursor line when it is at the bottom part of the content
; Need enable_extra_buffer to be enabled
; 0 - disabled
; 1 - end of doc
; 2 - always
auto_scroll_cursor_line=1
[export]
; Path of the wkhtmltopdf tool
wkhtmltopdf=wkhtmltopdf

View File

@ -406,7 +406,8 @@ int VEditUtils::selectedBlockCount(const QTextCursor &p_cursor)
void VEditUtils::scrollBlockInPage(QTextEdit *p_edit,
int p_blockNum,
int p_dest)
int p_dest,
int p_margin)
{
QTextDocument *doc = p_edit->document();
QTextCursor cursor = p_edit->textCursor();
@ -416,9 +417,9 @@ void VEditUtils::scrollBlockInPage(QTextEdit *p_edit,
QTextBlock block = doc->findBlockByNumber(p_blockNum);
int pib = cursor.positionInBlock();
if (cursor.block().blockNumber() != p_blockNum) {
// Move the cursor to the block.
int pib = cursor.positionInBlock();
if (pib >= block.length()) {
pib = block.length() - 1;
}
@ -427,15 +428,20 @@ void VEditUtils::scrollBlockInPage(QTextEdit *p_edit,
p_edit->setTextCursor(cursor);
}
// Scroll to let current cursor locate in proper position.
p_edit->ensureCursorVisible();
QScrollBar *vsbar = p_edit->verticalScrollBar();
if (!vsbar || !vsbar->isVisible()) {
// No vertical scrollbar. No need to scroll.
return;
}
int sstep = vsbar->singleStep();
if (p_margin < sstep) {
p_margin = sstep;
}
// Scroll to let current cursor locate in proper position.
p_edit->ensureCursorVisible();
QRect rect = p_edit->cursorRect();
int height = p_edit->rect().height();
QScrollBar *sbar = p_edit->horizontalScrollBar();
@ -443,13 +449,15 @@ void VEditUtils::scrollBlockInPage(QTextEdit *p_edit,
height -= sbar->height();
}
bool moved = false;
switch (p_dest) {
case 0:
{
// Top.
while (rect.y() > 0 && vsbar->value() < vsbar->maximum()) {
vsbar->setValue(vsbar->value() + vsbar->singleStep());
while (rect.y() > p_margin && vsbar->value() < vsbar->maximum()) {
vsbar->setValue(vsbar->value() + sstep);
rect = p_edit->cursorRect();
moved = true;
}
break;
@ -459,15 +467,19 @@ void VEditUtils::scrollBlockInPage(QTextEdit *p_edit,
{
// Center.
height = qMax(height / 2, 1);
if (rect.y() > height) {
while (rect.y() > height && vsbar->value() < vsbar->maximum()) {
vsbar->setValue(vsbar->value() + vsbar->singleStep());
int upBound = height + p_margin;
int lowBound = height - p_margin;
if (rect.y() > upBound) {
while (rect.y() > upBound && vsbar->value() < vsbar->maximum()) {
vsbar->setValue(vsbar->value() + sstep);
rect = p_edit->cursorRect();
moved = true;
}
} else if (rect.y() < height) {
while (rect.y() < height && vsbar->value() > vsbar->minimum()) {
vsbar->setValue(vsbar->value() - vsbar->singleStep());
} else if (rect.y() < lowBound) {
while (rect.y() < lowBound && vsbar->value() > vsbar->minimum()) {
vsbar->setValue(vsbar->value() - sstep);
rect = p_edit->cursorRect();
moved = true;
}
}
@ -475,24 +487,31 @@ void VEditUtils::scrollBlockInPage(QTextEdit *p_edit,
}
case 2:
{
// Bottom.
while (rect.y() < height && vsbar->value() > vsbar->minimum()) {
vsbar->setValue(vsbar->value() - vsbar->singleStep());
int lowBound = height - p_margin;
while (rect.y() < lowBound && vsbar->value() > vsbar->minimum()) {
vsbar->setValue(vsbar->value() - sstep);
rect = p_edit->cursorRect();
moved = true;
}
break;
}
default:
break;
}
if (moved) {
p_edit->ensureCursorVisible();
}
}
void VEditUtils::scrollBlockInPage(QPlainTextEdit *p_edit,
int p_blockNum,
int p_dest)
int p_dest,
int p_margin)
{
QTextDocument *doc = p_edit->document();
QTextCursor cursor = p_edit->textCursor();
@ -502,9 +521,9 @@ void VEditUtils::scrollBlockInPage(QPlainTextEdit *p_edit,
QTextBlock block = doc->findBlockByNumber(p_blockNum);
int pib = cursor.positionInBlock();
if (cursor.block().blockNumber() != p_blockNum) {
// Move the cursor to the block.
int pib = cursor.positionInBlock();
if (pib >= block.length()) {
pib = block.length() - 1;
}
@ -513,15 +532,20 @@ void VEditUtils::scrollBlockInPage(QPlainTextEdit *p_edit,
p_edit->setTextCursor(cursor);
}
// Scroll to let current cursor locate in proper position.
p_edit->ensureCursorVisible();
QScrollBar *vsbar = p_edit->verticalScrollBar();
if (!vsbar || !vsbar->isVisible()) {
// No vertical scrollbar. No need to scroll.
return;
}
int sstep = vsbar->singleStep();
if (p_margin < sstep) {
p_margin = sstep;
}
// Scroll to let current cursor locate in proper position.
p_edit->ensureCursorVisible();
QRect rect = p_edit->cursorRect();
int height = p_edit->rect().height();
QScrollBar *sbar = p_edit->horizontalScrollBar();
@ -529,12 +553,13 @@ void VEditUtils::scrollBlockInPage(QPlainTextEdit *p_edit,
height -= sbar->height();
}
bool moved = false;
switch (p_dest) {
case 0:
{
// Top.
while (rect.y() > 0 && vsbar->value() < vsbar->maximum()) {
vsbar->setValue(vsbar->value() + vsbar->singleStep());
while (rect.y() > p_margin && vsbar->value() < vsbar->maximum()) {
vsbar->setValue(vsbar->value() + sstep);
rect = p_edit->cursorRect();
}
@ -545,15 +570,19 @@ void VEditUtils::scrollBlockInPage(QPlainTextEdit *p_edit,
{
// Center.
height = qMax(height / 2, 1);
if (rect.y() > height) {
while (rect.y() > height && vsbar->value() < vsbar->maximum()) {
vsbar->setValue(vsbar->value() + vsbar->singleStep());
int upBound = height + p_margin;
int lowBound = height - p_margin;
if (rect.y() > upBound) {
while (rect.y() > upBound && vsbar->value() < vsbar->maximum()) {
vsbar->setValue(vsbar->value() + sstep);
rect = p_edit->cursorRect();
moved = true;
}
} else if (rect.y() < height) {
while (rect.y() < height && vsbar->value() > vsbar->minimum()) {
vsbar->setValue(vsbar->value() - vsbar->singleStep());
} else if (rect.y() < lowBound) {
while (rect.y() < lowBound && vsbar->value() > vsbar->minimum()) {
vsbar->setValue(vsbar->value() - sstep);
rect = p_edit->cursorRect();
moved = true;
}
}
@ -561,20 +590,26 @@ void VEditUtils::scrollBlockInPage(QPlainTextEdit *p_edit,
}
case 2:
{
// Bottom.
while (rect.y() < height && vsbar->value() > vsbar->minimum()) {
vsbar->setValue(vsbar->value() - vsbar->singleStep());
int lowBound = height - p_margin;
while (rect.y() < lowBound && vsbar->value() > vsbar->minimum()) {
vsbar->setValue(vsbar->value() - sstep);
rect = p_edit->cursorRect();
moved = true;
}
break;
}
default:
break;
}
if (moved) {
p_edit->ensureCursorVisible();
}
}
bool VEditUtils::isBlockQuoteBlock(const QTextBlock &p_block)
{

View File

@ -129,7 +129,8 @@ public:
// Will set the cursor to the block.
static void scrollBlockInPage(QTextEdit *p_edit,
int p_blockNum,
int p_dest);
int p_dest,
int p_margin = 0);
// Scroll block @p_blockNum into the visual window.
// @p_dest is the position of the window: 0 for top, 1 for center, 2 for bottom.
@ -137,7 +138,8 @@ public:
// Will set the cursor to the block.
static void scrollBlockInPage(QPlainTextEdit *p_edit,
int p_blockNum,
int p_dest);
int p_dest,
int p_margin = 0);
// Check if @p_block is a auto list block.
// @p_seq will be the seq number of the ordered list, or -1.

View File

@ -361,6 +361,10 @@ void VConfigManager::initEditorConfigs()
"enable_tab_highlight").toBool();
m_parsePasteLocalImage = getConfigFromSettings("editor", "parse_paste_local_image").toBool();
m_enableExtraBuffer = getConfigFromSettings("editor", "enable_extra_buffer").toBool();
m_autoScrollCursorLine = getConfigFromSettings("editor", "auto_scroll_cursor_line").toInt();
}
void VConfigManager::initSettings()

View File

@ -67,6 +67,13 @@ enum SmartLivePreview
WebToEditor = 0x2
};
enum
{
AutoScrollDisabled = 0,
AutoScrollEndOfDoc = 1,
AutoScrollAlways = 2
};
class VConfigManager : public QObject
{
public:
@ -587,6 +594,11 @@ public:
const QColor &getBaseBackground() const;
void setBaseBackground(const QColor &p_bg);
bool getEnableExtraBuffer() const;
int getAutoScrollCursorLine() const;
void setAutoScrollCursorLine(int p_mode);
private:
// Look up a config from user and default settings.
QVariant getConfigFromSettings(const QString &section, const QString &key) const;
@ -1050,6 +1062,16 @@ private:
// Base background of MainWindow.
QColor m_baseBackground;
// Whether enable extra buffer at the bottom of editor.
bool m_enableExtraBuffer;
// Whether auto scroll cursor line to the middle of the window when
// cursor is at the bottom part of the content.
// 0 - disalbed
// 1 - end of doc
// 2 - always
int m_autoScrollCursorLine;
// The name of the config file in each directory.
static const QString c_dirConfigFile;
@ -2730,4 +2752,33 @@ inline void VConfigManager::setBaseBackground(const QColor &p_bg)
{
m_baseBackground = p_bg;
}
inline bool VConfigManager::getEnableExtraBuffer() const
{
return m_enableExtraBuffer;
}
inline int VConfigManager::getAutoScrollCursorLine() const
{
if (m_enableExtraBuffer) {
return m_autoScrollCursorLine;
} else {
return AutoScrollDisabled;
}
}
inline void VConfigManager::setAutoScrollCursorLine(int p_mode)
{
m_autoScrollCursorLine = p_mode;
if (p_mode == AutoScrollDisabled) {
setConfigToSettings("editor", "auto_scroll_cursor_line", m_autoScrollCursorLine);
} else {
if (!m_enableExtraBuffer) {
m_enableExtraBuffer = true;
setConfigToSettings("editor", "enable_extra_buffer", m_enableExtraBuffer);
}
setConfigToSettings("editor", "auto_scroll_cursor_line", m_autoScrollCursorLine);
}
}
#endif // VCONFIGMANAGER_H

View File

@ -1705,3 +1705,39 @@ void VEditor::pastePlainText()
m_editOps->insertText(text);
}
void VEditor::scrollCursorLineIfNecessary()
{
bool moved = false;
QTextCursor cursor = textCursorW();
int mode = g_config->getAutoScrollCursorLine();
switch (mode) {
case AutoScrollEndOfDoc:
V_FALLTHROUGH;
case AutoScrollAlways:
{
const int bc = m_document->blockCount();
int bn = cursor.blockNumber();
int margin = -1;
if (mode == AutoScrollAlways) {
margin = m_editor->rect().height() / 8;
} else if (bn == bc - 1) {
margin = m_editor->rect().height() / 4;
}
if (margin > -1) {
moved = true;
scrollBlockInPage(bn, 1, margin);
}
break;
}
default:
break;
}
if (!moved) {
makeBlockVisible(cursor.block());
}
}

View File

@ -154,7 +154,7 @@ public:
// @p_dest is the position of the window: 0 for top, 1 for center, 2 for bottom.
// @p_blockNum is based on 0.
// Will set the cursor to the block.
virtual void scrollBlockInPage(int p_blockNum, int p_dest) = 0;
virtual void scrollBlockInPage(int p_blockNum, int p_dest, int p_margin = 0) = 0;
// Update config according to global configurations.
virtual void updateConfig();
@ -273,6 +273,9 @@ protected:
// Paste plain text.
void pastePlainText();
// Scroll cursor line if in need.
void scrollCursorLineIfNecessary();
QWidget *m_editor;
VEditorObject *m_object;

View File

@ -815,7 +815,7 @@ void VMainWindow::initHelpMenu()
QAction *docAct = new QAction(tr("&Documentation"), this);
docAct->setToolTip(tr("View VNote's documentation"));
connect(docAct, &QAction::triggered,
this, [this]() {
this, []() {
QString url("http://vnote.readthedocs.io");
QDesktopServices::openUrl(url);
});
@ -823,7 +823,7 @@ void VMainWindow::initHelpMenu()
QAction *donateAct = new QAction(tr("Do&nate"), this);
donateAct->setToolTip(tr("Donate to VNote or view the donate list"));
connect(donateAct, &QAction::triggered,
this, [this]() {
this, []() {
QString url("https://github.com/tamlok/vnote#donate");
QDesktopServices::openUrl(url);
});
@ -839,7 +839,7 @@ void VMainWindow::initHelpMenu()
QAction *starAct = new QAction(tr("Star VNote on &Github"), this);
starAct->setToolTip(tr("Give a star to VNote on Github project"));
connect(starAct, &QAction::triggered,
this, [this]() {
this, []() {
QString url("https://github.com/tamlok/vnote");
QDesktopServices::openUrl(url);
});
@ -847,7 +847,7 @@ void VMainWindow::initHelpMenu()
QAction *feedbackAct = new QAction(tr("&Feedback"), this);
feedbackAct->setToolTip(tr("Open an issue on Github"));
connect(feedbackAct, &QAction::triggered,
this, [this]() {
this, []() {
QString url("https://github.com/tamlok/vnote/issues");
QDesktopServices::openUrl(url);
});
@ -958,7 +958,7 @@ void VMainWindow::initMarkdownMenu()
lineNumberAct->setToolTip(tr("Enable line number in code blocks in read mode"));
lineNumberAct->setCheckable(true);
connect(lineNumberAct, &QAction::triggered,
this, [this](bool p_checked){
this, [](bool p_checked){
g_config->setEnableCodeBlockLineNumber(p_checked);
});
markdownMenu->addAction(lineNumberAct);
@ -1081,7 +1081,7 @@ void VMainWindow::initFileMenu()
QAction *openConfigAct = new QAction(tr("Open Configuration Folder"), this);
openConfigAct->setToolTip(tr("Open configuration folder of VNote"));
connect(openConfigAct, &QAction::triggered,
this, [this](){
this, [](){
QUrl url = QUrl::fromLocalFile(g_config->getConfigFolder());
QDesktopServices::openUrl(url);
});
@ -1247,7 +1247,7 @@ void VMainWindow::initEditMenu()
tabAct->setToolTip(tr("Highlight all the tabs"));
tabAct->setCheckable(true);
connect(tabAct, &QAction::triggered,
this, [this](bool p_checked) {
this, [](bool p_checked) {
g_config->setEnableTabHighlight(p_checked);
});
@ -1329,6 +1329,8 @@ void VMainWindow::initEditMenu()
editMenu->addAction(tabAct);
tabAct->setChecked(g_config->getEnableTabHighlight());
initAutoScrollCursorLineMenu(editMenu);
}
void VMainWindow::initDockWindows()
@ -1582,7 +1584,7 @@ void VMainWindow::initMarkdownitOptionMenu(QMenu *p_menu)
htmlAct->setCheckable(true);
htmlAct->setChecked(opt.m_html);
connect(htmlAct, &QAction::triggered,
this, [this](bool p_checked) {
this, [](bool p_checked) {
MarkdownitOption opt = g_config->getMarkdownitOption();
opt.m_html = p_checked;
g_config->setMarkdownitOption(opt);
@ -1593,7 +1595,7 @@ void VMainWindow::initMarkdownitOptionMenu(QMenu *p_menu)
breaksAct->setCheckable(true);
breaksAct->setChecked(opt.m_breaks);
connect(breaksAct, &QAction::triggered,
this, [this](bool p_checked) {
this, [](bool p_checked) {
MarkdownitOption opt = g_config->getMarkdownitOption();
opt.m_breaks = p_checked;
g_config->setMarkdownitOption(opt);
@ -1604,7 +1606,7 @@ void VMainWindow::initMarkdownitOptionMenu(QMenu *p_menu)
linkifyAct->setCheckable(true);
linkifyAct->setChecked(opt.m_linkify);
connect(linkifyAct, &QAction::triggered,
this, [this](bool p_checked) {
this, [](bool p_checked) {
MarkdownitOption opt = g_config->getMarkdownitOption();
opt.m_linkify = p_checked;
g_config->setMarkdownitOption(opt);
@ -1615,7 +1617,7 @@ void VMainWindow::initMarkdownitOptionMenu(QMenu *p_menu)
supAct->setCheckable(true);
supAct->setChecked(opt.m_sup);
connect(supAct, &QAction::triggered,
this, [this](bool p_checked) {
this, [](bool p_checked) {
MarkdownitOption opt = g_config->getMarkdownitOption();
opt.m_sup = p_checked;
g_config->setMarkdownitOption(opt);
@ -1626,7 +1628,7 @@ void VMainWindow::initMarkdownitOptionMenu(QMenu *p_menu)
subAct->setCheckable(true);
subAct->setChecked(opt.m_sub);
connect(subAct, &QAction::triggered,
this, [this](bool p_checked) {
this, [](bool p_checked) {
MarkdownitOption opt = g_config->getMarkdownitOption();
opt.m_sub = p_checked;
g_config->setMarkdownitOption(opt);
@ -1637,7 +1639,7 @@ void VMainWindow::initMarkdownitOptionMenu(QMenu *p_menu)
metadataAct->setCheckable(true);
metadataAct->setChecked(opt.m_metadata);
connect(metadataAct, &QAction::triggered,
this, [this](bool p_checked) {
this, [](bool p_checked) {
MarkdownitOption opt = g_config->getMarkdownitOption();
opt.m_metadata = p_checked;
g_config->setMarkdownitOption(opt);
@ -1648,7 +1650,7 @@ void VMainWindow::initMarkdownitOptionMenu(QMenu *p_menu)
emojiAct->setCheckable(true);
emojiAct->setChecked(opt.m_emoji);
connect(emojiAct, &QAction::triggered,
this, [this](bool p_checked) {
this, [](bool p_checked) {
MarkdownitOption opt = g_config->getMarkdownitOption();
opt.m_emoji = p_checked;
g_config->setMarkdownitOption(opt);
@ -1740,14 +1742,10 @@ void VMainWindow::initRenderStyleMenu(QMenu *p_menu)
QActionGroup *ag = new QActionGroup(this);
connect(ag, &QActionGroup::triggered,
this, [this](QAction *p_action) {
if (!p_action) {
return;
}
this, [](QAction *p_action) {
QString data = p_action->data().toString();
g_config->setCssStyle(data);
vnote->updateTemplate();
g_vnote->updateTemplate();
});
QList<QString> styles = g_config->getCssStyles();
@ -1793,14 +1791,10 @@ void VMainWindow::initCodeBlockStyleMenu(QMenu *p_menu)
QActionGroup *ag = new QActionGroup(this);
connect(ag, &QActionGroup::triggered,
this, [this](QAction *p_action) {
if (!p_action) {
return;
}
this, [](QAction *p_action) {
QString data = p_action->data().toString();
g_config->setCodeBlockCssStyle(data);
vnote->updateTemplate();
g_vnote->updateTemplate();
});
QList<QString> styles = g_config->getCodeBlockCssStyles();
@ -1942,11 +1936,7 @@ void VMainWindow::initEditorStyleMenu(QMenu *p_menu)
QActionGroup *ag = new QActionGroup(this);
connect(ag, &QActionGroup::triggered,
this, [this](QAction *p_action) {
if (!p_action) {
return;
}
this, [](QAction *p_action) {
QString data = p_action->data().toString();
g_config->setEditorStyle(data);
});
@ -1968,6 +1958,49 @@ void VMainWindow::initEditorStyleMenu(QMenu *p_menu)
}
}
void VMainWindow::initAutoScrollCursorLineMenu(QMenu *p_menu)
{
QMenu *subMenu = p_menu->addMenu(tr("Auto Scroll Cursor Line"));
subMenu->setToolTipsVisible(true);
QActionGroup *ag = new QActionGroup(this);
connect(ag, &QActionGroup::triggered,
this, [](QAction *p_action) {
g_config->setAutoScrollCursorLine(p_action->data().toInt());
});
int mode = g_config->getAutoScrollCursorLine();
int data = AutoScrollDisabled;
QAction *act = new QAction(tr("Disabled"), ag);
act->setCheckable(true);
act->setData(data);
subMenu->addAction(act);
if (mode == data) {
act->setChecked(true);
}
data = AutoScrollEndOfDoc;
act = new QAction(tr("End Of Document"), ag);
act->setToolTip(tr("Scroll cursor line into the center when it locates at the end of document"));
act->setCheckable(true);
act->setData(data);
subMenu->addAction(act);
if (mode == data) {
act->setChecked(true);
}
data = AutoScrollAlways;
act = new QAction(tr("Always"), ag);
act->setToolTip(tr("Always scroll cursor line into the center"));
act->setCheckable(true);
act->setData(data);
subMenu->addAction(act);
if (mode == data) {
act->setChecked(true);
}
}
void VMainWindow::setRenderBackgroundColor(QAction *action)
{
if (!action) {
@ -3018,11 +3051,7 @@ void VMainWindow::initThemeMenu(QMenu *p_menu)
QActionGroup *ag = new QActionGroup(this);
connect(ag, &QActionGroup::triggered,
this, [this](QAction *p_action) {
if (!p_action) {
return;
}
this, [](QAction *p_action) {
QString data = p_action->data().toString();
g_config->setTheme(data);
});

View File

@ -260,7 +260,9 @@ private:
// Init the Line Number submenu in Edit menu.
void initEditorLineNumberMenu(QMenu *p_menu);
void initEditorStyleMenu(QMenu *p_emnu);
void initEditorStyleMenu(QMenu *p_menu);
void initAutoScrollCursorLineMenu(QMenu *p_menu);
void updateWindowTitle(const QString &str);

View File

@ -91,7 +91,7 @@ VMdEditor::VMdEditor(VFile *p_file,
// in this case.
connect(m_pegHighlighter, &PegMarkdownHighlighter::highlightCompleted,
this, [this]() {
makeBlockVisible(textCursor().block());
scrollCursorLineIfNecessary();
if (m_freshEdit) {
m_freshEdit = false;
@ -215,7 +215,7 @@ bool VMdEditor::scrollToBlock(int p_blockNumber)
{
QTextBlock block = document()->findBlockByNumber(p_blockNumber);
if (block.isValid()) {
VEditUtils::scrollBlockInPage(this, block.blockNumber(), 0);
scrollBlockInPage(block.blockNumber(), 0);
moveCursor(QTextCursor::EndOfBlock);
return true;
}
@ -1014,9 +1014,9 @@ bool VMdEditor::jumpTitle(bool p_forward, int p_relativeLevel, int p_repeat)
return false;
}
void VMdEditor::scrollBlockInPage(int p_blockNum, int p_dest)
void VMdEditor::scrollBlockInPage(int p_blockNum, int p_dest, int p_margin)
{
VEditUtils::scrollBlockInPage(this, p_blockNum, p_dest);
VEditUtils::scrollBlockInPage(this, p_blockNum, p_dest, p_margin);
}
void VMdEditor::updateTextEditConfig()
@ -1029,6 +1029,8 @@ void VMdEditor::updateTextEditConfig()
setImageLineColor(g_config->getEditorPreviewImageLineFg());
setEnableExtraBuffer(g_config->getEnableExtraBuffer());
int lineNumber = g_config->getEditorLineNumber();
if (lineNumber < (int)LineNumberType::None || lineNumber >= (int)LineNumberType::Invalid) {
lineNumber = (int)LineNumberType::None;

View File

@ -58,7 +58,7 @@ public:
// Return true if @p_blockNumber is valid to scroll to.
bool scrollToHeader(int p_blockNumber);
void scrollBlockInPage(int p_blockNum, int p_dest) Q_DECL_OVERRIDE;
void scrollBlockInPage(int p_blockNum, int p_dest, int p_margin = 0) Q_DECL_OVERRIDE;
void updateConfig() Q_DECL_OVERRIDE;

View File

@ -41,7 +41,8 @@ VTextDocumentLayout::VTextDocumentLayout(QTextDocument *p_doc,
m_lastCursorBlockWidth(-1),
m_highlightCursorLineBlock(false),
m_cursorLineBlockBg("#C0C0C0"),
m_cursorLineBlockNumber(-1)
m_cursorLineBlockNumber(-1),
m_extraBufferHeight(0)
{
}
@ -396,7 +397,7 @@ int VTextDocumentLayout::pageCount() const
QSizeF VTextDocumentLayout::documentSize() const
{
return QSizeF(m_width, m_height);
return QSizeF(m_width, m_height + m_extraBufferHeight);
}
QRectF VTextDocumentLayout::frameBoundingRect(QTextFrame *p_frame) const

View File

@ -77,6 +77,8 @@ public:
// Request update block by block number.
void updateBlockByNumber(int p_blockNumber);
void setExtraBufferHeight(int p_height);
signals:
// Emit to update current cursor block width if m_cursorBlockMode is enabled.
void cursorBlockWidthUpdated(int p_width);
@ -196,7 +198,7 @@ private:
// The block number of the block which contains the m_width.
int m_maximumWidthBlockNumber;
// Height of all the document (all the blocks).
// Height of all the document (all the blocks, excluding m_extraBufferHeight).
qreal m_height;
// Set the leading space of a line.
@ -237,6 +239,9 @@ private:
// The block containing the cursor.
int m_cursorLineBlockNumber;
// Extra buffer height in document size.
int m_extraBufferHeight;
};
inline qreal VTextDocumentLayout::getLineLeading() const
@ -325,4 +330,14 @@ inline void VTextDocumentLayout::updateOffset(const QTextBlock &p_block)
updateOffsetBefore(p_block);
updateOffsetAfter(p_block);
}
inline void VTextDocumentLayout::setExtraBufferHeight(int p_height)
{
if (m_extraBufferHeight == p_height) {
return;
}
m_extraBufferHeight = p_height;
emit documentSizeChanged(documentSize());
}
#endif // VTEXTDOCUMENTLAYOUT_H

View File

@ -52,6 +52,8 @@ void VTextEdit::init()
m_highlightCursorLineBlock = false;
m_enableExtraBuffer = false;
m_imageMgr = new VImageResourceManager2();
QTextDocument *doc = document();
@ -106,13 +108,17 @@ void VTextEdit::resizeEvent(QResizeEvent *p_event)
{
QTextEdit::resizeEvent(p_event);
if (m_lineNumberType != LineNumberType::None) {
QRect rect = contentsRect();
if (m_lineNumberType != LineNumberType::None) {
m_lineNumberArea->setGeometry(QRect(rect.left(),
rect.top(),
m_lineNumberArea->calculateWidth(),
rect.height()));
}
if (m_enableExtraBuffer) {
getLayout()->setExtraBufferHeight(rect.height() / 2);
}
}
void VTextEdit::paintLineNumberArea(QPaintEvent *p_event)

View File

@ -78,6 +78,8 @@ public:
void setDisplayScaleFactor(qreal p_factor);
void setEnableExtraBuffer(bool p_enable);
protected:
void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE;
@ -112,6 +114,8 @@ private:
bool m_highlightCursorLineBlock;
int m_defaultCursorWidth;
bool m_enableExtraBuffer;
};
inline void VTextEdit::setLineNumberType(LineNumberType p_type)
@ -131,4 +135,15 @@ inline void VTextEdit::setLineNumberColor(const QColor &p_foreground,
m_lineNumberArea->setForegroundColor(p_foreground);
m_lineNumberArea->setBackgroundColor(p_background);
}
inline void VTextEdit::setEnableExtraBuffer(bool p_enable)
{
if (m_enableExtraBuffer == p_enable) {
return;
}
m_enableExtraBuffer = p_enable;
getLayout()->setExtraBufferHeight(m_enableExtraBuffer ? contentsRect().height() / 2
: 0);
}
#endif // VTEXTEDIT_H