123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880 |
- #include "markdownviewwindow.h"
- #include <QSplitter>
- #include <QToolBar>
- #include <QStackedWidget>
- #include <QEvent>
- #include <QCoreApplication>
- #include <QScrollBar>
- #include <QLabel>
- #include <core/fileopenparameters.h>
- #include <core/editorconfig.h>
- #include <core/markdowneditorconfig.h>
- #include <core/htmltemplatehelper.h>
- #include <vtextedit/vtextedit.h>
- #include <vtextedit/pegmarkdownhighlighter.h>
- #include <vtextedit/markdowneditorconfig.h>
- #include <utils/pathutils.h>
- #include <buffer/markdownbuffer.h>
- #include <core/vnotex.h>
- #include <core/thememgr.h>
- #include "editors/markdowneditor.h"
- #include "textviewwindowhelper.h"
- #include "editors/markdownviewer.h"
- #include "editors/editormarkdownvieweradapter.h"
- #include "editors/previewhelper.h"
- #include "dialogs/deleteconfirmdialog.h"
- #include "outlineprovider.h"
- #include "toolbarhelper.h"
- #include "findandreplacewidget.h"
- #include "editors/statuswidget.h"
- using namespace vnotex;
- MarkdownViewWindow::MarkdownViewWindow(const QSharedPointer<FileOpenParameters> &p_paras, QWidget *p_parent)
- : ViewWindow(p_parent),
- m_openParas(p_paras)
- {
- // Need to setup before setupUI() since the tool bar action will need the provider.
- setupOutlineProvider();
- setupUI();
- m_previewHelper = new PreviewHelper(nullptr, this);
- setModeInternal(modeFromOpenParameters(*p_paras));
- m_initialized = true;
- }
- MarkdownViewWindow::~MarkdownViewWindow()
- {
- if (m_textEditorStatusWidget) {
- getMainStatusWidget()->removeWidget(m_textEditorStatusWidget.get());
- m_textEditorStatusWidget->setParent(nullptr);
- }
- if (m_viewerStatusWidget) {
- getMainStatusWidget()->removeWidget(m_viewerStatusWidget.get());
- m_viewerStatusWidget->setParent(nullptr);
- }
- m_mainStatusWidget->setParent(nullptr);
- }
- void MarkdownViewWindow::setupUI()
- {
- // Central widget.
- m_splitter = new QSplitter(this);
- m_splitter->setContentsMargins(0, 0, 0, 0);
- setCentralWidget(m_splitter);
- // Get the focus event from splitter.
- m_splitter->installEventFilter(this);
- // Status widget.
- // We use a QTabWidget as status widget since we have two widgets for different modes.
- {
- auto statusWidget = QSharedPointer<StatusWidget>::create(this);
- m_mainStatusWidget = QSharedPointer<QStackedWidget>::create(this);
- m_mainStatusWidget->setContentsMargins(0, 0, 0, 0);
- statusWidget->setEditorStatusWidget(m_mainStatusWidget);
- setStatusWidget(statusWidget);
- }
- setupToolBar();
- }
- void MarkdownViewWindow::setMode(Mode p_mode)
- {
- setModeInternal(p_mode);
- if (m_findAndReplace && m_findAndReplace->isVisible()) {
- m_findAndReplace->setReplaceEnabled(m_mode != Mode::Read);
- }
- }
- void MarkdownViewWindow::setModeInternal(Mode p_mode)
- {
- if (p_mode == m_mode) {
- return;
- }
- m_previousMode = m_mode;
- m_mode = p_mode;
- switch (m_mode) {
- case Mode::Read:
- {
- if (!m_viewer) {
- setupViewer();
- if (m_initialized) {
- syncViewerFromBuffer(true);
- }
- }
- // Avoid focus glitch.
- m_viewer->show();
- m_viewer->setFocus();
- if (m_editor) {
- m_editor->hide();
- }
- getMainStatusWidget()->setCurrentWidget(m_viewerStatusWidget.get());
- break;
- }
- case Mode::Edit:
- {
- if (!m_editor) {
- // We need viewer to preview.
- if (!m_viewer) {
- setupViewer();
- }
- setupTextEditor();
- if (m_initialized) {
- syncTextEditorFromBuffer(true);
- }
- }
- // Avoid focus glitch.
- m_editor->show();
- m_editor->setFocus();
- Q_ASSERT(m_viewer);
- m_viewer->hide();
- getMainStatusWidget()->setCurrentWidget(m_textEditorStatusWidget.get());
- break;
- }
- default:
- Q_ASSERT(false);
- break;
- }
- // Let editor to show or scrollToLine will not work correctly.
- QCoreApplication::processEvents();
- if (m_initialized) {
- doSyncEditorFromBufferContent(true);
- }
- emit modeChanged();
- }
- void MarkdownViewWindow::setModified(bool p_modified)
- {
- if (m_editor) {
- m_editor->setModified(p_modified);
- }
- }
- void MarkdownViewWindow::handleEditorConfigChange()
- {
- const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
- const auto &markdownEditorConfig = editorConfig.getMarkdownEditorConfig();
- if (markdownEditorConfig.revision() != m_markdownEditorConfigRevision) {
- m_markdownEditorConfigRevision = markdownEditorConfig.revision();
- HtmlTemplateHelper::updateMarkdownViewerTemplate(markdownEditorConfig);
- if (m_editor) {
- auto config = createMarkdownEditorConfig(markdownEditorConfig);
- m_editor->setConfig(config);
- m_editor->updateFromConfig();
- }
- updateWebViewerConfig(markdownEditorConfig);
- }
- }
- QString MarkdownViewWindow::getLatestContent() const
- {
- Q_ASSERT(m_editor);
- return m_editor->getText();
- }
- void MarkdownViewWindow::syncEditorFromBuffer()
- {
- m_bufferRevision = getBuffer() ? getBuffer()->getRevision() : 0;
- syncTextEditorFromBuffer(false);
- syncViewerFromBuffer(false);
- }
- void MarkdownViewWindow::syncEditorFromBufferContent()
- {
- doSyncEditorFromBufferContent(false);
- }
- void MarkdownViewWindow::doSyncEditorFromBufferContent(bool p_syncPosition)
- {
- auto buffer = getBuffer();
- Q_ASSERT(buffer);
- // m_bufferRevision may already be the same as the buffer revision, in which
- // case we will call editor or viewer to update its content.
- m_bufferRevision = buffer->getRevision();
- switch (m_mode) {
- case Mode::Read:
- syncViewerFromBufferContent(p_syncPosition);
- break;
- case Mode::Edit:
- syncTextEditorFromBufferContent(p_syncPosition);
- break;
- default:
- Q_ASSERT(false);
- }
- }
- void MarkdownViewWindow::handleBufferChangedInternal()
- {
- TextViewWindowHelper::handleBufferChanged(this);
- auto buffer = getBuffer();
- if (m_openParas && m_openParas->m_newFile) {
- Q_ASSERT(m_mode != Mode::Read);
- const auto &markdownEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig();
- if (markdownEditorConfig.getInsertFileNameAsTitle() && buffer->getContent().isEmpty()) {
- const auto title = QString("# %1\n").arg(QFileInfo(buffer->getName()).baseName());
- m_editor->insertText(title);
- }
- }
- m_openParas.clear();
- }
- void MarkdownViewWindow::setupToolBar()
- {
- auto toolBar = createToolBar(this);
- const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
- const int iconSize = editorConfig.getToolBarIconSize();
- toolBar->setIconSize(QSize(iconSize, iconSize));
- addToolBar(toolBar);
- addAction(toolBar, ViewWindowToolBarHelper::EditReadDiscard);
- addAction(toolBar, ViewWindowToolBarHelper::Save);
- toolBar->addSeparator();
- addAction(toolBar, ViewWindowToolBarHelper::Attachment);
- toolBar->addSeparator();
- addAction(toolBar, ViewWindowToolBarHelper::SectionNumber);
- addAction(toolBar, ViewWindowToolBarHelper::TypeHeading);
- addAction(toolBar, ViewWindowToolBarHelper::TypeBold);
- addAction(toolBar, ViewWindowToolBarHelper::TypeItalic);
- addAction(toolBar, ViewWindowToolBarHelper::TypeStrikethrough);
- addAction(toolBar, ViewWindowToolBarHelper::TypeUnorderedList);
- addAction(toolBar, ViewWindowToolBarHelper::TypeOrderedList);
- addAction(toolBar, ViewWindowToolBarHelper::TypeTodoList);
- addAction(toolBar, ViewWindowToolBarHelper::TypeCheckedTodoList);
- addAction(toolBar, ViewWindowToolBarHelper::TypeCode);
- addAction(toolBar, ViewWindowToolBarHelper::TypeCodeBlock);
- addAction(toolBar, ViewWindowToolBarHelper::TypeMath);
- addAction(toolBar, ViewWindowToolBarHelper::TypeMathBlock);
- addAction(toolBar, ViewWindowToolBarHelper::TypeQuote);
- addAction(toolBar, ViewWindowToolBarHelper::TypeLink);
- addAction(toolBar, ViewWindowToolBarHelper::TypeImage);
- addAction(toolBar, ViewWindowToolBarHelper::TypeTable);
- ToolBarHelper::addSpacer(toolBar);
- addAction(toolBar, ViewWindowToolBarHelper::FindAndReplace);
- addAction(toolBar, ViewWindowToolBarHelper::Outline);
- }
- void MarkdownViewWindow::setupTextEditor()
- {
- Q_ASSERT(!m_editor);
- Q_ASSERT(m_viewer);
- const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
- const auto &markdownEditorConfig = editorConfig.getMarkdownEditorConfig();
- m_editorConfigRevision = editorConfig.revision();
- m_markdownEditorConfigRevision = markdownEditorConfig.revision();
- m_editor = new MarkdownEditor(markdownEditorConfig,
- createMarkdownEditorConfig(markdownEditorConfig),
- this);
- m_splitter->insertWidget(0, m_editor);
- TextViewWindowHelper::connectEditor(this);
- // Status widget.
- m_textEditorStatusWidget = m_editor->statusWidget();
- getMainStatusWidget()->addWidget(m_textEditorStatusWidget.get());
- m_textEditorStatusWidget->show();
- m_previewHelper->setMarkdownEditor(m_editor);
- m_editor->setPreviewHelper(m_previewHelper);
- // Connect viewer and editor.
- connect(adapter(), &MarkdownViewerAdapter::viewerReady,
- m_editor->getHighlighter(), &vte::PegMarkdownHighlighter::updateHighlight);
- connect(m_editor, &MarkdownEditor::htmlToMarkdownRequested,
- adapter(), &MarkdownViewerAdapter::htmlToMarkdownRequested);
- connect(adapter(), &MarkdownViewerAdapter::htmlToMarkdownReady,
- m_editor, &MarkdownEditor::handleHtmlToMarkdownData);
- // Connect outline pipeline.
- connect(m_editor, &MarkdownEditor::headingsChanged,
- this, [this]() {
- if (getMode() != Mode::Read) {
- auto outline = headingsToOutline(m_editor->getHeadings());
- m_outlineProvider->setOutline(outline);
- }
- });
- connect(m_editor, &MarkdownEditor::currentHeadingChanged,
- this, [this]() {
- if (getMode() != Mode::Read) {
- m_outlineProvider->setCurrentHeadingIndex(m_editor->getCurrentHeadingIndex());
- }
- });
- connect(m_editor, &MarkdownEditor::readRequested,
- this, [this]() {
- read(true);
- });
- }
- QStackedWidget *MarkdownViewWindow::getMainStatusWidget() const
- {
- return m_mainStatusWidget.data();
- }
- bool MarkdownViewWindow::eventFilter(QObject *p_obj, QEvent *p_event)
- {
- if (p_obj == m_splitter) {
- if (p_event->type() == QEvent::FocusIn) {
- focusEditor();
- }
- }
- return ViewWindow::eventFilter(p_obj, p_event);
- }
- void MarkdownViewWindow::focusEditor()
- {
- switch (m_mode) {
- case Mode::Read:
- m_viewer->setFocus();
- break;
- case Mode::Edit:
- m_editor->setFocus();
- break;
- default:
- Q_ASSERT(false);
- break;
- }
- }
- void MarkdownViewWindow::setupViewer()
- {
- Q_ASSERT(!m_viewer);
- const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
- const auto &markdownEditorConfig = editorConfig.getMarkdownEditorConfig();
- m_editorConfigRevision = editorConfig.revision();
- m_markdownEditorConfigRevision = markdownEditorConfig.revision();
- HtmlTemplateHelper::updateMarkdownViewerTemplate(markdownEditorConfig);
- auto adapter = new EditorMarkdownViewerAdapter(nullptr, this);
- m_viewer = new MarkdownViewer(adapter,
- VNoteX::getInst().getThemeMgr().getBaseBackground(),
- markdownEditorConfig.getZoomFactorInReadMode(),
- this);
- m_splitter->addWidget(m_viewer);
- // Status widget.
- {
- // TODO: implement a real status widget for viewer.
- auto label = new QLabel(tr("Markdown Viewer"), this);
- label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
- m_viewerStatusWidget.reset(label);
- getMainStatusWidget()->addWidget(m_viewerStatusWidget.get());
- m_viewerStatusWidget->show();
- }
- m_viewer->setPreviewHelper(m_previewHelper);
- connect(m_viewer, &MarkdownViewer::zoomFactorChanged,
- this, [this](qreal p_factor) {
- auto &markdownEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig();
- markdownEditorConfig.setZoomFactorInReadMode(p_factor);
- showZoomFactor(p_factor);
- });
- connect(m_viewer, &WebViewer::linkHovered,
- this, [this](const QString &p_url) {
- showMessage(p_url);
- });
- connect(m_viewer, &MarkdownViewer::editRequested,
- this, [this]() {
- edit();
- });
- // Connect outline pipeline.
- connect(adapter, &MarkdownViewerAdapter::headingsChanged,
- this, [this]() {
- if (getMode() == Mode::Read) {
- auto outline = headingsToOutline(this->adapter()->getHeadings());
- m_outlineProvider->setOutline(outline);
- }
- });
- connect(adapter, &MarkdownViewerAdapter::currentHeadingChanged,
- this, [this]() {
- if (getMode() == Mode::Read) {
- m_outlineProvider->setCurrentHeadingIndex(this->adapter()->getCurrentHeadingIndex());
- }
- });
- connect(adapter, &MarkdownViewerAdapter::findTextReady,
- this, [this](const QString &p_text, int p_totalMatches, int p_currentMatchIndex) {
- this->showFindResult(p_text, p_totalMatches, p_currentMatchIndex);
- });
- }
- void MarkdownViewWindow::syncTextEditorFromBuffer(bool p_syncPositionFromReadMode)
- {
- if (!m_editor) {
- return;
- }
- const bool old = m_propogateEditorToBuffer;
- m_propogateEditorToBuffer = false;
- auto buffer = getBuffer();
- m_editor->setBuffer(buffer);
- if (buffer) {
- m_editor->setReadOnly(buffer->isReadOnly());
- m_editor->setBasePath(buffer->getContentBasePath());
- m_editor->setText(buffer->getContent());
- m_editor->setModified(buffer->isModified());
- int lineNumber = -1;
- if (p_syncPositionFromReadMode) {
- lineNumber = getReadLineNumber();
- }
- m_editor->scrollToLine(lineNumber, false);
- } else {
- m_editor->setReadOnly(true);
- m_editor->setBasePath("");
- m_editor->setText("");
- m_editor->setModified(false);
- }
- m_textEditorBufferRevision = m_bufferRevision;
- m_propogateEditorToBuffer = old;
- }
- void MarkdownViewWindow::syncViewerFromBuffer(bool p_syncPositionFromEditMode)
- {
- if (!m_viewer) {
- return;
- }
- auto buffer = getBuffer();
- adapter()->setBuffer(buffer);
- if (buffer) {
- int lineNumber = -1;
- if (p_syncPositionFromEditMode) {
- lineNumber = getEditLineNumber();
- }
- // TODO: Check buffer for last position recover.
- // Use getPath() instead of getBasePath() to make in-page anchor work.
- m_viewer->setHtml(HtmlTemplateHelper::getMarkdownViewerTemplate(),
- PathUtils::pathToUrl(buffer->getContentPath()));
- adapter()->setText(m_bufferRevision, buffer->getContent(), lineNumber);
- } else {
- m_viewer->setHtml("");
- adapter()->setText(0, "", -1);
- }
- m_viewerBufferRevision = m_bufferRevision;
- }
- void MarkdownViewWindow::syncTextEditorFromBufferContent(bool p_syncPosition)
- {
- Q_ASSERT(m_editor);
- if (m_textEditorBufferRevision == m_bufferRevision) {
- if (p_syncPosition) {
- m_editor->scrollToLine(getReadLineNumber(), false);
- }
- return;
- }
- const bool old = m_propogateEditorToBuffer;
- m_propogateEditorToBuffer = false;
- auto buffer = getBuffer();
- Q_ASSERT(buffer);
- m_editor->setText(buffer->getContent());
- m_editor->setModified(buffer->isModified());
- m_textEditorBufferRevision = m_bufferRevision;
- m_propogateEditorToBuffer = old;
- }
- void MarkdownViewWindow::syncViewerFromBufferContent(bool p_syncPosition)
- {
- Q_ASSERT(m_viewer);
- if (m_viewerBufferRevision == m_bufferRevision) {
- if (p_syncPosition) {
- adapter()->scrollToPosition(MarkdownViewerAdapter::Position(getEditLineNumber(), QString()));
- }
- return;
- }
- auto buffer = getBuffer();
- Q_ASSERT(buffer);
- adapter()->setText(m_bufferRevision,
- buffer->getContent(),
- p_syncPosition ? getEditLineNumber() : -1);
- m_viewerBufferRevision = m_bufferRevision;
- }
- void MarkdownViewWindow::setBufferRevisionAfterInvalidation(int p_bufferRevision)
- {
- m_bufferRevision = p_bufferRevision;
- switch (m_mode) {
- case Mode::Edit:
- m_textEditorBufferRevision = p_bufferRevision;
- break;
- case Mode::Read:
- m_viewerBufferRevision = p_bufferRevision;
- break;
- default:
- Q_ASSERT(false);
- }
- }
- EditorMarkdownViewerAdapter *MarkdownViewWindow::adapter() const
- {
- if (m_viewer) {
- return dynamic_cast<EditorMarkdownViewerAdapter *>(m_viewer->adapter());
- }
- return nullptr;
- }
- int MarkdownViewWindow::getEditLineNumber() const
- {
- if (m_previousMode == Mode::Edit || m_previousMode == Mode::FocusPreview) {
- if (m_editor) {
- return m_editor->getTopLine();
- }
- }
- return -1;
- }
- int MarkdownViewWindow::getReadLineNumber() const
- {
- if (m_previousMode == Mode::Read) {
- if (m_viewer) {
- return adapter()->getTopLineNumber();
- }
- }
- return -1;
- }
- void MarkdownViewWindow::handleTypeAction(TypeAction p_action)
- {
- Q_ASSERT(inModeCanInsert() && m_editor);
- Q_ASSERT(!getBuffer()->isReadOnly());
- switch (p_action) {
- case TypeAction::Heading1:
- Q_FALLTHROUGH();
- case TypeAction::Heading2:
- Q_FALLTHROUGH();
- case TypeAction::Heading3:
- Q_FALLTHROUGH();
- case TypeAction::Heading4:
- Q_FALLTHROUGH();
- case TypeAction::Heading5:
- Q_FALLTHROUGH();
- case TypeAction::Heading6:
- m_editor->typeHeading(p_action - TypeAction::Heading1 + 1);
- break;
- case TypeAction::HeadingNone:
- m_editor->typeHeading(0);
- break;
- case TypeAction::Bold:
- m_editor->typeBold();
- break;
- case TypeAction::Italic:
- m_editor->typeItalic();
- break;
- case TypeAction::Strikethrough:
- m_editor->typeStrikethrough();
- break;
- case TypeAction::UnorderedList:
- m_editor->typeUnorderedList();
- break;
- case TypeAction::OrderedList:
- m_editor->typeOrderedList();
- break;
- case TypeAction::TodoList:
- m_editor->typeTodoList(false);
- break;
- case TypeAction::CheckedTodoList:
- m_editor->typeTodoList(true);
- break;
- case TypeAction::Code:
- m_editor->typeCode();
- break;
- case TypeAction::CodeBlock:
- m_editor->typeCodeBlock();
- break;
- case TypeAction::Math:
- m_editor->typeMath();
- break;
- case TypeAction::MathBlock:
- m_editor->typeMathBlock();
- break;
- case TypeAction::Quote:
- m_editor->typeQuote();
- break;
- case TypeAction::Link:
- m_editor->typeLink();
- break;
- case TypeAction::Image:
- m_editor->typeImage();
- break;
- default:
- qWarning() << "TypeAction not handled" << p_action;
- break;
- }
- }
- void MarkdownViewWindow::handleSectionNumberOverride(OverrideState p_state)
- {
- if (m_mode != Mode::Read) {
- m_editor->overrideSectionNumber(p_state);
- }
- }
- void MarkdownViewWindow::detachFromBufferInternal()
- {
- auto buffer = getBuffer();
- if (buffer && buffer->getAttachViewWindowCount() == 1) {
- const auto state = buffer->state();
- if (state == Buffer::StateFlag::Normal || state == Buffer::StateFlag::Discarded) {
- // We are the last ViewWindow of this buffer. Clear obsolete images.
- clearObsoleteImages();
- }
- }
- }
- void MarkdownViewWindow::clearObsoleteImages()
- {
- const auto obsoleteImages = static_cast<MarkdownBuffer *>(getBuffer())->clearObsoleteImages();
- if (obsoleteImages.isEmpty()) {
- return;
- }
- auto buffer = getBuffer();
- Q_ASSERT(buffer);
- auto &markdownEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig();
- if (markdownEditorConfig.getConfirmBeforeClearObsoleteImages()) {
- QVector<ConfirmItemInfo> items;
- for (auto const &imgPath : obsoleteImages) {
- items.push_back(ConfirmItemInfo(imgPath, imgPath, imgPath, nullptr));
- }
- DeleteConfirmDialog dialog(tr("Clear Obsolete Images"),
- tr("These images seems not in use anymore. Please confirm the deletion of them."),
- tr("Deleted images could be found in the recycle bin of notebook if it is from a bundle notebook."),
- items,
- DeleteConfirmDialog::Flag::AskAgain | DeleteConfirmDialog::Flag::Preview,
- false,
- this);
- if (dialog.exec() == QDialog::Accepted) {
- items = dialog.getConfirmedItems();
- markdownEditorConfig.setConfirmBeforeClearObsoleteImages(!dialog.isNoAskChecked());
- for (const auto &item : items) {
- buffer->removeImage(item.m_path);
- }
- }
- } else {
- for (const auto &imgPath : obsoleteImages) {
- buffer->removeImage(imgPath);
- }
- }
- }
- QSharedPointer<OutlineProvider> MarkdownViewWindow::getOutlineProvider()
- {
- return m_outlineProvider;
- }
- template <class T>
- QSharedPointer<Outline> MarkdownViewWindow::headingsToOutline(const QVector<T> &p_headings)
- {
- auto outline = QSharedPointer<Outline>::create();
- if (!p_headings.isEmpty()) {
- outline->m_headings.reserve(p_headings.size());
- for (const auto &heading : p_headings) {
- outline->m_headings.push_back(Outline::Heading(heading.m_name, heading.m_level));
- }
- }
- return outline;
- }
- void MarkdownViewWindow::setupOutlineProvider()
- {
- m_outlineProvider.reset(new OutlineProvider(nullptr));
- connect(m_outlineProvider.data(), &OutlineProvider::headingClicked,
- this, [this](int p_idx) {
- switch (getMode()) {
- case Mode::Read:
- adapter()->scrollToHeading(p_idx);
- break;
- default:
- m_editor->scrollToHeading(p_idx);
- break;
- }
- });
- }
- QSharedPointer<vte::MarkdownEditorConfig> MarkdownViewWindow::createMarkdownEditorConfig(const MarkdownEditorConfig &p_config)
- {
- const auto &themeMgr = VNoteX::getInst().getThemeMgr();
- auto textEditorConfig = TextViewWindowHelper::createTextEditorConfig(p_config.getTextEditorConfig(),
- themeMgr.getFile(Theme::File::MarkdownEditorStyle),
- themeMgr.getMarkdownEditorHighlightTheme());
- auto editorConfig = QSharedPointer<vte::MarkdownEditorConfig>::create(textEditorConfig);
- editorConfig->m_constrainInPlacePreviewWidthEnabled = p_config.getConstrainInPlacePreviewWidthEnabled();
- return editorConfig;
- }
- void MarkdownViewWindow::scrollUp()
- {
- if (m_mode == Mode::Read) {
- adapter()->scroll(true);
- } else {
- QScrollBar *vbar = m_editor->getTextEdit()->verticalScrollBar();
- if (vbar && (vbar->minimum() != vbar->maximum())) {
- vbar->triggerAction(QAbstractSlider::SliderSingleStepAdd);
- }
- }
- }
- void MarkdownViewWindow::scrollDown()
- {
- if (m_mode == Mode::Read) {
- adapter()->scroll(false);
- } else {
- QScrollBar *vbar = m_editor->getTextEdit()->verticalScrollBar();
- if (vbar && (vbar->minimum() != vbar->maximum())) {
- vbar->triggerAction(QAbstractSlider::SliderSingleStepSub);
- }
- }
- }
- void MarkdownViewWindow::updateWebViewerConfig(const MarkdownEditorConfig &p_config)
- {
- if (!m_viewer) {
- return;
- }
- m_viewer->setZoomFactor(p_config.getZoomFactorInReadMode());
- }
- void MarkdownViewWindow::zoom(bool p_zoomIn)
- {
- // Only editor will receive the wheel event.
- Q_ASSERT(m_mode != Mode::Read);
- m_editor->zoom(m_editor->zoomDelta() + (p_zoomIn ? 1 : -1));
- auto &textEditorConfig = ConfigMgr::getInst().getEditorConfig().getMarkdownEditorConfig().getTextEditorConfig();
- textEditorConfig.setZoomDelta(m_editor->zoomDelta());
- showZoomDelta(m_editor->zoomDelta());
- }
- void MarkdownViewWindow::handleFindTextChanged(const QString &p_text, FindOptions p_options)
- {
- if (m_mode == Mode::Read) {
- adapter()->findText(p_text, p_options);
- } else {
- TextViewWindowHelper::handleFindTextChanged(this, p_text, p_options);
- }
- }
- void MarkdownViewWindow::handleFindNext(const QString &p_text, FindOptions p_options)
- {
- if (m_mode == Mode::Read) {
- if (p_options & FindOption::IncrementalSearch) {
- adapter()->findText(p_text, p_options);
- }
- } else {
- TextViewWindowHelper::handleFindNext(this, p_text, p_options);
- }
- }
- void MarkdownViewWindow::handleReplace(const QString &p_text, FindOptions p_options, const QString &p_replaceText)
- {
- if (m_mode == Mode::Read) {
- VNoteX::getInst().showStatusMessageShort(tr("Replace is not supported in read mode"));
- } else {
- TextViewWindowHelper::handleReplace(this, p_text, p_options, p_replaceText);
- }
- }
- void MarkdownViewWindow::handleReplaceAll(const QString &p_text, FindOptions p_options, const QString &p_replaceText)
- {
- if (m_mode == Mode::Read) {
- VNoteX::getInst().showStatusMessageShort(tr("Replace is not supported in read mode"));
- } else {
- TextViewWindowHelper::handleReplaceAll(this, p_text, p_options, p_replaceText);
- }
- }
- void MarkdownViewWindow::handleFindAndReplaceWidgetClosed()
- {
- if (m_editor) {
- TextViewWindowHelper::handleFindAndReplaceWidgetClosed(this);
- } else {
- adapter()->findText("", FindOption::None);
- }
- }
- void MarkdownViewWindow::handleFindAndReplaceWidgetOpened()
- {
- Q_ASSERT(m_findAndReplace);
- m_findAndReplace->setReplaceEnabled(m_mode != Mode::Read);
- }
|