Skip to content

Commit 024d720

Browse files
pengfeixxdeepin-bot[bot]
authored andcommitted
fix: center search result line in read-only markdown view
1. Root cause: in read-only markdown view search next/prev called jumpToLine with keepLineAtCenter=false, so the hidden TextEdit only scrolled minimally and kept the match at the bottom edge of its own viewport, while render-page sync only aligns the top visible block; since the 800px rendered column is taller per source line, the match fell below the rendered fold (reliably reproducible when maximized) 2. Fix: pass keepLineAtCenter=true in searchKeywordSeletion so keepCurrentLineAtCenter centers the anchor line; the explicit scrollbar setValue also drives valueChanged render-page scroll sync 3. Test: add EditWrapper UT cases (maximized/normal window) asserting the renderer receives scrollToLine near the matched line; all 107 editor_wrapper UT cases pass Log: fix search result not visible in read-only markdown view Influence: 1. Test search next/prev in read-only markdown view, verify match is centered on screen, especially with a maximized window 2. Test search next/prev in edit mode, verify no regression 3. Verify render-page scroll sync follows editor scrollbar fix: 修复只读Markdown视图下查找结果不在当前屏显示 1. 根因:只读Markdown视图下查找下一个/上一个调用jumpToLine时传入 keepLineAtCenter=false,隐藏的TextEdit仅做最小滚动、匹配项停在 其视口底边缘,而渲染页滚动同步仅按顶部可见行对齐;800px定宽 渲染列每源码行渲染高度更大,匹配项落到渲染视口折叠线下 (窗口最大化时必现) 2. 方案:searchKeywordSeletion中jumpToLine的keepLineAtCenter改为 true,keepCurrentLineAtCenter将锚点行居中,显式scrollbar setValue同时驱动valueChanged渲染页滚动同步 3. 测试:新增EditWrapper单测(最大化/普通窗口两场景),断言渲染器 收到的scrollToLine行号贴近匹配行;editor_wrapper 107例全部通过 Log: 修复只读Markdown视图下查找结果不在当前屏显示的问题 Influence: 1. 在只读Markdown视图下测试查找下一个/上一个,验证匹配内容居中 显示,重点验证窗口最大化场景 2. 在编辑模式下测试查找功能,验证无回归 3. 验证渲染页滚动与编辑器滚动条同步 PMS: BUG-380705
1 parent 3937fd9 commit 024d720

2 files changed

Lines changed: 86 additions & 2 deletions

File tree

‎src/editor/dtextedit.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2724,7 +2724,7 @@ bool TextEdit::searchKeywordSeletion(QString keyword, QTextCursor cursor, bool f
27242724
if (!next.isNull()) {
27252725
qCDebug(appLog) << "Searching keyword seletion with find next and not null";
27262726
m_findHighlightSelection.cursor = next;
2727-
jumpToLine(next.blockNumber() + offsetLines, false);
2727+
jumpToLine(next.blockNumber() + offsetLines, true);
27282728
setTextCursor(next);
27292729
ret = true;
27302730
}
@@ -2745,7 +2745,7 @@ bool TextEdit::searchKeywordSeletion(QString keyword, QTextCursor cursor, bool f
27452745
if (!prev.isNull()) {
27462746
qCDebug(appLog) << "Searching keyword seletion with find previous and not null";
27472747
m_findHighlightSelection.cursor = prev;
2748-
jumpToLine(prev.blockNumber() + offsetLines, false);
2748+
jumpToLine(prev.blockNumber() + offsetLines, true);
27492749
setTextCursor(prev);
27502750
ret = true;
27512751
}

‎tests/editor_wrapper/test_editwrapper.cpp‎

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,90 @@ TEST_F(EditWrapperTest, PlainTextEmpty_DefaultTrue_AfterInsertFalse)
638638
EXPECT_FALSE(m_wrapper->isPlainTextEmpty());
639639
}
640640

641+
// ============================================================================
642+
// V-6705 验证用例:md 只读视图下查找"下一个",渲染页 scrollToLine 同步行为
643+
// 场景:隐藏 TextEdit(ReadView)+ 大窗口(模拟最大化),匹配项在远处
644+
// 断言(修复后期望):1) 渲染器收到 scrollToLine;
645+
// 2) 同步行号与匹配行距离 ≤ 半屏(居中语义),保证渲染页顶部对齐后匹配仍在屏内
646+
// ============================================================================
647+
static void v6705FindNextScenario(EditWrapper *wrapper, RecordingRenderer *renderer,
648+
int winW, int winH, const char *tag)
649+
{
650+
renderer->ready = true;
651+
wrapper->setMarkdownRendererForTest(renderer);
652+
653+
// 长文档:500 行,needle 只在第 400 行(0 基块号 399)
654+
QString text;
655+
for (int i = 1; i <= 500; ++i)
656+
text += (i == 400 ? QString("line %1 needle here\n").arg(i)
657+
: QString("line %1 plain text content\n").arg(i));
658+
659+
QTemporaryDir dir;
660+
const QString mdPath = dir.filePath("v6705.md");
661+
{
662+
QFile f(mdPath);
663+
ASSERT_TRUE(f.open(QIODevice::WriteOnly));
664+
f.write(text.toUtf8());
665+
f.close();
666+
}
667+
wrapper->updatePath(mdPath, mdPath);
668+
wrapper->textEditor()->setPlainText(text);
669+
670+
// 真实应用时序:编辑页先以真实尺寸布局(Edit 模式可见),再切 ReadView 隐藏。
671+
// 未 show 的 widget 不派发 Resize 事件,隐藏页几何不会更新,必须先 show 顶层容器。
672+
if (QWidget *top = wrapper->parentWidget() ? wrapper->parentWidget() : wrapper)
673+
top->resize(winW, winH);
674+
wrapper->resize(winW, winH);
675+
if (wrapper->parentWidget())
676+
wrapper->parentWidget()->show();
677+
else
678+
wrapper->show();
679+
QApplication::processEvents();
680+
681+
wrapper->updateMarkdownRecognition(QStringLiteral("v6705.md"), QString());
682+
wrapper->setViewMode(ViewMode::ReadView);
683+
ASSERT_EQ(wrapper->viewMode(), ViewMode::ReadView);
684+
685+
TextEdit *ed = wrapper->textEditor();
686+
ASSERT_EQ(ed->toPlainText().split('\n').size(), 501); // 500 行 + 末尾空串
687+
688+
ed->verticalScrollBar()->setValue(0);
689+
QApplication::processEvents();
690+
renderer->scrollCalls = 0;
691+
renderer->lastLine = -1.0;
692+
693+
// Act:真实查找路径(Window::handleFindKeyword → updateCursorKeywordSelection)
694+
ed->updateCursorKeywordSelection(QStringLiteral("needle"), true);
695+
QApplication::processEvents();
696+
697+
const int matchBlock = ed->textCursor().blockNumber();
698+
const int lineHeight = ed->cursorRect().height();
699+
const int viewportH = ed->viewport()->height();
700+
const int visibleLines = lineHeight > 0 ? viewportH / lineHeight : 0;
701+
const double dist = matchBlock - renderer->lastLine;
702+
703+
qInfo("[%s] win=%dx%d scrollCalls=%d lastLine=%.1f matchBlock=%d vbarValue=%d "
704+
"topVisibleBlock=%d viewportH=%d lineHeight=%d visibleLines=%d matchToSyncTopDist=%.1f",
705+
tag, winW, winH, renderer->scrollCalls, renderer->lastLine, matchBlock,
706+
ed->verticalScrollBar()->value(), ed->topVisibleBlockNumber(),
707+
viewportH, lineHeight, visibleLines, dist);
708+
709+
// 观测点 1:渲染页确实收到滚动指令(Qt6 下 setTextCursor 内部滚动即触发)
710+
EXPECT_GE(renderer->scrollCalls, 1);
711+
// 观测点 2(修复语义):同步行号与匹配行相距不超过半屏 + 少量余量
712+
EXPECT_LE(dist, visibleLines / 2 + 3);
713+
}
714+
715+
TEST_F(EditWrapperTest, V6705_ReadViewFindNext_SyncsRendererNearMatch_Maximized)
716+
{
717+
v6705FindNextScenario(m_wrapper, &m_renderer, 1920, 1040, "maximized");
718+
}
719+
720+
TEST_F(EditWrapperTest, V6705_ReadViewFindNext_SyncsRendererNearMatch_Normal)
721+
{
722+
v6705FindNextScenario(m_wrapper, &m_renderer, 900, 600, "normal");
723+
}
724+
641725
// ============================================================================
642726
// isModified(TEST_P:m_bIsTemFile × 撤销栈状态,B28)
643727
// ============================================================================

0 commit comments

Comments
 (0)