diff --git a/src/core/editorconfig.h b/src/core/editorconfig.h index a81a79ac..0e6b2426 100644 --- a/src/core/editorconfig.h +++ b/src/core/editorconfig.h @@ -61,6 +61,7 @@ namespace vnotex Tag, Debug, Print, + ClearHighlights, MaxShortcut }; Q_ENUM(Shortcut) diff --git a/src/core/htmltemplatehelper.cpp b/src/core/htmltemplatehelper.cpp index 6321b3ee..d661cb4c 100644 --- a/src/core/htmltemplatehelper.cpp +++ b/src/core/htmltemplatehelper.cpp @@ -20,6 +20,7 @@ QString WebGlobalOptions::toJavascriptObject() const { return QStringLiteral("window.vxOptions = {\n") + QString("webPlantUml: %1,\n").arg(Utils::boolToString(m_webPlantUml)) + + QString("plantUmlWebService: '%1',\n").arg(m_plantUmlWebService) + QString("webGraphviz: %1,\n").arg(Utils::boolToString(m_webGraphviz)) + QString("mathJaxScript: '%1',\n").arg(m_mathJaxScript) + QString("constrainImageWidthEnabled: %1,\n").arg(Utils::boolToString(m_constrainImageWidthEnabled)) @@ -213,6 +214,7 @@ QString HtmlTemplateHelper::generateMarkdownViewerTemplate(const MarkdownEditorC { WebGlobalOptions opts; opts.m_webPlantUml = p_config.getWebPlantUml(); + opts.m_plantUmlWebService = p_config.getPlantUmlWebService(); opts.m_webGraphviz = p_config.getWebGraphviz(); opts.m_mathJaxScript = p_config.getMathJaxScript(); opts.m_sectionNumberEnabled = p_config.getSectionNumberMode() == MarkdownEditorConfig::SectionNumberMode::Read; diff --git a/src/core/htmltemplatehelper.h b/src/core/htmltemplatehelper.h index b725812f..9eba5d02 100644 --- a/src/core/htmltemplatehelper.h +++ b/src/core/htmltemplatehelper.h @@ -13,6 +13,8 @@ namespace vnotex { bool m_webPlantUml = true; + QString m_plantUmlWebService; + bool m_webGraphviz = true; QString m_mathJaxScript; diff --git a/src/core/markdowneditorconfig.cpp b/src/core/markdowneditorconfig.cpp index 7fd26cc8..7b6cef9c 100644 --- a/src/core/markdowneditorconfig.cpp +++ b/src/core/markdowneditorconfig.cpp @@ -35,6 +35,8 @@ void MarkdownEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_u m_plantUmlCommand = READSTR(QStringLiteral("plantuml_command")); + m_plantUmlWebService = READSTR(QStringLiteral("plantuml_web_service")); + m_webGraphviz = READBOOL(QStringLiteral("web_graphviz")); m_graphvizExe = READSTR(QStringLiteral("graphviz_exe")); @@ -90,6 +92,7 @@ QJsonObject MarkdownEditorConfig::toJson() const obj[QStringLiteral("web_plantuml")] = m_webPlantUml; obj[QStringLiteral("plantuml_jar")] = m_plantUmlJar; obj[QStringLiteral("plantuml_command")] = m_plantUmlCommand; + obj[QStringLiteral("plantuml_web_service")] = m_plantUmlWebService; obj[QStringLiteral("web_graphviz")] = m_webGraphviz; obj[QStringLiteral("graphviz_exe")] = m_graphvizExe; obj[QStringLiteral("mathjax_script")] = m_mathJaxScript; @@ -238,6 +241,16 @@ const QString &MarkdownEditorConfig::getPlantUmlCommand() const return m_plantUmlCommand; } +const QString &MarkdownEditorConfig::getPlantUmlWebService() const +{ + return m_plantUmlWebService; +} + +void MarkdownEditorConfig::setPlantUmlWebService(const QString &p_service) +{ + updateConfig(m_plantUmlWebService, p_service, this); +} + bool MarkdownEditorConfig::getWebGraphviz() const { return m_webGraphviz; @@ -280,9 +293,7 @@ bool MarkdownEditorConfig::getConfirmBeforeClearObsoleteImages() const void MarkdownEditorConfig::setConfirmBeforeClearObsoleteImages(bool p_confirm) { - updateConfig(m_confirmBeforeClearObsoleteImages, - p_confirm, - this); + updateConfig(m_confirmBeforeClearObsoleteImages, p_confirm, this); } bool MarkdownEditorConfig::getInsertFileNameAsTitle() const diff --git a/src/core/markdowneditorconfig.h b/src/core/markdowneditorconfig.h index 9cbead37..97d2701c 100644 --- a/src/core/markdowneditorconfig.h +++ b/src/core/markdowneditorconfig.h @@ -70,6 +70,9 @@ namespace vnotex const QString &getPlantUmlCommand() const; + const QString &getPlantUmlWebService() const; + void setPlantUmlWebService(const QString &p_service); + bool getWebGraphviz() const; void setWebGraphviz(bool p_enabled); @@ -185,6 +188,9 @@ namespace vnotex // %1: the format to render in. QString m_plantUmlCommand; + // PlantUml Web service to override that in plantuml.js file. + QString m_plantUmlWebService; + bool m_webGraphviz = true; // Graphviz executable file. diff --git a/src/data/core/vnotex.json b/src/data/core/vnotex.json index 41cfe8f9..36e75770 100644 --- a/src/data/core/vnotex.json +++ b/src/data/core/vnotex.json @@ -208,7 +208,8 @@ "ApplySnippet" : "Ctrl+G, I", "Tag" : "Ctrl+G, B", "Debug" : "F12", - "Print" : "" + "Print" : "", + "ClearHighlights" : "Ctrl+G, Space" }, "spell_check_auto_detect_language" : false, "spell_check_default_dictionary" : "en_US", @@ -401,6 +402,8 @@ "//commnet" : "Command to render PlantUML via stdin and stdout (overrides plantuml_jar)", "//commnet" : "- %1: the format to render in", "plantuml_command" : "", + "//commnet" : "PlantUml Web service to use", + "plantuml_web_service" : "", "//comment" : "Whether use javascript or external program to render Graphviz", "web_graphviz" : true, "//commnet" : "Local Graphviz executable file to render Graphviz", diff --git a/src/data/extra/web/js/plantuml.js b/src/data/extra/web/js/plantuml.js index fb981958..af2ae798 100644 --- a/src/data/extra/web/js/plantuml.js +++ b/src/data/extra/web/js/plantuml.js @@ -34,6 +34,18 @@ class PlantUml extends GraphRenderer { } } + initialize(p_callback) { + if (super.initialized) { + return true; + } + + if (!!window.vxOptions.plantUmlWebService) { + this.serverUrl = window.vxOptions.plantUmlWebService; + console.log('override PlantUml Web service', this.serverUrl); + } + + return super.initialize(p_callback); + } // Interface 1. render(p_node, p_format) { diff --git a/src/widgets/dialogs/settings/fileassociationpage.cpp b/src/widgets/dialogs/settings/fileassociationpage.cpp index 0ea114b0..a19e7e89 100644 --- a/src/widgets/dialogs/settings/fileassociationpage.cpp +++ b/src/widgets/dialogs/settings/fileassociationpage.cpp @@ -62,7 +62,7 @@ bool FileAssociationPage::saveInternal() if (name.isEmpty()) { continue; } - auto suffixes = lineEdit->text().split(c_suffixSeparator, Qt::SkipEmptyParts); + auto suffixes = lineEdit->text().split(c_suffixSeparator, QString::SkipEmptyParts); fileTypeSuffixes.push_back(CoreConfig::FileTypeSuffix(name, Utils::toLower(suffixes))); } diff --git a/src/widgets/dialogs/settings/markdowneditorpage.cpp b/src/widgets/dialogs/settings/markdowneditorpage.cpp index 53dd596d..e167ea91 100644 --- a/src/widgets/dialogs/settings/markdowneditorpage.cpp +++ b/src/widgets/dialogs/settings/markdowneditorpage.cpp @@ -104,6 +104,8 @@ void MarkdownEditorPage::loadInternal() m_plantUmlJarFileInput->setText(markdownConfig.getPlantUmlJar()); + m_plantUmlWebServiceLineEdit->setText(markdownConfig.getPlantUmlWebService()); + { int idx = m_graphvizModeComboBox->findData(markdownConfig.getWebGraphviz() ? 0 : 1); m_graphvizModeComboBox->setCurrentIndex(idx); @@ -189,6 +191,8 @@ bool MarkdownEditorPage::saveInternal() markdownConfig.setPlantUmlJar(m_plantUmlJarFileInput->text()); + markdownConfig.setPlantUmlWebService(m_plantUmlWebServiceLineEdit->text()); + markdownConfig.setWebGraphviz(m_graphvizModeComboBox->currentData().toInt() == 0); markdownConfig.setGraphvizExe(m_graphvizFileInput->text()); @@ -468,9 +472,9 @@ QGroupBox *MarkdownEditorPage::setupGeneralGroup() { m_plantUmlModeComboBox = WidgetsFactory::createComboBox(box); - m_plantUmlModeComboBox->setToolTip(tr("Use online service or local JAR file to render PlantUml graphs")); + m_plantUmlModeComboBox->setToolTip(tr("Use Web service or local JAR file to render PlantUml graphs")); - m_plantUmlModeComboBox->addItem(tr("Online Service"), 0); + m_plantUmlModeComboBox->addItem(tr("Web Service"), 0); m_plantUmlModeComboBox->addItem(tr("Local JAR"), 1); const QString label(tr("PlantUml:")); @@ -527,10 +531,21 @@ QGroupBox *MarkdownEditorPage::setupGeneralGroup() } { - m_graphvizModeComboBox = WidgetsFactory::createComboBox(box); - m_graphvizModeComboBox->setToolTip(tr("Use online service or local executable file to render Graphviz graphs")); + m_plantUmlWebServiceLineEdit = WidgetsFactory::createLineEdit(box); + m_plantUmlWebServiceLineEdit->setToolTip(tr("Override the Web service used to render PlantUml graphs")); - m_graphvizModeComboBox->addItem(tr("Online Service"), 0); + const QString label(tr("PlantUml Web service:")); + layout->addRow(label, m_plantUmlWebServiceLineEdit); + addSearchItem(label, m_plantUmlWebServiceLineEdit->toolTip(), m_plantUmlWebServiceLineEdit); + connect(m_plantUmlWebServiceLineEdit, &QLineEdit::textChanged, + this, &MarkdownEditorPage::pageIsChanged); + } + + { + m_graphvizModeComboBox = WidgetsFactory::createComboBox(box); + m_graphvizModeComboBox->setToolTip(tr("Use Web service or local executable file to render Graphviz graphs")); + + m_graphvizModeComboBox->addItem(tr("Web Service"), 0); m_graphvizModeComboBox->addItem(tr("Local Executable"), 1); const QString label(tr("Graphviz:")); diff --git a/src/widgets/dialogs/settings/markdowneditorpage.h b/src/widgets/dialogs/settings/markdowneditorpage.h index 4b689523..8f65c95c 100644 --- a/src/widgets/dialogs/settings/markdowneditorpage.h +++ b/src/widgets/dialogs/settings/markdowneditorpage.h @@ -79,6 +79,8 @@ namespace vnotex LocationInputWithBrowseButton *m_plantUmlJarFileInput = nullptr; + QLineEdit *m_plantUmlWebServiceLineEdit = nullptr; + QComboBox *m_graphvizModeComboBox = nullptr; LocationInputWithBrowseButton *m_graphvizFileInput = nullptr; diff --git a/src/widgets/dialogs/settings/settingsdialog.cpp b/src/widgets/dialogs/settings/settingsdialog.cpp index 7d2c20be..4aeff09a 100644 --- a/src/widgets/dialogs/settings/settingsdialog.cpp +++ b/src/widgets/dialogs/settings/settingsdialog.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -37,6 +39,9 @@ SettingsDialog::SettingsDialog(QWidget *p_parent) setupUI(); setupPages(); + + connect(this, &QDialog::finished, + this, &SettingsDialog::checkOnFinish); } void SettingsDialog::setupUI() @@ -315,3 +320,25 @@ void SettingsDialog::search() return true; }); } + +void SettingsDialog::checkOnFinish() +{ + // Check whether need to prompt for restart. + forEachPage([this](const SettingsPage *p_page) { + if (p_page->isRestartNeeded()) { + // Restart VNote. + int ret = MessageBoxHelper::questionYesNo(MessageBoxHelper::Type::Information, + tr("A restart of VNote may be needed to make changes take effect. Restart VNote now?"), + QString(), + QString(), + this); + if (ret == QMessageBox::Yes) { + QMetaObject::invokeMethod(VNoteX::getInst().getMainWindow(), + &MainWindow::restart, + Qt::QueuedConnection); + } + return false; + } + return true; + }); +} diff --git a/src/widgets/dialogs/settings/settingsdialog.h b/src/widgets/dialogs/settings/settingsdialog.h index 545dc84f..fa567bfe 100644 --- a/src/widgets/dialogs/settings/settingsdialog.h +++ b/src/widgets/dialogs/settings/settingsdialog.h @@ -53,6 +53,8 @@ namespace vnotex void search(); + void checkOnFinish(); + QLineEdit *m_searchEdit = nullptr; TreeWidget *m_pageExplorer = nullptr; diff --git a/src/widgets/dialogs/settings/settingspage.cpp b/src/widgets/dialogs/settings/settingspage.cpp index 3a906849..34a895d9 100644 --- a/src/widgets/dialogs/settings/settingspage.cpp +++ b/src/widgets/dialogs/settings/settingspage.cpp @@ -78,6 +78,8 @@ bool SettingsPage::save() if (saveInternal()) { m_changed = false; + // TODO: may need finer-grain check. + m_restartNeeded = true; return true; } @@ -102,3 +104,8 @@ void SettingsPage::setError(const QString &p_err) { m_error = p_err; } + +bool SettingsPage::isRestartNeeded() const +{ + return m_restartNeeded; +} diff --git a/src/widgets/dialogs/settings/settingspage.h b/src/widgets/dialogs/settings/settingspage.h index 937fce22..fe663f69 100644 --- a/src/widgets/dialogs/settings/settingspage.h +++ b/src/widgets/dialogs/settings/settingspage.h @@ -25,6 +25,8 @@ namespace vnotex const QString &error() const; + bool isRestartNeeded() const; + signals: void changed(); @@ -64,6 +66,8 @@ namespace vnotex bool m_changed = false; + bool m_restartNeeded = false; + QString m_error; }; } diff --git a/src/widgets/mainwindow.cpp b/src/widgets/mainwindow.cpp index 77609fe6..ab9f1702 100644 --- a/src/widgets/mainwindow.cpp +++ b/src/widgets/mainwindow.cpp @@ -389,6 +389,7 @@ void MainWindow::closeEvent(QCloseEvent *p_event) showNormal(); } } + saveStateAndGeometry(); } @@ -408,6 +409,8 @@ void MainWindow::closeEvent(QCloseEvent *p_event) FramelessMainWindowImpl::closeEvent(p_event); qApp->exit(exitCode > -1 ? exitCode : 0); } else { + emit minimizedToSystemTray(); + hide(); p_event->ignore(); if (needShowMessage) { diff --git a/src/widgets/mainwindow.h b/src/widgets/mainwindow.h index 8175c007..5b6ef2af 100644 --- a/src/widgets/mainwindow.h +++ b/src/widgets/mainwindow.h @@ -85,6 +85,8 @@ namespace vnotex // @m_response of @p_event: true to continue the close, false to stop the close. void mainWindowClosed(const QSharedPointer &p_event); + void minimizedToSystemTray(); + // No user interaction is available. void mainWindowClosedOnQuit(); diff --git a/src/widgets/markdownviewwindow.cpp b/src/widgets/markdownviewwindow.cpp index f982a13f..06052209 100644 --- a/src/widgets/markdownviewwindow.cpp +++ b/src/widgets/markdownviewwindow.cpp @@ -1025,10 +1025,19 @@ void MarkdownViewWindow::handleReplaceAll(const QString &p_text, FindOptions p_o void MarkdownViewWindow::handleFindAndReplaceWidgetClosed() { - if (m_editor) { - TextViewWindowHelper::handleFindAndReplaceWidgetClosed(this); - } else { + if (isReadMode()) { adapter()->findText(QStringList(), FindOption::FindNone); + } else { + TextViewWindowHelper::clearSearchHighlights(this); + } +} + +void MarkdownViewWindow::clearHighlights() +{ + if (isReadMode()) { + adapter()->findText(QStringList(), FindOption::FindNone); + } else { + TextViewWindowHelper::clearSearchHighlights(this); } } diff --git a/src/widgets/markdownviewwindow.h b/src/widgets/markdownviewwindow.h index 8b4d47f7..4bc84548 100644 --- a/src/widgets/markdownviewwindow.h +++ b/src/widgets/markdownviewwindow.h @@ -86,6 +86,8 @@ namespace vnotex void print() Q_DECL_OVERRIDE; + void clearHighlights() Q_DECL_OVERRIDE; + protected: void syncEditorFromBuffer() Q_DECL_OVERRIDE; diff --git a/src/widgets/textviewwindow.cpp b/src/widgets/textviewwindow.cpp index 8e956c51..44ffda11 100644 --- a/src/widgets/textviewwindow.cpp +++ b/src/widgets/textviewwindow.cpp @@ -241,7 +241,7 @@ void TextViewWindow::handleReplaceAll(const QString &p_text, FindOptions p_optio void TextViewWindow::handleFindAndReplaceWidgetClosed() { - TextViewWindowHelper::handleFindAndReplaceWidgetClosed(this); + TextViewWindowHelper::clearSearchHighlights(this); } void TextViewWindow::updateEditorFromConfig() @@ -317,3 +317,8 @@ void TextViewWindow::print() m_editor->getTextEdit()->print(printer.data()); } } + +void TextViewWindow::clearHighlights() +{ + TextViewWindowHelper::clearSearchHighlights(this); +} diff --git a/src/widgets/textviewwindow.h b/src/widgets/textviewwindow.h index be409f1c..52ebcfc4 100644 --- a/src/widgets/textviewwindow.h +++ b/src/widgets/textviewwindow.h @@ -70,6 +70,8 @@ namespace vnotex QPoint getFloatingWidgetPosition() Q_DECL_OVERRIDE; + void clearHighlights() Q_DECL_OVERRIDE; + private: void setupUI(); diff --git a/src/widgets/textviewwindowhelper.h b/src/widgets/textviewwindowhelper.h index c7e04e23..1e3e51a3 100644 --- a/src/widgets/textviewwindowhelper.h +++ b/src/widgets/textviewwindowhelper.h @@ -213,7 +213,7 @@ namespace vnotex } template - static void handleFindAndReplaceWidgetClosed(_ViewWindow *p_win) + static void clearSearchHighlights(_ViewWindow *p_win) { p_win->m_editor->clearIncrementalSearchHighlight(); p_win->m_editor->clearSearchHighlight(); diff --git a/src/widgets/viewarea.cpp b/src/widgets/viewarea.cpp index b94b06bc..92eaf30f 100644 --- a/src/widgets/viewarea.cpp +++ b/src/widgets/viewarea.cpp @@ -67,6 +67,13 @@ ViewArea::ViewArea(QWidget *p_parent) p_event->m_handled = true; } }); + connect(mainWindow, &MainWindow::minimizedToSystemTray, + this, [this]() { + if (ConfigMgr::getInst().getCoreConfig().isRecoverLastSessionOnStartEnabled()) { + // Save it here, too. Avoid losing session when VNote is closed unexpectedly. + saveSession(); + } + }); connect(mainWindow, &MainWindow::mainWindowClosedOnQuit, this, [this]() { diff --git a/src/widgets/viewwindow.cpp b/src/widgets/viewwindow.cpp index 363423b1..e2c8506a 100644 --- a/src/widgets/viewwindow.cpp +++ b/src/widgets/viewwindow.cpp @@ -1001,6 +1001,17 @@ void ViewWindow::setupShortcuts() }); } } + + // ClearHighlights. + { + auto shortcut = WidgetUtils::createShortcut(editorConfig.getShortcut(EditorConfig::ClearHighlights), this, Qt::WidgetWithChildrenShortcut); + if (shortcut) { + connect(shortcut, &QShortcut::activated, + this, [this]() { + clearHighlights(); + }); + } + } } void ViewWindow::wheelEvent(QWheelEvent *p_event) @@ -1345,3 +1356,7 @@ void ViewWindow::print() { qWarning() << "print is not supported"; } + +void ViewWindow::clearHighlights() +{ +} diff --git a/src/widgets/viewwindow.h b/src/widgets/viewwindow.h index 14157031..da8e1f3d 100644 --- a/src/widgets/viewwindow.h +++ b/src/widgets/viewwindow.h @@ -256,6 +256,8 @@ namespace vnotex virtual void updateViewModeMenu(QMenu *p_menu); + virtual void clearHighlights(); + static QToolBar *createToolBar(QWidget *p_parent = nullptr); // The revision of the buffer of the last sync content.