From 66c1d543c2e310f702bb231fbef9e7a74a868f83 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Mon, 12 Dec 2016 21:58:53 +0800 Subject: [PATCH] synchronize current header in read and edit mode Signed-off-by: Le Tan --- src/vedittab.cpp | 50 ++++++++++++++++++++++++++++++++++++++------- src/vedittab.h | 3 ++- src/vmainwindow.cpp | 3 +-- src/vmdedit.cpp | 20 +++++++++++++++--- src/vmdedit.h | 5 ++++- src/voutline.cpp | 3 +++ src/vtoc.h | 6 ++++-- 7 files changed, 74 insertions(+), 16 deletions(-) diff --git a/src/vedittab.cpp b/src/vedittab.cpp index 725bc930..81937b85 100644 --- a/src/vedittab.cpp +++ b/src/vedittab.cpp @@ -50,10 +50,11 @@ void VEditTab::setupUI() m_textEditor = new VMdEdit(m_file, this); connect(dynamic_cast(m_textEditor), &VMdEdit::headersChanged, this, &VEditTab::updateTocFromHeaders); - connect(m_textEditor, SIGNAL(curHeaderChanged(int)), - this, SLOT(updateCurHeader(int))); + connect(m_textEditor, SIGNAL(curHeaderChanged(int, int)), + this, SLOT(updateCurHeader(int, int))); connect(m_textEditor, &VEdit::textChanged, this, &VEditTab::handleTextChanged); + m_textEditor->reloadFile(); addWidget(m_textEditor); setupMarkdownPreview(); @@ -91,6 +92,7 @@ void VEditTab::showFileReadMode() { qDebug() << "read" << m_file->getName(); isEditMode = false; + int outlineIndex = curHeader.m_outlineIndex; switch (m_file->getDocType()) { case DocType::Html: m_textEditor->setReadOnly(true); @@ -98,10 +100,12 @@ void VEditTab::showFileReadMode() case DocType::Markdown: if (mdConverterType == MarkdownConverterType::Marked) { document.setText(m_file->getContent()); + updateTocFromHtml(document.getToc()); } else { previewByConverter(); } setCurrentWidget(webPreviewer); + scrollPreviewToHeader(outlineIndex); break; default: qWarning() << "error: unknown doc type" << int(m_file->getDocType()); @@ -110,6 +114,18 @@ void VEditTab::showFileReadMode() noticeStatusChanged(); } +void VEditTab::scrollPreviewToHeader(int p_outlineIndex) +{ + Q_ASSERT(p_outlineIndex >= 0); + if (p_outlineIndex < tableOfContent.headers.size()) { + QString anchor = tableOfContent.headers[p_outlineIndex].anchor; + qDebug() << "scroll preview to" << p_outlineIndex << anchor; + if (!anchor.isEmpty()) { + document.scrollToAnchor(anchor.mid(1)); + } + } +} + void VEditTab::previewByConverter() { VMarkdownConverter mdConverter; @@ -126,8 +142,14 @@ void VEditTab::previewByConverter() void VEditTab::showFileEditMode() { isEditMode = true; + + // beginEdit() may change curHeader. + int outlineIndex = curHeader.m_outlineIndex; m_textEditor->beginEdit(); setCurrentWidget(m_textEditor); + if (m_file->getDocType() == DocType::Markdown) { + dynamic_cast(m_textEditor)->scrollToHeader(outlineIndex); + } m_textEditor->setFocus(); noticeStatusChanged(); } @@ -253,6 +275,9 @@ void VEditTab::handleFocusChanged(QWidget *old, QWidget *now) void VEditTab::updateTocFromHtml(const QString &tocHtml) { + if (isEditMode) { + return; + } tableOfContent.type = VHeaderType::Anchor; QVector &headers = tableOfContent.headers; headers.clear(); @@ -280,6 +305,9 @@ void VEditTab::updateTocFromHtml(const QString &tocHtml) void VEditTab::updateTocFromHeaders(const QVector &headers) { + if (!isEditMode) { + return; + } tableOfContent.type = VHeaderType::LineNumber; tableOfContent.headers = headers; tableOfContent.filePath = m_file->retrivePath(); @@ -379,22 +407,30 @@ void VEditTab::scrollToAnchor(const VAnchor &anchor) void VEditTab::updateCurHeader(const QString &anchor) { - if (curHeader.anchor.mid(1) == anchor) { + if (isEditMode || curHeader.anchor.mid(1) == anchor) { return; } curHeader = VAnchor(m_file->retrivePath(), "#" + anchor, -1); if (!anchor.isEmpty()) { + const QVector &headers = tableOfContent.headers; + for (int i = 0; i < headers.size(); ++i) { + if (headers[i].anchor == curHeader.anchor) { + curHeader.m_outlineIndex = i; + break; + } + } emit curHeaderChanged(curHeader); } } -void VEditTab::updateCurHeader(int lineNumber) +void VEditTab::updateCurHeader(int p_lineNumber, int p_outlineIndex) { - if (curHeader.lineNumber == lineNumber) { + if (!isEditMode || curHeader.lineNumber == p_lineNumber) { return; } - curHeader = VAnchor(m_file->retrivePath(), "", lineNumber); - if (lineNumber > -1) { + curHeader = VAnchor(m_file->retrivePath(), "", p_lineNumber); + curHeader.m_outlineIndex = p_outlineIndex; + if (p_lineNumber > -1) { emit curHeaderChanged(curHeader); } } diff --git a/src/vedittab.h b/src/vedittab.h index ddb78009..3cda35e6 100644 --- a/src/vedittab.h +++ b/src/vedittab.h @@ -48,7 +48,7 @@ private slots: void handleFocusChanged(QWidget *old, QWidget *now); void updateTocFromHtml(const QString &tocHtml); void updateCurHeader(const QString &anchor); - void updateCurHeader(int lineNumber); + void updateCurHeader(int p_lineNumber, int p_outlineIndex); void updateTocFromHeaders(const QVector &headers); void handleTextChanged(); @@ -62,6 +62,7 @@ private: void parseTocUl(QXmlStreamReader &xml, QVector &headers, int level); void parseTocLi(QXmlStreamReader &xml, QVector &headers, int level); void noticeStatusChanged(); + void scrollPreviewToHeader(int p_outlineIndex); QPointer m_file; bool isEditMode; diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index cf62a64b..1a7e18de 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -28,9 +28,8 @@ VMainWindow::VMainWindow(QWidget *parent) initDockWindows(); initAvatar(); - setContextMenuPolicy(Qt::NoContextMenu); - restoreStateAndGeometry(); + setContextMenuPolicy(Qt::NoContextMenu); notebookSelector->update(); } diff --git a/src/vmdedit.cpp b/src/vmdedit.cpp index 01eecc56..287ae093 100644 --- a/src/vmdedit.cpp +++ b/src/vmdedit.cpp @@ -53,12 +53,15 @@ void VMdEdit::beginEdit() setFont(vconfig.getMdEditFont()); - setPlainText(m_file->getContent()); + Q_ASSERT(m_file->getContent() == toPlainText()); initInitImages(); setReadOnly(false); setModified(false); + + // Request update outline. + generateEditOutline(); } void VMdEdit::endEdit() @@ -180,13 +183,14 @@ void VMdEdit::updateCurHeader() int curHeader = 0; QTextCursor cursor(this->textCursor()); int curLine = cursor.block().firstLineNumber(); - for (int i = m_headers.size() - 1; i >= 0; --i) { + int i = 0; + for (i = m_headers.size() - 1; i >= 0; --i) { if (m_headers[i].lineNumber <= curLine) { curHeader = m_headers[i].lineNumber; break; } } - emit curHeaderChanged(curHeader); + emit curHeaderChanged(curHeader, i == -1 ? 0 : i); } void VMdEdit::generateEditOutline() @@ -209,3 +213,13 @@ void VMdEdit::generateEditOutline() emit headersChanged(m_headers); updateCurHeader(); } + +void VMdEdit::scrollToHeader(int p_headerIndex) +{ + Q_ASSERT(p_headerIndex >= 0); + if (p_headerIndex < m_headers.size()) { + int line = m_headers[p_headerIndex].lineNumber; + qDebug() << "scroll editor to" << p_headerIndex << "line" << line; + scrollToLine(line); + } +} diff --git a/src/vmdedit.h b/src/vmdedit.h index d4b07744..945b54aa 100644 --- a/src/vmdedit.h +++ b/src/vmdedit.h @@ -20,9 +20,12 @@ public: void insertImage(const QString &p_name); + // Scroll to m_headers[p_headerIndex]. + void scrollToHeader(int p_headerIndex); + signals: void headersChanged(const QVector &headers); - void curHeaderChanged(int lineNumber); + void curHeaderChanged(int p_lineNumber, int p_outlineIndex); private slots: void generateEditOutline(); diff --git a/src/voutline.cpp b/src/voutline.cpp index 8e4c71d4..61ac814d 100644 --- a/src/voutline.cpp +++ b/src/voutline.cpp @@ -53,6 +53,7 @@ void VOutline::updateTreeByLevel(const QVector &headers, int &index, QJsonObject itemJson; itemJson["anchor"] = header.anchor; itemJson["line_number"] = header.lineNumber; + itemJson["outline_index"] = index; item->setData(0, Qt::UserRole, itemJson); item->setText(0, header.name); item->setToolTip(0, header.name); @@ -83,10 +84,12 @@ void VOutline::handleCurItemChanged(QTreeWidgetItem *p_curItem, QTreeWidgetItem QJsonObject itemJson = p_curItem->data(0, Qt::UserRole).toJsonObject(); QString anchor = itemJson["anchor"].toString(); int lineNumber = itemJson["line_number"].toInt(); + int outlineIndex = itemJson["outline_index"].toInt(); VAnchor tmp; tmp.filePath = outline.filePath; tmp.anchor = anchor; tmp.lineNumber = lineNumber; + tmp.m_outlineIndex = outlineIndex; if (tmp == curHeader) { return; } diff --git a/src/vtoc.h b/src/vtoc.h index 6e987180..27b28e46 100644 --- a/src/vtoc.h +++ b/src/vtoc.h @@ -23,12 +23,14 @@ struct VHeader struct VAnchor { - VAnchor() : lineNumber(-1) {} + VAnchor() : lineNumber(-1), m_outlineIndex(0) {} VAnchor(const QString filePath, const QString &anchor, int lineNumber) - : filePath(filePath), anchor(anchor), lineNumber(lineNumber) {} + : filePath(filePath), anchor(anchor), lineNumber(lineNumber), m_outlineIndex(0) {} QString filePath; QString anchor; int lineNumber; + // Index of this anchor in VToc outline. + int m_outlineIndex; bool operator==(const VAnchor &p_anchor) const { return (p_anchor.filePath == filePath