From ff79533fa019a7d1ad5fc6b44a902ae32018c83d Mon Sep 17 00:00:00 2001 From: Le Tan Date: Fri, 18 Jun 2021 20:46:30 +0800 Subject: [PATCH] support external programs --- src/core/coreconfig.h | 1 + src/core/sessionconfig.cpp | 62 +++++++-- src/core/sessionconfig.h | 24 +++- src/data/core/vnotex.json | 3 +- src/data/extra/docs/en/external_programs.md | 30 ++++ .../extra/docs/zh_CN/external_programs.md | 30 ++++ src/data/extra/extra.qrc | 2 + src/export/webviewexporter.cpp | 4 +- src/utils/processutils.cpp | 9 ++ src/utils/processutils.h | 2 + src/utils/widgetutils.cpp | 4 + src/widgets/dialogs/exportdialog.cpp | 2 +- src/widgets/dialogs/settings/miscpage.cpp | 36 +++++ src/widgets/dialogs/settings/miscpage.h | 26 ++++ .../dialogs/settings/settingsdialog.cpp | 9 ++ src/widgets/notebooknodeexplorer.cpp | 130 ++++++++++++++++++ src/widgets/notebooknodeexplorer.h | 10 ++ src/widgets/viewsplit.cpp | 19 +++ src/widgets/viewwindow.cpp | 25 +++- src/widgets/viewwindow.h | 14 ++ src/widgets/widgets.pri | 2 + 21 files changed, 423 insertions(+), 21 deletions(-) create mode 100644 src/data/extra/docs/en/external_programs.md create mode 100644 src/data/extra/docs/zh_CN/external_programs.md create mode 100644 src/widgets/dialogs/settings/miscpage.cpp create mode 100644 src/widgets/dialogs/settings/miscpage.h diff --git a/src/core/coreconfig.h b/src/core/coreconfig.h index c5caa6b0..e827eb73 100644 --- a/src/core/coreconfig.h +++ b/src/core/coreconfig.h @@ -51,6 +51,7 @@ namespace vnotex ActivateNextTab, ActivatePreviousTab, FocusContentArea, + OpenWithDefaultProgram, MaxShortcut }; Q_ENUM(Shortcut) diff --git a/src/core/sessionconfig.cpp b/src/core/sessionconfig.cpp index 452d85d7..157ddbca 100644 --- a/src/core/sessionconfig.cpp +++ b/src/core/sessionconfig.cpp @@ -37,6 +37,24 @@ QJsonObject SessionConfig::NotebookItem::toJson() const return jobj; } +void SessionConfig::ExternalProgram::fromJson(const QJsonObject &p_jobj) +{ + m_name = p_jobj[QStringLiteral("name")].toString(); + m_command = p_jobj[QStringLiteral("command")].toString(); + m_shortcut = p_jobj[QStringLiteral("shortcut")].toString(); +} + +QJsonObject SessionConfig::ExternalProgram::toJson() const +{ + QJsonObject jobj; + + jobj[QStringLiteral("name")] = m_name; + jobj[QStringLiteral("command")] = m_command; + jobj[QStringLiteral("shortcut")] = m_shortcut; + + return jobj; +} + SessionConfig::SessionConfig(ConfigMgr *p_mgr) : IConfig(p_mgr, nullptr) { @@ -57,10 +75,6 @@ void SessionConfig::init() loadStateAndGeometry(sessionJobj); - if (MainConfig::isVersionChanged()) { - doVersionSpecificOverride(); - } - m_exportOption.fromJson(sessionJobj[QStringLiteral("export_option")].toObject()); m_searchOption.fromJson(sessionJobj[QStringLiteral("search_option")].toObject()); @@ -68,6 +82,14 @@ void SessionConfig::init() m_viewAreaSession = readByteArray(sessionJobj, QStringLiteral("viewarea_session")); m_notebookExplorerSession = readByteArray(sessionJobj, QStringLiteral("notebook_explorer_session")); + + loadExternalPrograms(sessionJobj); + + loadNotebooks(sessionJobj); + + if (MainConfig::isVersionChanged()) { + doVersionSpecificOverride(); + } } void SessionConfig::loadCore(const QJsonObject &p_session) @@ -128,14 +150,8 @@ void SessionConfig::setNewNotebookDefaultRootFolderPath(const QString &p_path) this); } -const QVector &SessionConfig::getNotebooks() +const QVector &SessionConfig::getNotebooks() const { - if (m_notebooks.isEmpty()) { - auto mgr = getMgr(); - auto sessionSettings = mgr->getSettings(ConfigMgr::Source::Session); - const auto &sessionJobj = sessionSettings->getJson(); - loadNotebooks(sessionJobj); - } return m_notebooks; } @@ -191,6 +207,7 @@ QJsonObject SessionConfig::toJson() const obj[QStringLiteral("search_option")] = m_searchOption.toJson(); writeByteArray(obj, QStringLiteral("viewarea_session"), m_viewAreaSession); writeByteArray(obj, QStringLiteral("notebook_explorer_session"), m_notebookExplorerSession); + obj[QStringLiteral("external_programs")] = saveExternalPrograms(); return obj; } @@ -365,3 +382,26 @@ void SessionConfig::setQuickAccessFiles(const QStringList &p_files) { updateConfig(m_quickAccessFiles, p_files, this); } + +void SessionConfig::loadExternalPrograms(const QJsonObject &p_session) +{ + const auto arr = p_session.value(QStringLiteral("external_programs")).toArray(); + m_externalPrograms.resize(arr.size()); + for (int i = 0; i < arr.size(); ++i) { + m_externalPrograms[i].fromJson(arr[i].toObject()); + } +} + +QJsonArray SessionConfig::saveExternalPrograms() const +{ + QJsonArray arr; + for (const auto &pro : m_externalPrograms) { + arr.append(pro.toJson()); + } + return arr; +} + +const QVector &SessionConfig::getExternalPrograms() const +{ + return m_externalPrograms; +} diff --git a/src/core/sessionconfig.h b/src/core/sessionconfig.h index 603b34d7..6ca93f63 100644 --- a/src/core/sessionconfig.h +++ b/src/core/sessionconfig.h @@ -53,6 +53,20 @@ namespace vnotex Software }; + struct ExternalProgram + { + void fromJson(const QJsonObject &p_jobj); + + QJsonObject toJson() const; + + QString m_name; + + // %1: the file paths to open. + QString m_command; + + QString m_shortcut; + }; + explicit SessionConfig(ConfigMgr *p_mgr); ~SessionConfig(); @@ -65,7 +79,7 @@ namespace vnotex const QString &getCurrentNotebookRootFolderPath() const; void setCurrentNotebookRootFolderPath(const QString &p_path); - const QVector &getNotebooks(); + const QVector &getNotebooks() const; void setNotebooks(const QVector &p_notebooks); void writeToSettings() const Q_DECL_OVERRIDE; @@ -107,6 +121,8 @@ namespace vnotex const QStringList &getQuickAccessFiles() const; void setQuickAccessFiles(const QStringList &p_files); + const QVector &getExternalPrograms() const; + private: void loadCore(const QJsonObject &p_session); @@ -120,6 +136,10 @@ namespace vnotex QJsonObject saveStateAndGeometry() const; + void loadExternalPrograms(const QJsonObject &p_session); + + QJsonArray saveExternalPrograms() const; + void doVersionSpecificOverride(); QString m_newNotebookDefaultRootFolderPath; @@ -153,6 +173,8 @@ namespace vnotex QString m_flashPage; QStringList m_quickAccessFiles; + + QVector m_externalPrograms; }; } // ns vnotex diff --git a/src/data/core/vnotex.json b/src/data/core/vnotex.json index b00b4e9b..564f4fcb 100644 --- a/src/data/core/vnotex.json +++ b/src/data/core/vnotex.json @@ -44,7 +44,8 @@ "AlternateTab" : "Ctrl+G, 0", "ActivateNextTab" : "Ctrl+G, N", "ActivatePreviousTab" : "Ctrl+G, P", - "FocusContentArea" : "Ctrl+G, Y" + "FocusContentArea" : "Ctrl+G, Y", + "OpenWithDefaultProgram" : "F9" }, "toolbar_icon_size" : 16, "note_management" : { diff --git a/src/data/extra/docs/en/external_programs.md b/src/data/extra/docs/en/external_programs.md new file mode 100644 index 00000000..7c44a7cb --- /dev/null +++ b/src/data/extra/docs/en/external_programs.md @@ -0,0 +1,30 @@ +# External Programs +VNote allows user to open notes with **external programs** via the `Open With` in the context menu of the node explorer. + +To add custom external programs, user needs to edit the session configuration. A sample may look like this: + +```json +{ + "external_programs": [ + { + "name" : "gvim", + "command" : "C:\\\"Program Files (x86)\"\\Vim\\vim80\\gvim.exe %1", + "shortcut" : "F4" + }, + { + "name" : "notepad", + "command" : "notepad %1", + "shortcut" : "" + } + ] +} +``` + +An external program could have 3 properties: + +1. `name`: the name of the program in VNote; +2. `command`: the command to execute when opening notes with this external program; + 1. Use `%1` as a placeholder which will be replaced by the real file paths (automatically wrapped by double quotes); +3. `shortcut`: the shortcut assigned to this external program; + +Close VNote before editting the session configuration. diff --git a/src/data/extra/docs/zh_CN/external_programs.md b/src/data/extra/docs/zh_CN/external_programs.md new file mode 100644 index 00000000..f319ecdf --- /dev/null +++ b/src/data/extra/docs/zh_CN/external_programs.md @@ -0,0 +1,30 @@ +# 外部程序 +VNote 支持通过在节点浏览器上下文菜单中的 `打开方式` 来调用 **外部程序** 打开笔记。 + +用户需要编辑会话配置来添加自定义外部程序。一个例子如下: + +```json +{ + "external_programs": [ + { + "name" : "gvim", + "command" : "C:\\\"Program Files (x86)\"\\Vim\\vim80\\gvim.exe %1", + "shortcut" : "F4" + }, + { + "name" : "notepad", + "command" : "notepad %1", + "shortcut" : "" + } + ] +} +``` + +一个外部程序可以包含3个属性: + +1. `name`: 该程序在 VNote 中的名字; +2. `command`: 当使用该外部程序打开笔记时执行的命令; + 1. 使用 `%1` 占位符,会被替换为真实的文件路径(自动加上双引号包裹); +3. `shortcut`: 分配给该外部程序的快捷键; + +修改配置前请关闭 VNote。 diff --git a/src/data/extra/extra.qrc b/src/data/extra/extra.qrc index 3fa07841..2bf112fe 100644 --- a/src/data/extra/extra.qrc +++ b/src/data/extra/extra.qrc @@ -4,10 +4,12 @@ docs/en/about_vnotex.txt docs/en/shortcuts.md docs/en/markdown_guide.md + docs/en/external_programs.md docs/zh_CN/get_started.txt docs/zh_CN/about_vnotex.txt docs/zh_CN/shortcuts.md docs/zh_CN/markdown_guide.md + docs/zh_CN/external_programs.md web/markdown-viewer-template.html web/markdown-export-template.html web/css/globalstyles.css diff --git a/src/export/webviewexporter.cpp b/src/export/webviewexporter.cpp index e7b8494d..3dee05cb 100644 --- a/src/export/webviewexporter.cpp +++ b/src/export/webviewexporter.cpp @@ -333,7 +333,9 @@ void WebViewExporter::prepareWkhtmltopdfArguments(const ExportPdfOption &p_pdfOp // Must be put after the global object options. if (p_pdfOption.m_addTableOfContents) { - m_wkhtmltopdfArgs << "toc" << "--toc-text-size-shrink" << "1.0"; + m_wkhtmltopdfArgs << "toc"; + m_wkhtmltopdfArgs << "--toc-text-size-shrink" << "1.0"; + m_wkhtmltopdfArgs << "--toc-header-text" << tr("Table of Contents"); } } diff --git a/src/utils/processutils.cpp b/src/utils/processutils.cpp index 5a32683d..6fb9f1b1 100644 --- a/src/utils/processutils.cpp +++ b/src/utils/processutils.cpp @@ -156,3 +156,12 @@ ProcessUtils::State ProcessUtils::start(const QString &p_program, return proc.exitStatus() == QProcess::NormalExit ? State::Succeeded : State::Crashed; } + +void ProcessUtils::startDetached(const QString &p_command) +{ + Q_ASSERT(!p_command.isEmpty()); + auto process = new QProcess(); + QObject::connect(process, QOverload::of(&QProcess::finished), + process, &QProcess::deleteLater); + process->start(p_command); +} diff --git a/src/utils/processutils.h b/src/utils/processutils.h index a04b47c4..6cffd416 100644 --- a/src/utils/processutils.h +++ b/src/utils/processutils.h @@ -35,6 +35,8 @@ namespace vnotex const std::function &p_logger, const bool &p_askedToStop); + static void startDetached(const QString &p_command); + // Copied from QProcess code. static QStringList parseCombinedArgString(const QString &p_args); diff --git a/src/utils/widgetutils.cpp b/src/utils/widgetutils.cpp index af7da07a..4e07c9db 100644 --- a/src/utils/widgetutils.cpp +++ b/src/utils/widgetutils.cpp @@ -175,6 +175,10 @@ void WidgetUtils::addActionShortcut(QAction *p_action, void WidgetUtils::addActionShortcutText(QAction *p_action, const QString &p_shortcut) { + if (p_shortcut.isEmpty()) { + return; + } + QKeySequence kseq(p_shortcut); if (kseq.isEmpty()) { return; diff --git a/src/widgets/dialogs/exportdialog.cpp b/src/widgets/dialogs/exportdialog.cpp index 9e718064..b64bead3 100644 --- a/src/widgets/dialogs/exportdialog.cpp +++ b/src/widgets/dialogs/exportdialog.cpp @@ -612,7 +612,7 @@ QWidget *ExportDialog::getPdfAdvancedSettings() } { - m_addTableOfContentsCheckBox = WidgetsFactory::createCheckBox(tr("Add Table-Of-Contents"), widget); + m_addTableOfContentsCheckBox = WidgetsFactory::createCheckBox(tr("Add Table-of-Contents"), widget); layout->addRow(m_addTableOfContentsCheckBox); } diff --git a/src/widgets/dialogs/settings/miscpage.cpp b/src/widgets/dialogs/settings/miscpage.cpp new file mode 100644 index 00000000..3163583e --- /dev/null +++ b/src/widgets/dialogs/settings/miscpage.cpp @@ -0,0 +1,36 @@ +#include "miscpage.h" + +#include + +#include +#include +#include +#include +#include + +using namespace vnotex; + +MiscPage::MiscPage(QWidget *p_parent) + : SettingsPage(p_parent) +{ + setupUI(); +} + +void MiscPage::setupUI() +{ +} + +void MiscPage::loadInternal() +{ + +} + +void MiscPage::saveInternal() +{ + +} + +QString MiscPage::title() const +{ + return tr("Misc"); +} diff --git a/src/widgets/dialogs/settings/miscpage.h b/src/widgets/dialogs/settings/miscpage.h new file mode 100644 index 00000000..fc39d3c0 --- /dev/null +++ b/src/widgets/dialogs/settings/miscpage.h @@ -0,0 +1,26 @@ +#ifndef MISCPAGE_H +#define MISCPAGE_H + +#include "settingspage.h" + +namespace vnotex +{ + class MiscPage : public SettingsPage + { + Q_OBJECT + public: + explicit MiscPage(QWidget *p_parent = nullptr); + + QString title() const Q_DECL_OVERRIDE; + + protected: + void loadInternal() Q_DECL_OVERRIDE; + + void saveInternal() Q_DECL_OVERRIDE; + + private: + void setupUI(); + }; +} + +#endif // MISCPAGE_H diff --git a/src/widgets/dialogs/settings/settingsdialog.cpp b/src/widgets/dialogs/settings/settingsdialog.cpp index a3dba929..e37bf713 100644 --- a/src/widgets/dialogs/settings/settingsdialog.cpp +++ b/src/widgets/dialogs/settings/settingsdialog.cpp @@ -10,6 +10,7 @@ #include #include "generalpage.h" +#include "miscpage.h" #include "editorpage.h" #include "texteditorpage.h" #include "markdowneditorpage.h" @@ -123,6 +124,14 @@ void SettingsDialog::setupPages() } } + // Misc. + { + /* + auto page = new MiscPage(this); + addPage(page); + */ + } + setChangesUnsaved(false); m_pageExplorer->setCurrentItem(m_pageExplorer->topLevelItem(0), 0, QItemSelectionModel::ClearAndSelect); m_pageExplorer->expandAll(); diff --git a/src/widgets/notebooknodeexplorer.cpp b/src/widgets/notebooknodeexplorer.cpp index 870f9246..44bcdfc6 100644 --- a/src/widgets/notebooknodeexplorer.cpp +++ b/src/widgets/notebooknodeexplorer.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -16,6 +17,8 @@ #include "vnotex.h" #include "mainwindow.h" #include +#include +#include #include "treewidget.h" #include "dialogs/notepropertiesdialog.h" #include "dialogs/folderpropertiesdialog.h" @@ -31,6 +34,8 @@ #include #include #include +#include +#include using namespace vnotex; @@ -177,6 +182,8 @@ NotebookNodeExplorer::NotebookNodeExplorer(QWidget *p_parent) initNodeIcons(); setupUI(); + + setupShortcuts(); } void NotebookNodeExplorer::initNodeIcons() const @@ -793,6 +800,10 @@ void NotebookNodeExplorer::createContextMenuOnNode(QMenu *p_menu, const Node *p_ act = createAction(Action::Open, p_menu); p_menu->addAction(act); + addOpenWithMenu(p_menu); + + p_menu->addSeparator(); + if (selectedSize == 1 && p_node->isContainer()) { act = createAction(Action::ExpandAll, p_menu); p_menu->addAction(act); @@ -827,6 +838,10 @@ void NotebookNodeExplorer::createContextMenuOnNode(QMenu *p_menu, const Node *p_ act = createAction(Action::Open, p_menu); p_menu->addAction(act); + addOpenWithMenu(p_menu); + + p_menu->addSeparator(); + if (selectedSize == 1 && p_node->isContainer()) { act = createAction(Action::ExpandAll, p_menu); p_menu->addAction(act); @@ -902,6 +917,10 @@ void NotebookNodeExplorer::createContextMenuOnExternalNode(QMenu *p_menu, const act = createAction(Action::Open, p_menu); p_menu->addAction(act); + addOpenWithMenu(p_menu); + + p_menu->addSeparator(); + act = createAction(Action::ImportToConfig, p_menu); p_menu->addAction(act); @@ -1831,6 +1850,27 @@ void NotebookNodeExplorer::openSelectedNodes() } } +QStringList NotebookNodeExplorer::getSelectedNodesPath() const +{ + QStringList files; + + // Support nodes and external nodes. + auto selectedNodes = getSelectedNodes(); + for (const auto &externalNode : selectedNodes.second) { + files << externalNode->fetchAbsolutePath(); + } + + for (const auto &node : selectedNodes.first) { + if (checkInvalidNode(node)) { + continue; + } + + files << node->fetchAbsolutePath(); + } + + return files; +} + QSharedPointer NotebookNodeExplorer::importToIndex(const ExternalNode *p_node) { auto node = m_notebook->addAsNode(p_node->getNode(), @@ -1914,3 +1954,93 @@ void NotebookNodeExplorer::expandItemRecursively(QTreeWidgetItem *p_item) expandItemRecursively(p_item->child(i)); } } + +void NotebookNodeExplorer::addOpenWithMenu(QMenu *p_menu) +{ + auto subMenu = p_menu->addMenu(tr("Open &With")); + + { + const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + for (const auto &pro : sessionConfig.getExternalPrograms()) { + QAction *act = subMenu->addAction(pro.m_name); + connect(act, &QAction::triggered, + this, [this, act]() { + openSelectedNodesWithExternalProgram(act->data().toString()); + }); + act->setData(pro.m_command); + WidgetUtils::addActionShortcutText(act, pro.m_shortcut); + } + } + + subMenu->addSeparator(); + + { + auto defaultAct = subMenu->addAction(tr("System Default Program"), + this, + &NotebookNodeExplorer::openSelectedNodesWithDefaultProgram); + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + WidgetUtils::addActionShortcutText(defaultAct, coreConfig.getShortcut(CoreConfig::OpenWithDefaultProgram)); + } + + subMenu->addAction(tr("Add External Program"), + this, + []() { + const auto file = DocsUtils::getDocFile(QStringLiteral("external_programs.md")); + if (!file.isEmpty()) { + auto paras = QSharedPointer::create(); + paras->m_readOnly = true; + emit VNoteX::getInst().openFileRequested(file, paras); + } + }); +} + +void NotebookNodeExplorer::setupShortcuts() +{ + const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); + + // OpenWithDefaultProgram. + { + auto shortcut = WidgetUtils::createShortcut(coreConfig.getShortcut(CoreConfig::OpenWithDefaultProgram), this); + if (shortcut) { + connect(shortcut, &QShortcut::activated, + this, &NotebookNodeExplorer::openSelectedNodesWithDefaultProgram); + } + } + + const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig(); + for (const auto &pro : sessionConfig.getExternalPrograms()) { + auto shortcut = WidgetUtils::createShortcut(pro.m_shortcut, this); + const auto &command = pro.m_command; + if (shortcut) { + connect(shortcut, &QShortcut::activated, + this, [this, command]() { + openSelectedNodesWithExternalProgram(command); + }); + } + } +} + +void NotebookNodeExplorer::openSelectedNodesWithDefaultProgram() +{ + const auto files = getSelectedNodesPath(); + for (const auto &file : files) { + if (file.isEmpty()) { + continue; + } + WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(file)); + } +} + +void NotebookNodeExplorer::openSelectedNodesWithExternalProgram(const QString &p_command) +{ + const auto files = getSelectedNodesPath(); + for (const auto &file : files) { + if (file.isEmpty()) { + continue; + } + + auto command = p_command; + command.replace(QStringLiteral("%1"), QString("\"%1\"").arg(file)); + ProcessUtils::startDetached(command); + } +} diff --git a/src/widgets/notebooknodeexplorer.h b/src/widgets/notebooknodeexplorer.h index 6266c28c..d610258f 100644 --- a/src/widgets/notebooknodeexplorer.h +++ b/src/widgets/notebooknodeexplorer.h @@ -155,6 +155,8 @@ namespace vnotex void setupUI(); + void setupShortcuts(); + void setupMasterExplorer(QWidget *p_parent = nullptr); void clearExplorer(); @@ -263,6 +265,14 @@ namespace vnotex void expandItemRecursively(QTreeWidgetItem *p_item); + void addOpenWithMenu(QMenu *p_menu); + + QStringList getSelectedNodesPath() const; + + void openSelectedNodesWithDefaultProgram(); + + void openSelectedNodesWithExternalProgram(const QString &p_command); + static NotebookNodeExplorer::NodeData getItemNodeData(const QTreeWidgetItem *p_item); static void setItemNodeData(QTreeWidgetItem *p_item, const NodeData &p_data); diff --git a/src/widgets/viewsplit.cpp b/src/widgets/viewsplit.cpp index 451a6a74..4052522f 100644 --- a/src/widgets/viewsplit.cpp +++ b/src/widgets/viewsplit.cpp @@ -569,6 +569,25 @@ void ViewSplit::createContextMenuOnTabBar(QMenu *p_menu, int p_tabIdx) const p_menu->addSeparator(); + { + auto act = p_menu->addAction(tr("Auto Reload")); + act->setToolTip(tr("Reload file from disk automatically if it is changed outside")); + act->setCheckable(true); + auto win = getViewWindow(p_tabIdx); + Q_ASSERT(win); + act->setChecked(win->getWindowFlags() & ViewWindow::AutoReload); + connect(act, &QAction::triggered, + this, [win](bool p_checked) { + if (p_checked) { + win->setWindowFlags(win->getWindowFlags() | ViewWindow::AutoReload); + } else { + win->setWindowFlags(win->getWindowFlags() & ~ViewWindow::AutoReload); + } + }); + } + + p_menu->addSeparator(); + // Copy Path. p_menu->addAction(tr("Copy Path"), [this, p_tabIdx]() { diff --git a/src/widgets/viewwindow.cpp b/src/widgets/viewwindow.cpp index b6adbb52..15335d5c 100644 --- a/src/widgets/viewwindow.cpp +++ b/src/widgets/viewwindow.cpp @@ -755,12 +755,15 @@ int ViewWindow::checkFileMissingOrChangedOutside() return Failed; } } else if (m_buffer->checkFileChangedOutside()) { - int ret = MessageBoxHelper::questionSaveDiscardCancel(MessageBoxHelper::Warning, - tr("File is changed from outside (%1).").arg(m_buffer->getPath()), - tr("Do you want to save the buffer to the file to override, or discard the buffer?"), - tr("The file is changed from outside. Please choose to save the buffer to the file or " - "just discard the buffer and reload the file."), - this); + int ret = QMessageBox::Discard; + if (!(getWindowFlags() & WindowFlag::AutoReload)) { + ret = MessageBoxHelper::questionSaveDiscardCancel(MessageBoxHelper::Warning, + tr("File is changed from outside (%1).").arg(m_buffer->getPath()), + tr("Do you want to save the buffer to the file to override, or discard the buffer?"), + tr("The file is changed from outside. Please choose to save the buffer to the file or " + "just discard the buffer and reload the file."), + this); + } switch (ret) { case QMessageBox::Save: if (!save(true)) { @@ -1095,3 +1098,13 @@ ViewWindowSession ViewWindow::saveSession() const session.m_viewWindowMode = getMode(); return session; } + +ViewWindow::WindowFlags ViewWindow::getWindowFlags() const +{ + return m_flags; +} + +void ViewWindow::setWindowFlags(WindowFlags p_flags) +{ + m_flags = p_flags; +} diff --git a/src/widgets/viewwindow.h b/src/widgets/viewwindow.h index 8fda5806..75281bcc 100644 --- a/src/widgets/viewwindow.h +++ b/src/widgets/viewwindow.h @@ -30,6 +30,13 @@ namespace vnotex { Q_OBJECT public: + enum WindowFlag + { + None = 0, + AutoReload = 0x1 + }; + Q_DECLARE_FLAGS(WindowFlags, WindowFlag); + explicit ViewWindow(QWidget *p_parent = nullptr); virtual ~ViewWindow(); @@ -74,6 +81,9 @@ namespace vnotex virtual ViewWindowSession saveSession() const; + WindowFlags getWindowFlags() const; + void setWindowFlags(WindowFlags p_flags); + public slots: virtual void handleEditorConfigChange() = 0; @@ -320,9 +330,13 @@ namespace vnotex EditReadDiscardAction *m_editReadDiscardAct = nullptr; + WindowFlags m_flags = WindowFlag::None; + static QIcon s_savedIcon; static QIcon s_modifiedIcon; }; } // ns vnotex +Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::ViewWindow::WindowFlags) + #endif // VIEWWINDOW_H diff --git a/src/widgets/widgets.pri b/src/widgets/widgets.pri index 7fbd6626..dbe181b8 100644 --- a/src/widgets/widgets.pri +++ b/src/widgets/widgets.pri @@ -19,6 +19,7 @@ SOURCES += \ $$PWD/dialogs/settings/editorpage.cpp \ $$PWD/dialogs/settings/generalpage.cpp \ $$PWD/dialogs/settings/markdowneditorpage.cpp \ + $$PWD/dialogs/settings/miscpage.cpp \ $$PWD/dialogs/settings/quickaccesspage.cpp \ $$PWD/dialogs/settings/settingspage.cpp \ $$PWD/dialogs/settings/settingsdialog.cpp \ @@ -117,6 +118,7 @@ HEADERS += \ $$PWD/dialogs/settings/editorpage.h \ $$PWD/dialogs/settings/generalpage.h \ $$PWD/dialogs/settings/markdowneditorpage.h \ + $$PWD/dialogs/settings/miscpage.h \ $$PWD/dialogs/settings/quickaccesspage.h \ $$PWD/dialogs/settings/settingspage.h \ $$PWD/dialogs/settings/settingsdialog.h \