1
0
Le Tan 3 жил өмнө
parent
commit
ecf1f8dbbe
48 өөрчлөгдсөн 691 нэмэгдсэн , 619 устгасан
  1. 21 21
      README_zh_CN.md
  2. 1 1
      src/core/coreconfig.cpp
  3. 1 1
      src/core/coreconfig.h
  4. 1 0
      src/core/editorconfig.h
  5. 14 0
      src/core/notebook/notebookdatabaseaccess.cpp
  6. 2 0
      src/core/notebook/notebookdatabaseaccess.h
  7. 2 2
      src/core/notebook/notebooktagmgr.cpp
  8. 1 1
      src/data/core/core.qrc
  9. 0 0
      src/data/core/icons/debug_editor.svg
  10. 1 10
      src/data/core/icons/find_replace_editor.svg
  11. 0 0
      src/data/core/icons/print_editor.svg
  12. 1 7
      src/data/core/icons/quick_access_menu.svg
  13. 1 10
      src/data/core/icons/search.svg
  14. 1 10
      src/data/core/icons/search_dock.svg
  15. 0 18
      src/data/core/icons/settings.svg
  16. 0 18
      src/data/core/icons/settings_menu.svg
  17. 0 0
      src/data/core/icons/snippet_dock.svg
  18. 1 4
      src/data/core/icons/split_window_list.svg
  19. 0 14
      src/data/core/icons/whatsthis.svg
  20. 67 56
      src/data/core/translations/vnote_ja.ts
  21. BIN
      src/data/core/translations/vnote_zh_CN.qm
  22. 153 150
      src/data/core/translations/vnote_zh_CN.ts
  23. 3 2
      src/data/core/vnotex.json
  24. 7 7
      src/data/extra/docs/en/shortcuts.md
  25. 2 2
      src/data/extra/docs/zh_CN/about_vnotex.txt
  26. 7 7
      src/data/extra/docs/zh_CN/external_programs.md
  27. 5 5
      src/data/extra/docs/zh_CN/features_tips.txt
  28. 17 17
      src/data/extra/docs/zh_CN/markdown_guide.md
  29. 14 14
      src/data/extra/docs/zh_CN/shortcuts.md
  30. 8 8
      src/data/extra/docs/zh_CN/welcome.md
  31. 1 1
      src/export/exporter.cpp
  32. 22 0
      src/utils/printutils.cpp
  33. 21 0
      src/utils/printutils.h
  34. 2 0
      src/utils/utils.pri
  35. 1 1
      src/widgets/dialogs/importnotebookdialog.cpp
  36. 5 0
      src/widgets/dialogs/settings/settingsdialog.cpp
  37. 20 1
      src/widgets/markdownviewwindow.cpp
  38. 2 0
      src/widgets/markdownviewwindow.h
  39. 12 1
      src/widgets/textviewwindow.cpp
  40. 2 0
      src/widgets/textviewwindow.h
  41. 226 227
      src/widgets/toolbarhelper.cpp
  42. 6 0
      src/widgets/toolbarhelper.h
  43. 1 1
      src/widgets/viewsplit.cpp
  44. 14 1
      src/widgets/viewwindow.cpp
  45. 2 0
      src/widgets/viewwindow.h
  46. 7 0
      src/widgets/viewwindowtoolbarhelper.cpp
  47. 2 1
      src/widgets/viewwindowtoolbarhelper.h
  48. 14 0
      tests/test_core/test_notebook/testnotebookdatabase.cpp

+ 21 - 21
README_zh_CN.md

@@ -5,45 +5,45 @@
 
 一个舒适的笔记平台!
 
-更多信息,请访问 [VNote 主页](https://tamlok.gitee.io/vnote) 或者[由 Gitee 托管的主页](https://tamlok.gitee.io/vnote) 
+更多信息,请访问[VNote主页](https://vnotex.github.io/vnote)或者[由Gitee托管的主页](https://tamlok.gitee.io/vnote)
 
 ![VNote](pics/vnote.png)
 
 ## 简介
-**VNote** 是一个专注于 Markdown 的基于 Qt 的开源免费的笔记应用。VNote 希望能提供一个拥有完美编辑体验的舒适的笔记平台。
+**VNote**是一个专注于Markdown的基于Qt的开源免费的笔记应用。VNote希望能提供一个拥有完美编辑体验的舒适的笔记平台。
 
-VNote 不是一个简单的 Markdown 编辑器。通过提供强大的笔记管理,VNote 使得使用 Markdown 记笔记更轻松简单。将来,VNote 会支持更多的文档格式。
+VNote不是一个简单的Markdown编辑器。通过提供强大的笔记管理,VNote使得使用Markdown记笔记更轻松简单。将来,VNote会支持更多的文档格式。
 
-得益于 Qt,VNote 当前可以高效地运行在 **Linux**  **Windows** ,以及 **macOS** 平台上。
+得益于Qt,VNote当前可以高效地运行在**Linux**,**Windows**,以及**macOS**平台上。
 
 ![主界面](pics/main.png)
 
 ## 下载
-基于 `master` 分支的 [持续构建版本发布](https://github.com/vnotex/vnote/releases/tag/continuous-build) 
+基于`master`分支的[持续构建版本发布](https://github.com/vnotex/vnote/releases/tag/continuous-build)。
 
-最新的 [稳定版本发布](https://github.com/vnotex/vnote/releases/latest)  其他下载选项:
+最新的[稳定版本发布](https://github.com/vnotex/vnote/releases/latest)。其他下载选项:
 
 * [天翼云盘](https://cloud.189.cn/t/Av67NvmEJVBv)
-* [百度云盘](https://pan.baidu.com/s/1Fou1flmBsQUQ8Qs9V_M6Aw) 提取码 `note`
+* [百度云盘](https://pan.baidu.com/s/1Fou1flmBsQUQ8Qs9V_M6Aw) 提取码`note`
 
 ## 支持
-* [GitHub Issues](https://github.com/vnotex/vnote/issues) 
-* 邮件: `tamlokveer at gmail.com` 
-* [Slack](https://join.slack.com/t/vnote/shared_invite/enQtNDg2MzY0NDg3NzI4LTVhMzBlOTY0YzVhMmQyMTFmZDdhY2M3MDQxYTBjOTA2Y2IxOGRiZjg2NzdhMjkzYmUyY2VkMWJlZTNhMTQyODU) 
-* [Telegram](https://t.me/vnotex) 
-* 微信公众号: vnotex 
+* [GitHub Issues](https://github.com/vnotex/vnote/issues);
+* 邮件:`tamlokveer at gmail.com`;
+* [Slack](https://join.slack.com/t/vnote/shared_invite/enQtNDg2MzY0NDg3NzI4LTVhMzBlOTY0YzVhMmQyMTFmZDdhY2M3MDQxYTBjOTA2Y2IxOGRiZjg2NzdhMjkzYmUyY2VkMWJlZTNhMTQyODU);
+* [Telegram](https://t.me/vnotex);
+* 微信公众号:`vnotex`
 
 ## 捐赠
-有很多方式可以帮助 VNote 的开发:
+有很多方式可以帮助VNote的开发:
 
-* 持续关注 VNote 并反馈问题以帮助改进;
-* 推荐 VNote 给朋友,口碑传播;
-* 参与 VNote 的开发,发起 [拉取请求](https://github.com/vnotex/vnote/pulls) 一起改进 VNote;
-* 如果 VNote 真的好用,可以考虑捐赠;
+* 持续关注VNote并反馈问题以帮助改进。
+* 推荐VNote给朋友,口碑传播。
+* 参与VNote的开发,发起[拉取请求](https://github.com/vnotex/vnote/pulls)一起改进VNote。
+* 如果VNote真的好用,可以考虑捐赠。
 
-**PayPal**: [PayPal.Me/vnotemd](https://www.paypal.me/vnotemd)
+**PayPal**[PayPal.Me/vnotemd](https://www.paypal.me/vnotemd)
 
-**支付宝**: `[email protected]`
+**支付宝**`[email protected]`
 
 <img src="pics/alipay.png" width="256px" height="256px" />
 
@@ -51,7 +51,7 @@ VNote 不是一个简单的 Markdown 编辑器。通过提供强大的笔记管
 
 <img src="pics/wechat_pay.png" width="256px" height="256px" />
 
-感谢这些 [捐赠用户](https://github.com/vnotex/vnote/wiki/Donate-List) 
+感谢这些[捐赠用户](https://github.com/vnotex/vnote/wiki/Donate-List)!
 
 ## 许可
-VNote 遵循 [GNU LGPLv3](https://opensource.org/licenses/LGPL-3.0) 许可。VNote 项目的代码可以自由给 VNoteX 项目使用。
+VNote遵循[GNU LGPLv3](https://opensource.org/licenses/LGPL-3.0)许可。VNote项目的代码可以自由给VNoteX项目使用。

+ 1 - 1
src/core/coreconfig.cpp

@@ -45,7 +45,7 @@ void CoreConfig::init(const QJsonObject &p_app,
 
     m_toolBarIconSize = READINT(QStringLiteral("toolbar_icon_size"));
     if (m_toolBarIconSize <= 0) {
-        m_toolBarIconSize = 16;
+        m_toolBarIconSize = 18;
     }
 
     m_docksTabBarIconSize = READINT(QStringLiteral("docks_tabbar_icon_size"));

+ 1 - 1
src/core/coreconfig.h

@@ -127,7 +127,7 @@ namespace vnotex
         QString m_shortcuts[Shortcut::MaxShortcut];
 
         // Icon size of MainWindow tool bar.
-        int m_toolBarIconSize = 16;
+        int m_toolBarIconSize = 18;
 
         // Icon size of MainWindow QDockWidgets tab bar.
         int m_docksTabBarIconSize = 20;

+ 1 - 0
src/core/editorconfig.h

@@ -60,6 +60,7 @@ namespace vnotex
             ApplySnippet,
             Tag,
             Debug,
+            Print,
             MaxShortcut
         };
         Q_ENUM(Shortcut)

+ 14 - 0
src/core/notebook/notebookdatabaseaccess.cpp

@@ -194,6 +194,20 @@ bool NotebookDatabaseAccess::addNode(Node *p_node, bool p_ignoreId)
     return true;
 }
 
+bool NotebookDatabaseAccess::addNodeRecursively(Node *p_node, bool p_ignoreId)
+{
+    if (!p_node) {
+        return false;
+    }
+
+    auto paNode = p_node->getParent();
+    if (paNode && !addNodeRecursively(paNode, p_ignoreId)) {
+        return false;
+    }
+
+    return addNode(p_node, p_ignoreId);
+}
+
 QSharedPointer<NotebookDatabaseAccess::NodeRecord> NotebookDatabaseAccess::queryNode(ID p_id)
 {
     auto db = getDatabase();

+ 2 - 0
src/core/notebook/notebookdatabaseaccess.h

@@ -49,6 +49,8 @@ namespace vnotex
     public:
         bool addNode(Node *p_node, bool p_ignoreId);
 
+        bool addNodeRecursively(Node *p_node, bool p_ignoreId);
+
         // Whether there is a record with the same ID in DB and has the same path.
         bool existsNode(const Node *p_node);
 

+ 2 - 2
src/core/notebook/notebooktagmgr.cpp

@@ -187,8 +187,8 @@ bool NotebookTagMgr::updateNodeTags(Node *p_node)
     auto db = m_notebook->getDatabaseAccess();
 
     // Make sure the node exists in DB.
-    if (!db->addNode(p_node, false)) {
-        qWarning() << "failed to add node to DB" << p_node->fetchPath() << p_node->getId();
+    if (!db->addNodeRecursively(p_node, false)) {
+        qWarning() << "failed to add node to DB" << p_node->fetchPath() << p_node->getId() << (p_node->getParent() ? p_node->getParent()->getId() : -1);
         return false;
     }
 

+ 1 - 1
src/data/core/core.qrc

@@ -26,7 +26,6 @@
         <file>icons/inplace_preview_editor.svg</file>
         <file>icons/image_host_editor.svg</file>
         <file>icons/settings_menu.svg</file>
-        <file>icons/whatsthis.svg</file>
         <file>icons/help_menu.svg</file>
         <file>icons/import_menu.svg</file>
         <file>icons/export_menu.svg</file>
@@ -79,6 +78,7 @@
         <file>icons/close.svg</file>
         <file>icons/delete.svg</file>
         <file>icons/debug_editor.svg</file>
+        <file>icons/print_editor.svg</file>
         <file>icons/stay_on_top.svg</file>
         <file>icons/outline_editor.svg</file>
         <file>icons/find_replace_editor.svg</file>

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
src/data/core/icons/debug_editor.svg


+ 1 - 10
src/data/core/icons/find_replace_editor.svg

@@ -1,10 +1 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path style="fill:#000000" d="M445,386.7l-84.8-85.9c13.8-24.1,21-50.9,21-77.9c0-87.6-71.2-158.9-158.6-158.9C135.2,64,64,135.3,64,222.9
-	c0,87.6,71.2,158.9,158.6,158.9c27.9,0,55.5-7.7,80.1-22.4l84.4,85.6c1.9,1.9,4.6,3.1,7.3,3.1c2.7,0,5.4-1.1,7.3-3.1l43.3-43.8
-	C449,397.1,449,390.7,445,386.7z M222.6,125.9c53.4,0,96.8,43.5,96.8,97c0,53.5-43.4,97-96.8,97c-53.4,0-96.8-43.5-96.8-97
-	C125.8,169.4,169.2,125.9,222.6,125.9z"/>
-</svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1637134995193" class="icon" viewBox="0 0 1026 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4928" width="513" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M1009.371429 943.542857l-248.685714-256c0 0-7.314286-7.314286-14.628571-7.314286 51.2-65.828571 87.771429-160.914286 87.771429-256C826.514286 190.171429 643.657143 0 409.6 0 190.171429 0 0 190.171429 0 424.228571s190.171429 424.228571 416.914286 424.228571c102.4 0 204.8-43.885714 270.628571-102.4l7.314286 7.314286 248.685714 256c14.628571 14.628571 43.885714 14.628571 58.514286 0C1031.314286 987.428571 1031.314286 965.485714 1009.371429 943.542857L1009.371429 943.542857zM416.914286 782.628571c-197.485714 0-351.085714-160.914286-351.085714-358.4S219.428571 65.828571 416.914286 65.828571c197.485714 0 351.085714 160.914286 351.085714 358.4S614.4 782.628571 416.914286 782.628571L416.914286 782.628571z" p-id="4929" fill="#000000"></path></svg>

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
src/data/core/icons/print_editor.svg


+ 1 - 7
src/data/core/icons/quick_access_menu.svg

@@ -1,7 +1 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<polygon fill="#000000" points="96,288 243,288 191.9,480 416,224 269,224 320,32 "/>
-</svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1637135307796" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2546" width="512" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M353.877333 597.333333l-75.392 301.568c-7.978667 31.829333 31.402667 53.589333 54.144 29.909334L844.373333 395.52A32 32 0 0 0 821.333333 341.333333h-190.293333l71.338667-213.888A32 32 0 0 0 672 85.333333h-298.666667a32 32 0 0 0-30.762666 23.210667l-128 448A32 32 0 0 0 245.333333 597.333333h108.544z m202.453334-234.112a32 32 0 0 0 30.336 42.112h159.573333l-376.490667 392.362667 56.149334-224.597333a32 32 0 0 0-31.018667-39.765334h-107.093333l109.653333-384h230.144l-71.253333 213.888z" p-id="2547" fill="#000000"></path></svg>

+ 1 - 10
src/data/core/icons/search.svg

@@ -1,10 +1 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path style="fill:#000000" d="M445,386.7l-84.8-85.9c13.8-24.1,21-50.9,21-77.9c0-87.6-71.2-158.9-158.6-158.9C135.2,64,64,135.3,64,222.9
-	c0,87.6,71.2,158.9,158.6,158.9c27.9,0,55.5-7.7,80.1-22.4l84.4,85.6c1.9,1.9,4.6,3.1,7.3,3.1c2.7,0,5.4-1.1,7.3-3.1l43.3-43.8
-	C449,397.1,449,390.7,445,386.7z M222.6,125.9c53.4,0,96.8,43.5,96.8,97c0,53.5-43.4,97-96.8,97c-53.4,0-96.8-43.5-96.8-97
-	C125.8,169.4,169.2,125.9,222.6,125.9z"/>
-</svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1637134995193" class="icon" viewBox="0 0 1026 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4928" width="513" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M1009.371429 943.542857l-248.685714-256c0 0-7.314286-7.314286-14.628571-7.314286 51.2-65.828571 87.771429-160.914286 87.771429-256C826.514286 190.171429 643.657143 0 409.6 0 190.171429 0 0 190.171429 0 424.228571s190.171429 424.228571 416.914286 424.228571c102.4 0 204.8-43.885714 270.628571-102.4l7.314286 7.314286 248.685714 256c14.628571 14.628571 43.885714 14.628571 58.514286 0C1031.314286 987.428571 1031.314286 965.485714 1009.371429 943.542857L1009.371429 943.542857zM416.914286 782.628571c-197.485714 0-351.085714-160.914286-351.085714-358.4S219.428571 65.828571 416.914286 65.828571c197.485714 0 351.085714 160.914286 351.085714 358.4S614.4 782.628571 416.914286 782.628571L416.914286 782.628571z" p-id="4929" fill="#000000"></path></svg>

+ 1 - 10
src/data/core/icons/search_dock.svg

@@ -1,10 +1 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<path style="fill:#000000" d="M445,386.7l-84.8-85.9c13.8-24.1,21-50.9,21-77.9c0-87.6-71.2-158.9-158.6-158.9C135.2,64,64,135.3,64,222.9
-	c0,87.6,71.2,158.9,158.6,158.9c27.9,0,55.5-7.7,80.1-22.4l84.4,85.6c1.9,1.9,4.6,3.1,7.3,3.1c2.7,0,5.4-1.1,7.3-3.1l43.3-43.8
-	C449,397.1,449,390.7,445,386.7z M222.6,125.9c53.4,0,96.8,43.5,96.8,97c0,53.5-43.4,97-96.8,97c-53.4,0-96.8-43.5-96.8-97
-	C125.8,169.4,169.2,125.9,222.6,125.9z"/>
-</svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1637134995193" class="icon" viewBox="0 0 1026 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4928" width="513" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M1009.371429 943.542857l-248.685714-256c0 0-7.314286-7.314286-14.628571-7.314286 51.2-65.828571 87.771429-160.914286 87.771429-256C826.514286 190.171429 643.657143 0 409.6 0 190.171429 0 0 190.171429 0 424.228571s190.171429 424.228571 416.914286 424.228571c102.4 0 204.8-43.885714 270.628571-102.4l7.314286 7.314286 248.685714 256c14.628571 14.628571 43.885714 14.628571 58.514286 0C1031.314286 987.428571 1031.314286 965.485714 1009.371429 943.542857L1009.371429 943.542857zM416.914286 782.628571c-197.485714 0-351.085714-160.914286-351.085714-358.4S219.428571 65.828571 416.914286 65.828571c197.485714 0 351.085714 160.914286 351.085714 358.4S614.4 782.628571 416.914286 782.628571L416.914286 782.628571z" p-id="4929" fill="#000000"></path></svg>

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 18
src/data/core/icons/settings.svg


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 18
src/data/core/icons/settings_menu.svg


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
src/data/core/icons/snippet_dock.svg


+ 1 - 4
src/data/core/icons/split_window_list.svg

@@ -1,4 +1 @@
-<svg t="1600732290374" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11728" width="512" height="512">
-<path d="M725.333333 725.333333V128a85.333333 85.333333 0 0 0-85.333333-85.333333H394.24a128 128 0 0 0-90.453333 37.546666L122.88 261.12A128 128 0 0 0 85.333333 351.573333V725.333333a85.333333 85.333333 0 0 0 85.333334 85.333334h469.333333a85.333333 85.333333 0 0 0 85.333333-85.333334zM170.666667 384h213.333333a42.666667 42.666667 0 0 0 42.666667-42.666667V128h213.333333v597.333333H170.666667z m640-170.666667v597.333334a85.333333 85.333333 0 0 1-85.333334 85.333333H256a85.333333 85.333333 0 0 0 85.333333 85.333333h384a170.666667 170.666667 0 0 0 170.666667-170.666666V298.666667a85.333333 85.333333 0 0 0-85.333333-85.333334z" p-id="11729" fill="#000000">
-</path>
-</svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1637142310647" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11342" width="512" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M256 256V149.333333c0-58.88 47.829333-106.666667 106.666667-106.666666h512c58.88 0 106.666667 47.829333 106.666666 106.666666v512c0 58.88-47.829333 106.666667-106.666666 106.666667h-106.666667v106.666667c0 58.88-47.829333 106.666667-106.666667 106.666666H149.333333c-58.88 0-106.666667-47.829333-106.666666-106.666666V362.666667c0-58.88 47.829333-106.666667 106.666666-106.666667h106.666667z m0 85.333333H149.333333c-11.733333 0-21.333333 9.6-21.333333 21.333334v512c0 11.733333 9.6 21.333333 21.333333 21.333333h512c11.733333 0 21.333333-9.6 21.333334-21.333333v-106.666667H362.666667c-58.88 0-106.666667-47.829333-106.666667-106.666667V341.333333z m85.333333-192v512c0 11.733333 9.6 21.333333 21.333334 21.333334h512c11.733333 0 21.333333-9.6 21.333333-21.333334V149.333333c0-11.733333-9.6-21.333333-21.333333-21.333333H362.666667c-11.733333 0-21.333333 9.6-21.333334 21.333333z" p-id="11343" fill="#000000"></path></svg>

+ 0 - 14
src/data/core/icons/whatsthis.svg

@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-<g>
-	<path fill="#000000" d="M345.1,77.1C317.6,56.2,286.6,49,247.3,49c-29.8,0-55.3,6.1-75.5,19.7C142,89,128,123.1,128,177h76.8
-		c0-14.4-1.4-29.9,7-43.2c8.4-13.3,20.1-23.5,40.2-23.5c20.4,0,30.9,5.9,40.8,18.1c8.4,10.4,11.6,22.8,11.6,36
-		c0,11.4-5.8,21.9-12.7,31.4c-3.8,5.6-8.8,10.6-15.1,15.4c0,0-41.5,24.7-56.1,48.1c-10.9,17.4-14.8,39.2-15.7,65.3
-		c-0.1,1.9,0.6,5.8,7.2,5.8c6.5,0,56,0,61.8,0c5.8,0,7-4.4,7.1-6.2c0.4-9.5,1.6-24.1,3.3-29.6c3.3-10.4,9.7-19.5,19.7-27.3
-		l20.7-14.3c18.7-14.6,33.6-26.5,40.2-35.9c11.3-15.4,19.2-34.4,19.2-56.9C384,123.5,370.5,96.4,345.1,77.1z M242,370.2
-		c-25.9-0.8-47.3,17.2-48.2,45.3c-0.8,28.2,19.5,46.7,45.5,47.5c27,0.8,47.9-16.6,48.7-44.7C288.8,390.2,269,371,242,370.2z"/>
-</g>
-</svg>

+ 67 - 56
src/data/core/translations/vnote_ja.ts

@@ -109,7 +109,7 @@
     </message>
     <message>
         <location filename="../../../widgets/dialogs/settings/appearancepage.cpp" line="70"/>
-        <source>Keep dock widgets when expanding content area:</source>
+        <source>Dock widgets kept when expanding content area:</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
@@ -690,9 +690,8 @@
         <translation>ファイルベースのないバッファ(%1)をスキップしました。</translation>
     </message>
     <message>
-        <location filename="../../../export/exporter.cpp" line="120"/>
         <source>Failed to create output folder %1.</source>
-        <translation>出力フォルダ%1の作成に失敗しました。</translation>
+        <translation type="vanished">出力フォルダ%1の作成に失敗しました。</translation>
     </message>
     <message>
         <location filename="../../../export/exporter.cpp" line="64"/>
@@ -701,6 +700,7 @@
     </message>
     <message>
         <location filename="../../../export/exporter.cpp" line="38"/>
+        <location filename="../../../export/exporter.cpp" line="120"/>
         <source>Failed to create output folder (%1).</source>
         <translation type="unfinished"></translation>
     </message>
@@ -1503,8 +1503,12 @@
     </message>
     <message>
         <location filename="../../../widgets/dialogs/importnotebookdialog.cpp" line="103"/>
+        <source>Not a valid (%1) root folder (%2).</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
         <source>Not a valid %1 root folder (%2).</source>
-        <translation>有効な%1ルートフォルダ(%2)ではありません。</translation>
+        <translation type="vanished">有効な%1ルートフォルダ(%2)ではありません。</translation>
     </message>
     <message>
         <location filename="../../../widgets/dialogs/importnotebookdialog.cpp" line="127"/>
@@ -1700,7 +1704,7 @@ Remove them from the configuration?</source>
     </message>
     <message>
         <location filename="../../../widgets/systemtrayhelper.cpp" line="44"/>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="414"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="565"/>
         <source>Quit</source>
         <translation>終了</translation>
     </message>
@@ -1803,49 +1807,59 @@ Remove them from the configuration?</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="503"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="577"/>
+        <source>Menu</source>
+        <translation type="unfinished">メニュー</translation>
+    </message>
+    <message>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="624"/>
+        <source>Home Page</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="645"/>
         <source>Contributors</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="529"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="305"/>
         <source>Configuration</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="531"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="307"/>
         <source>Edit User Configuration File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="556"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="332"/>
         <source>Edit Markdown User Styles</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="569"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="345"/>
         <source>Edit the user styles of Markdown editor read mode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="643"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="419"/>
         <source>Quick Access Not Set</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
         <location filename="../../../widgets/toolbarhelper.cpp" line="289"/>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="375"/>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="385"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="526"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="536"/>
         <source>Settings</source>
         <translation>設定</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="305"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="456"/>
         <source>Expand Content Area</source>
         <translation>コンテンツ領域の拡大</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="327"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="478"/>
         <source>Press %1 To Exit Full Screen</source>
         <translation>%1 を押して全画面表示を終了する</translation>
     </message>
@@ -1860,88 +1874,81 @@ Remove them from the configuration?</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="335"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="486"/>
         <source>Stay on Top</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="347"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="498"/>
         <source>Windows</source>
         <translation>ウインドウ</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="540"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="316"/>
         <source>Open User Configuration Folder</source>
         <translation>ユーザー設定フォルダを開く</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="547"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="323"/>
         <source>Open Default Configuration Folder</source>
         <translation>既定の設定フォルダを開く</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="400"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="551"/>
         <source>Reset Main Window Layout</source>
         <translation>メインウィンドウのレイアウトをリセット</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="408"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="559"/>
         <source>Restart</source>
         <translation>再起動</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="426"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="622"/>
         <source>Help</source>
         <translation>ヘルプ</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="436"/>
         <source>What&apos;s This?</source>
-        <translation>これは何ですか?</translation>
+        <translation type="vanished">これは何ですか?</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="441"/>
         <source>Enter WhatsThis mode and click somewhere to show help information</source>
-        <translation>[これは何]モードに入り、ヘルプ情報を表示する場所をクリックします</translation>
+        <translation type="vanished">[これは何]モードに入り、ヘルプ情報を表示する場所をクリックします</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="445"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="600"/>
         <source>Shortcuts Help</source>
         <translation>ショートカットヘルプ</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="456"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="611"/>
         <source>Markdown Guide</source>
         <translation>Markdown ガイド</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="469"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="586"/>
         <source>View Logs</source>
         <translation>ログの表示</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="482"/>
-        <source>%1 Home Page</source>
-        <translation type="unfinished"></translation>
-    </message>
-    <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="488"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="630"/>
         <source>Feedback and Discussions</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="496"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="638"/>
         <source>Check for Updates</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="509"/>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="515"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="651"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="657"/>
         <source>About</source>
         <translation>バージョン情報</translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="512"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="654"/>
         <source>&lt;h3&gt;%1&lt;/h3&gt;
 &lt;span&gt;%2&lt;/span&gt;
 </source>
@@ -1950,7 +1957,7 @@ Remove them from the configuration?</source>
 </translation>
     </message>
     <message>
-        <location filename="../../../widgets/toolbarhelper.cpp" line="518"/>
+        <location filename="../../../widgets/toolbarhelper.cpp" line="660"/>
         <source>About Qt</source>
         <translation>Qtについて</translation>
     </message>
@@ -2520,66 +2527,66 @@ Remove them from the configuration?</source>
 <context>
     <name>vnotex::MarkdownViewWindow</name>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="445"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="447"/>
         <source>Markdown Viewer</source>
         <translation>Markdownビューア</translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="793"/>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="825"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="795"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="827"/>
         <source>Clear Obsolete Images</source>
         <translation>古いイメージをクリア</translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="794"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="796"/>
         <source>These images seems to be not in use anymore. Please confirm the deletion of them.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="795"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="797"/>
         <source>Deleted local images could be found in the recycle bin of notebook if it is from a bundle notebook.</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="819"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="821"/>
         <source>Clearing obsolete images...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="820"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="822"/>
         <source>Abort</source>
         <translation type="unfinished">中止</translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="834"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="836"/>
         <source>Clear image (%1)</source>
         <translation type="unfinished"></translation>
     </message>
     <message numerus="yes">
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="846"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="848"/>
         <source>Cleared %n obsolete images</source>
         <translation type="unfinished">
             <numerusform></numerusform>
         </translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="1259"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="1261"/>
         <source>View Mode Not Supported In Read Mode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="1277"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="1279"/>
         <source>Edit Only</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="1288"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="1290"/>
         <source>Edit with Preview</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="1001"/>
-        <location filename="../../../widgets/markdownviewwindow.cpp" line="1010"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="1003"/>
+        <location filename="../../../widgets/markdownviewwindow.cpp" line="1012"/>
         <source>Replace is not supported in read mode</source>
         <translation>置換は読み取りモードではサポートされていません</translation>
     </message>
@@ -4732,9 +4739,13 @@ Description: %3</source>
         <translation>ウインドウリスト</translation>
     </message>
     <message>
-        <location filename="../../../widgets/viewsplit.cpp" line="151"/>
         <source>Workspaces and Splits</source>
-        <translation>ワークスペースと分割</translation>
+        <translation type="vanished">ワークスペースと分割</translation>
+    </message>
+    <message>
+        <location filename="../../../widgets/viewsplit.cpp" line="151"/>
+        <source>Menu</source>
+        <translation type="unfinished">メニュー</translation>
     </message>
     <message>
         <location filename="../../../widgets/viewsplit.cpp" line="413"/>

BIN
src/data/core/translations/vnote_zh_CN.qm


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 153 - 150
src/data/core/translations/vnote_zh_CN.ts


+ 3 - 2
src/data/core/vnotex.json

@@ -61,7 +61,7 @@
             "MoveOneSplitRight" : "Ctrl+G, Shift+L",
             "OpenLastClosedFile" : "Ctrl+Shift+T"
         },
-        "toolbar_icon_size" : 16,
+        "toolbar_icon_size" : 18,
         "docks_tabbar_icon_size" : 24,
         "note_management" : {
             "external_node" : {
@@ -120,7 +120,8 @@
                 "FindPrevious" : "Shift+F3",
                 "ApplySnippet" : "Ctrl+G, I",
                 "Tag" : "Ctrl+G, B",
-                "Debug" : "F12"
+                "Debug" : "F12",
+                "Print" : ""
             },
             "spell_check_auto_detect_language" : false,
             "spell_check_default_dictionary" : "en_US",

+ 7 - 7
src/data/extra/docs/en/shortcuts.md

@@ -2,10 +2,10 @@
 1. All the keys without special notice are **case insensitive**;
 2. On macOS, `Ctrl` corresponds to `Command` except in Vi mode;
 3. The key sequence `Ctrl+G, I` means that first press both `Ctrl` and `G` simultaneously, release them, then press `I` and release;
-4. For a **complete latest shortcuts list**, please view the `vnotex.json` configuration file.
+4. For a **complete latest shortcuts list** or modifying default shortcuts, please view the `vnotex.json` configuration file.
 
 ## General
-- `Ctrl+G E`  
+- `Ctrl+G, E`  
 Toggle expanding the content area.
 - `Ctrl+Alt+N`  
 Create a note in current folder.
@@ -23,11 +23,11 @@ Recover last closed file.
 Open Flash Page.
 - `Ctrl+Alt+I`  
 Open Quick Access.
-- `Ctrl+G X`  
+- `Ctrl+G, X`  
 Close current tab.
-- `Ctrl+G D`  
+- `Ctrl+G, D`  
 Locate to the folder of current note.
-- `Ctrl+G O`  
+- `Ctrl+G, O`  
 Open the Outline popup.
 
 ## Text Editor
@@ -89,7 +89,7 @@ Shares the same shortcuts with Text Editor.
 
 - `Ctrl+T`  
 Edit current note or save changes and exit edit mode.
-- `Ctrl+G Q`  
+- `Ctrl+G, Q`  
 Discard current changes and exit edit mode.
 
 #### Text Editing
@@ -117,4 +117,4 @@ Increase or decrease the indentation. If any text is selected, the indentation w
 Insert two spaces followed by a new line, namely a soft linebreak in Markdown.
 
 ## Navigation Mode
-`Ctrl+G W` will turn VNote into **Navigation Mode**. In this mode, VNote will display at most two characters on some major widgets, and then pressing corresponding characters will jump to that widget.
+`Ctrl+G, W` will turn VNote into **Navigation Mode**. In this mode, VNote will display at most two characters on some major widgets, and then pressing corresponding characters will jump to that widget.

+ 2 - 2
src/data/extra/docs/zh_CN/about_vnotex.txt

@@ -1,7 +1,7 @@
 <p>
-VNoteX 致力于成为一个舒适的笔记平台。VNoteX 重构自 VNote,后者是一个始于2016年的专注于 Markdown 的开源笔记软件。VNote 在版本3之后会和 VNoteX 共享大部分源代码,并继续开源。
+VNoteX致力于成为一个舒适的笔记平台。VNoteX重构自VNote,后者是一个始于2016年的专注于Markdown的开源笔记软件。VNote在版本3之后会和VNoteX共享大部分源代码,并继续开源。
 <br/><br/>
-VNote 源代码可以在 <a href="https://github.com/vnotex/vnote">GitHub</a> 获取。
+VNote源代码可以在<a href="https://github.com/vnotex/vnote">GitHub</a>获取。
 <br/><br/>
 详情请访问<a href="https://vnotex.github.io/vnote">主页</a>。
 </p>

+ 7 - 7
src/data/extra/docs/zh_CN/external_programs.md

@@ -1,7 +1,7 @@
 # 外部程序
-VNote 支持通过在节点浏览器上下文菜单中的 `打开方式` 来调用 **外部程序** 打开笔记。
+VNote支持通过在节点浏览器上下文菜单中的`打开方式`来调用**外部程序**打开笔记。
 
-用户需要编辑会话配置(用户配置文件夹下的 `session.json` 文件)来添加自定义外部程序。一个例子如下:
+用户需要编辑会话配置(用户配置文件夹下的`session.json`文件)来添加自定义外部程序。一个例子如下:
 
 ```json
 {
@@ -22,9 +22,9 @@ VNote 支持通过在节点浏览器上下文菜单中的 `打开方式` 来调
 
 一个外部程序可以包含3个属性:
 
-1. `name`: 该程序在 VNote 中的名字;
-2. `command`: 当使用该外部程序打开笔记时执行的命令;
-    1. 使用 `%1` 占位符,会被替换为真实的文件路径(自动加上双引号包裹);
-3. `shortcut`: 分配给该外部程序的快捷键;
+1. `name`:该程序在VNote中的名字;
+2. `command`当使用该外部程序打开笔记时执行的命令;
+    1. 使用`%1`占位符,会被替换为真实的文件路径(自动加上双引号包裹);
+3. `shortcut`分配给该外部程序的快捷键;
 
-修改配置前请 **关闭 VNote** 
+修改配置前请**关闭VNote**。

+ 5 - 5
src/data/extra/docs/zh_CN/features_tips.txt

@@ -1,7 +1,7 @@
-<p>VNote 中一些不容错过的特性:</p>
-<h3 id="markdown-">Markdown 编辑器</h3>
+<p>VNote中一些不容错过的特性:</p>
+<h3 id="markdown-">Markdown编辑器</h3>
 <ul>
-<li>上下文菜单中的 <strong>解析为 Markdown 并粘贴</strong>: 解析富文本为 Markdown 文本,并按需获取图片到本地。</li>
-<li>上下文菜单中的 <strong>多功能粘贴</strong>: 粘贴为图片、附件或者连接。</li>
-<li>上下文菜单中的 <strong>交叉复制</strong>: 将所选文本复制为富文本。</li>
+<li>上下文菜单中的<strong>解析为Markdown并粘贴</strong>:解析富文本为Markdown文本,并按需获取图片到本地。</li>
+<li>上下文菜单中的<strong>多功能粘贴</strong>:粘贴为图片、附件或者连接。</li>
+<li>上下文菜单中的<strong>交叉复制</strong>:将所选文本复制为富文本。</li>
 </ul>

+ 17 - 17
src/data/extra/docs/zh_CN/markdown_guide.md

@@ -1,16 +1,16 @@
-# Markdown 指南
-Markdown 是一种轻量级的易用的书写语法。本文是 Markdown 的一个快速指南[^1]。
+# Markdown指南
+Markdown是一种轻量级的易用的书写语法。本文是Markdown的一个快速指南[^1]。
 
-## 什么是 Markdown?
-Markdown 是一种通过少量简单的标记字符来格式化文本的方法。您可以用纯文本来书写文档,然后在阅读时呈现一个美观的排版。
+## 什么是Markdown?
+Markdown是一种通过少量简单的标记字符来格式化文本的方法。您可以用纯文本来书写文档,然后在阅读时呈现一个美观的排版。
 
-其实并没有一个标准的 Markdown 语法,很多编辑器都会添加自己的扩展语法。不同于此,为了兼容性,VNote 仅仅支持那些被广泛使用的基本语法。
+其实并没有一个标准的Markdown语法,很多编辑器都会添加自己的扩展语法。不同于此,为了兼容性,VNote仅仅支持那些被广泛使用的基本语法。
 
-## 如何上手 Markdown?
-如果刚接触 Markdown,那么比较好的一个方法是逐个学习 Markdown 语法。刚开始,懂得标题和强调语法就能够写出基本的文档;然后,每天可以学习一个新的语法并不断练习。
+## 如何上手Markdown?
+如果刚接触Markdown,那么比较好的一个方法是逐个学习Markdown语法。刚开始,懂得标题和强调语法就能够写出基本的文档;然后,每天可以学习一个新的语法并不断练习。
 
 ## 语法指南
-下面是 VNote 支持的 Markdown 语法的一个概览。
+下面是VNote支持的Markdown语法的一个概览。
 
 ### 标题
 ```md
@@ -35,7 +35,7 @@ __This text will be bold__
 
 **注意**:
 
-* VNote 推荐使用`*`;
+* VNote推荐使用`*`;
 * 如果渲染错误,请尝试在第一个`*`之前以及最后一个`*`之后添加一个空格。如果被标记的文本是以全角符号开始或结尾,一般都需要前后添加一个空格;
 
 ### 列表
@@ -87,7 +87,7 @@ __This text will be bold__
 
 **注意**:
 
-* VNote 不推荐使用参考式的图片链接。VNote 不会预览这些图片。
+* VNote不推荐使用参考式的图片链接。VNote不会预览这些图片。
 
 ### 块引用
 ```md
@@ -121,11 +121,11 @@ Here is another sentence within the quote.
 
 **注意**:
 
-* `lang`用于指定代码块的代码语言,可选;如果不指定,VNote 不会尝试高亮代码;
+* `lang`用于指定代码块的代码语言,可选;如果不指定,VNote不会尝试高亮代码;
 * 总是在一个代码块前面添加一个空行是一个不错的实践;
 
 ### 图表
-VNote 支持使用以下引擎来绘制图表。您需要使用代码块,并标明特定语言,然后在代码块里面定义图表。
+VNote支持使用以下引擎来绘制图表。您需要使用代码块,并标明特定语言,然后在代码块里面定义图表。
 
 * [Flowchart.js](http://flowchart.js.org/),语言为`flow`或`flowchart`;
 * [Mermaid](https://mermaidjs.github.io/),语言为`mermaid`;
@@ -148,7 +148,7 @@ VNote 支持使用以下引擎来绘制图表。您需要使用代码块,并
     ```
 
 #### UML
-VNote 支持 [PlantUML](http://plantuml.com/) 来实现 UML 图表。您需要使用代码块,并标明语言为`puml`,然后在代码块里面定义图表。
+VNote支持[PlantUML](http://plantuml.com/)来实现UML图表。您需要使用代码块,并标明语言为`puml`,然后在代码块里面定义图表。
 
     ```puml
     @startuml
@@ -157,10 +157,10 @@ VNote 支持 [PlantUML](http://plantuml.com/) 来实现 UML 图表。您需要
     ```
 
 #### Graphviz
-VNote支持 [Graphviz](http://www.graphviz.org/) 来绘制图表。您需要使用代码块,并标明语言为`dot`,然后在代码块里面定义图表。
+VNote支持[Graphviz](http://www.graphviz.org/)来绘制图表。您需要使用代码块,并标明语言为`dot`,然后在代码块里面定义图表。
 
 ### 数学公式
-VNote 通过 [MathJax](https://www.mathjax.org/) 来支持数学公式。默认的**公式块**的分隔符是`$$...$$`,**行内公式**的分隔符是`$...$`。
+VNote通过[MathJax](https://www.mathjax.org/)来支持数学公式。默认的**公式块**的分隔符是`$$...$$`,**行内公式**的分隔符是`$...$`。
 
 * 行内公式不能跨多行;
 * 形如`3$abc$`/`$abc$4`/`$ abc$`和`$abc $`的不会被解析为公式;
@@ -185,7 +185,7 @@ VNote也可以使用标明语言`mathjax`的代码块来实现公式块。
 Here is a `inline code`.
 ```
 
-如果想输入一个 `` ` ``,需要使用两个 `` ` `` 来括住它,例如 ``` `` ` `` ```。 要输入两个 `` ` ``,则需要使用三个 `` ` ``。
+如果想输入一个`` ` ``,需要使用两个`` ` ``来括住它,例如``` `` ` `` ```。要输入两个`` ` ``,则需要使用三个`` ` ``。
 
 ### 删除线
 ```md
@@ -247,4 +247,4 @@ alert-dark
 
 一般来说,您应该在一个块元素(例如代码块、列表和块引用)后面插入一个空行来显式结束该元素。
 
-[^1]: 该指南参考了 [Mastering Markdown](https://guides.github.com/features/mastering-markdown/).
+[^1]: 该指南参考了[Mastering Markdown](https://guides.github.com/features/mastering-markdown/)

+ 14 - 14
src/data/extra/docs/zh_CN/shortcuts.md

@@ -1,11 +1,11 @@
 # 快捷键
 1. 以下按键除特别说明外,都不区分大小写;
-2. 在 macOS 下,`Ctrl` 对应于 `Command`,在 Vi 模式下除外;
-3. 按键序列 `Ctrl+G, I` 表示先同时按下 `Ctrl`  `G`,释放,然后按下 `I` 并释放;
-4. 可以通过查看配置文件 `vnotex.json` 来获取一个**完整的最新的快捷键列表**。
+2. 在macOS下,`Ctrl`对应于`Command`,在Vi模式下除外;
+3. 按键序列`Ctrl+G, I`表示先同时按下`Ctrl`和`G`,释放,然后按下`I`并释放;
+4. 可以通过查看配置文件`vnotex.json`来获取一个**完整的最新的快捷键列表**或者修改默认快捷键
 
 ## 通用
-- `Ctrl+G E`  
+- `Ctrl+G, E`  
 是否扩展内容区。
 - `Ctrl+Alt+N`  
 在当前文件夹下新建笔记。
@@ -14,8 +14,8 @@
 - `Ctrl+Alt+F`  
 高级查找。
 - `Ctrl+J`/`Ctrl+K`  
-VNote 的很多部件均支持`Ctrl+J`和`Ctrl+K`导航。
-- `Ctrl+Left Mouse`  
+VNote的很多部件均支持`Ctrl+J`和`Ctrl+K`导航。
+- `Ctrl+Left, Mouse`  
 任意滚动。
 - `Ctrl+Shift+T`  
 恢复上一个关闭的文件。
@@ -23,11 +23,11 @@ VNote 的很多部件均支持`Ctrl+J`和`Ctrl+K`导航。
 打开灵犀页。
 - `Ctrl+Alt+I`  
 打开快速访问。
-- `Ctrl+G X`  
+- `Ctrl+G, X`  
 关闭当前标签页。
-- `Ctrl+G D`  
+- `Ctrl+G, D`  
 定位到当前笔记所在文件夹。
-- `Ctrl+G O`  
+- `Ctrl+G, O`  
 打开大纲弹出窗口。
 
 ## 文本编辑器
@@ -45,7 +45,7 @@ VNote 的很多部件均支持`Ctrl+J`和`Ctrl+K`导航。
     取消补全。
     - `Enter`  
     插入补全。
-    - `Ctrl+[` or `Escape`  
+    - `Ctrl+[`或者`Escape`  
     结束补全。
 
 ### 文本编辑
@@ -78,7 +78,7 @@ VNote 的很多部件均支持`Ctrl+J`和`Ctrl+K`导航。
 恢复页面大小为100%。
 - 标题跳转
     - `<N>[[`:跳转到上`N`个标题;
-    - `<N>]]`: 跳转到下`N`个标题;
+    - `<N>]]`跳转到下`N`个标题;
     - `<N>[]`:跳转到上`N`个同层级的标题;
     - `<N>][`:跳转到下`N`个同层级的标题;
     - `<N>[{`:跳转到上`N`个高一层级的标题;
@@ -89,7 +89,7 @@ VNote 的很多部件均支持`Ctrl+J`和`Ctrl+K`导航。
 
 - `Ctrl+T`  
 编辑当前笔记或者保存更改并退出编辑模式。
-- `Ctrl+G Q`  
+- `Ctrl+G, Q`  
 放弃当前更改并退出编辑模式。
 
 #### 文本编辑
@@ -114,7 +114,7 @@ VNote 的很多部件均支持`Ctrl+J`和`Ctrl+K`导航。
 - `Tab`/`Shift+Tab`  
 增加或减小缩进。如果已经选择文本,则对所有选择的行进行缩进操作。
 - `Shift+Enter`  
-插入两个空格然后换行,在 Markdown 中类似于软换行的概念。
+插入两个空格然后换行,在Markdown中类似于软换行的概念。
 
 ## 展览模式
-`Ctrl+G W` 会使 VNote 进入**展览模式** 。该模式中,VNote会在一些主要部件中显示最多两个字母,按下这些字母可以跳转到对应的部件。
+`Ctrl+G, W`会使VNote进入**展览模式**。该模式中,VNote会在一些主要部件中显示最多两个字母,按下这些字母可以跳转到对应的部件。

+ 8 - 8
src/data/extra/docs/zh_CN/welcome.md

@@ -1,15 +1,15 @@
 # 欢迎使用 VNote
 一个舒适的笔记平台。
 
-更多信息,请访问 [VNote 主页](https://vnotex.github.io/vnote) 或者[由 Gitee 托管的主页](https://tamlok.gitee.io/vnote) 
+更多信息,请访问[VNote主页](https://vnotex.github.io/vnote)或者[由Gitee托管的主页](https://tamlok.gitee.io/vnote)。
 
 ## 常见问题
 * 将鼠标悬停在按钮上可以获取详细信息。
-* 如果更新后 VNote 崩溃,请删除用户配置文件夹中的 `vnotex.json` 文件。
-* VNote 有着一系列强大的快捷键。请查看用户配置文件 `vnotex.json` 以获取一个完整的快捷键列表或者修改默认快捷键。
-    * 按键序列 `Ctrl+G, I` 表示先同时按下 `Ctrl`  `G`,释放,然后按下 `I` 并释放。
-* 使用中有任何问题,欢迎[反馈](https://github.com/vnotex/vnote/issues) 
+* 如果更新后VNote崩溃,请删除用户配置文件夹中的`vnotex.json`文件。
+* VNote有着一系列强大的快捷键。请查看用户配置文件`vnotex.json`以获取一个完整的快捷键列表或者修改默认快捷键。
+    * 按键序列`Ctrl+G, I`表示先同时按下`Ctrl`和`G`,释放,然后按下`I`并释放。
+* 使用中有任何问题,欢迎[反馈](https://github.com/vnotex/vnote/issues)。
 
-## Windows 用户
-* 如果 VNote 经常卡顿或无响应,或者界面异常,请检查 **OpenGL** 选项。[详情](https://github.com/vnotex/vnote/issues/853) 
-* 请关闭 *有道词典* 或者禁用其取词翻译功能。
+## Windows用户
+* 如果VNote经常卡顿或无响应,或者界面异常,请检查**OpenGL**选项。[详情](https://github.com/vnotex/vnote/issues/853)。
+* 请关闭*有道词典*或者禁用其取词翻译功能。

+ 1 - 1
src/export/exporter.cpp

@@ -117,7 +117,7 @@ QString Exporter::doExport(const ExportOption &p_option, Node *p_note)
 
     // Make sure output folder exists.
     if (!QDir().mkpath(p_option.m_outputDir)) {
-        emit logRequested(tr("Failed to create output folder %1.").arg(p_option.m_outputDir));
+        emit logRequested(tr("Failed to create output folder (%1).").arg(p_option.m_outputDir));
         return outputFile;
     }
 

+ 22 - 0
src/utils/printutils.cpp

@@ -0,0 +1,22 @@
+#include "printutils.h"
+
+#include <QPrinter>
+#include <QPrintDialog>
+
+using namespace vnotex;
+
+QSharedPointer<QPrinter> PrintUtils::promptForPrint(bool p_printSelectionEnabled, QWidget *p_parent)
+{
+    auto printer = QSharedPointer<QPrinter>::create();
+
+    QPrintDialog dialog(printer.data(), p_parent);
+    if (p_printSelectionEnabled) {
+        dialog.addEnabledOption(QAbstractPrintDialog::PrintSelection);
+    }
+
+    if (dialog.exec() == QDialog::Accepted) {
+        return printer;
+    }
+
+    return nullptr;
+}

+ 21 - 0
src/utils/printutils.h

@@ -0,0 +1,21 @@
+#ifndef PRINTUTILS_H
+#define PRINTUTILS_H
+
+#include <QSharedPointer>
+
+class QPrinter;
+class QWidget;
+
+namespace vnotex
+{
+    class PrintUtils
+    {
+    public:
+        PrintUtils() = delete;
+
+        // Return null if user cancel the print.
+        static QSharedPointer<QPrinter> promptForPrint(bool p_printSelectionEnabled, QWidget *p_parent);
+    };
+}
+
+#endif // PRINTUTILS_H

+ 2 - 0
src/utils/utils.pri

@@ -6,6 +6,7 @@ SOURCES += \
     $$PWD/htmlutils.cpp \
     $$PWD/imageutils.cpp \
     $$PWD/pathutils.cpp \
+    $$PWD/printutils.cpp \
     $$PWD/processutils.cpp \
     $$PWD/urldragdroputils.cpp \
     $$PWD/utils.cpp \
@@ -21,6 +22,7 @@ HEADERS += \
     $$PWD/htmlutils.h \
     $$PWD/imageutils.h \
     $$PWD/pathutils.h \
+    $$PWD/printutils.h \
     $$PWD/processutils.h \
     $$PWD/urldragdroputils.h \
     $$PWD/utils.h \

+ 1 - 1
src/widgets/dialogs/importnotebookdialog.cpp

@@ -100,7 +100,7 @@ bool ImportNotebookDialog::validateRootFolderInput(QString &p_msg)
         auto backend = notebookMgr.createNotebookBackend(backendName, rootFolderPath);
         if (!factory->checkRootFolder(backend)) {
             Utils::appendMsg(p_msg,
-                tr("Not a valid %1 root folder (%2).").arg(factory->getDisplayName(), rootFolderPath));
+                tr("Not a valid (%1) root folder (%2).").arg(factory->getDisplayName(), rootFolderPath));
             return false;
         }
 

+ 5 - 0
src/widgets/dialogs/settings/settingsdialog.cpp

@@ -4,6 +4,7 @@
 #include <QVBoxLayout>
 #include <QStackedLayout>
 #include <QScrollArea>
+#include <QScrollBar>
 
 #include <widgets/treewidget.h>
 #include <widgets/lineedit.h>
@@ -78,6 +79,10 @@ void SettingsDialog::setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent)
                 Q_UNUSED(p_previous);
                 auto page = itemPage(p_item);
                 m_pageLayout->setCurrentWidget(page);
+                auto vsb = m_scrollArea->verticalScrollBar();
+                if (vsb) {
+                    vsb->setValue(0);
+                }
             });
 
     p_layout->addLayout(layout, 2);

+ 20 - 1
src/widgets/markdownviewwindow.cpp

@@ -12,6 +12,7 @@
 #include <QMenu>
 #include <QActionGroup>
 #include <QTimer>
+#include <QPrinter>
 
 #include <core/fileopenparameters.h>
 #include <core/editorconfig.h>
@@ -21,6 +22,7 @@
 #include <vtextedit/markdowneditorconfig.h>
 #include <utils/pathutils.h>
 #include <utils/widgetutils.h>
+#include <utils/printutils.h>
 #include <buffer/markdownbuffer.h>
 #include <core/vnotex.h>
 #include <core/thememgr.h>
@@ -318,8 +320,10 @@ void MarkdownViewWindow::setupToolBar()
     addAction(toolBar, ViewWindowToolBarHelper::TypeTable);
 
     ToolBarHelper::addSpacer(toolBar);
-    addAction(toolBar, ViewWindowToolBarHelper::FindAndReplace);
+
     addAction(toolBar, ViewWindowToolBarHelper::Outline);
+    addAction(toolBar, ViewWindowToolBarHelper::FindAndReplace);
+    addAction(toolBar, ViewWindowToolBarHelper::Print);
 
     {
         auto act = addAction(toolBar, ViewWindowToolBarHelper::Debug);
@@ -1374,3 +1378,18 @@ void MarkdownViewWindow::syncEditorPositionToPreview()
 
     adapter()->scrollToPosition(MarkdownViewerAdapter::Position(m_editor->getTopLine(), QString()));
 }
+
+void MarkdownViewWindow::print()
+{
+    if (!m_viewer || !m_viewerReady) {
+        return;
+    }
+
+    auto printer = PrintUtils::promptForPrint(m_viewer->hasSelection(), this);
+    if (printer) {
+        m_viewer->page()->print(printer.data(), [printer](bool p_succeeded) mutable {
+                    Q_UNUSED(p_succeeded);
+                    printer.reset();
+                });
+    }
+}

+ 2 - 0
src/widgets/markdownviewwindow.h

@@ -82,6 +82,8 @@ namespace vnotex
 
         void toggleDebug() Q_DECL_OVERRIDE;
 
+        void print() Q_DECL_OVERRIDE;
+
     protected:
         void syncEditorFromBuffer() Q_DECL_OVERRIDE;
 

+ 12 - 1
src/widgets/textviewwindow.cpp

@@ -4,6 +4,7 @@
 #include <QDebug>
 #include <QScrollBar>
 #include <QToolBar>
+#include <QPrinter>
 
 #include <vtextedit/vtextedit.h>
 #include <core/editorconfig.h>
@@ -15,6 +16,7 @@
 #include <core/thememgr.h>
 #include "editors/statuswidget.h"
 #include <core/fileopenparameters.h>
+#include <utils/printutils.h>
 
 using namespace vnotex;
 
@@ -67,11 +69,12 @@ void TextViewWindow::setupToolBar()
     toolBar->addSeparator();
 
     addAction(toolBar, ViewWindowToolBarHelper::Attachment);
-
     addAction(toolBar, ViewWindowToolBarHelper::Tag);
 
     ToolBarHelper::addSpacer(toolBar);
+
     addAction(toolBar, ViewWindowToolBarHelper::FindAndReplace);
+    addAction(toolBar, ViewWindowToolBarHelper::Print);
 }
 
 void TextViewWindow::handleBufferChangedInternal(const QSharedPointer<FileOpenParameters> &p_paras)
@@ -298,3 +301,11 @@ QString TextViewWindow::selectedText() const
     Q_ASSERT(m_editor);
     return m_editor->getTextEdit()->selectedText();
 }
+
+void TextViewWindow::print()
+{
+    auto printer = PrintUtils::promptForPrint(m_editor->getTextEdit()->hasSelection(), this);
+    if (printer) {
+        m_editor->getTextEdit()->print(printer.data());
+    }
+}

+ 2 - 0
src/widgets/textviewwindow.h

@@ -53,6 +53,8 @@ namespace vnotex
 
         void handleFindAndReplaceWidgetClosed() Q_DECL_OVERRIDE;
 
+        void print() Q_DECL_OVERRIDE;
+
     protected:
         void syncEditorFromBuffer() Q_DECL_OVERRIDE;
 

+ 226 - 227
src/widgets/toolbarhelper.cpp

@@ -289,237 +289,13 @@ QToolBar *ToolBarHelper::setupSettingsToolBar(MainWindow *p_win, QToolBar *p_too
         tb = createToolBar(p_win, MainWindow::tr("Settings"), "SettingsToolBar");
     }
 
-    // Spacer.
     addSpacer(tb);
 
-    // Expand.
-    {
-        const auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
-
-        auto btn = WidgetsFactory::createToolButton(tb);
-
-        auto menu = WidgetsFactory::createMenu(tb);
-        btn->setMenu(menu);
-
-        auto expandAct = menu->addAction(generateIcon("expand.svg"),
-                                         MainWindow::tr("Expand Content Area"));
-        WidgetUtils::addActionShortcut(expandAct,
-                                       coreConfig.getShortcut(CoreConfig::Shortcut::ExpandContentArea));
-        expandAct->setCheckable(true);
-        MainWindow::connect(expandAct, &QAction::triggered,
-                            p_win, &MainWindow::setContentAreaExpanded);
-        MainWindow::connect(p_win, &MainWindow::layoutChanged,
-                            [expandAct, p_win]() {
-                                expandAct->setChecked(p_win->isContentAreaExpanded());
-                            });
-        btn->setDefaultAction(expandAct);
-
-        {
-            auto fullScreenAct = new FullScreenToggleAction(p_win,
-                                                            generateIcon("fullscreen.svg"),
-                                                            menu);
-            const auto shortcut = coreConfig.getShortcut(CoreConfig::Shortcut::FullScreen);
-            WidgetUtils::addActionShortcut(fullScreenAct, shortcut);
-            MainWindow::connect(fullScreenAct, &FullScreenToggleAction::fullScreenToggled,
-                                p_win, [shortcut](bool p_fullScreen) {
-                                    if (p_fullScreen) {
-                                        VNoteX::getInst().showTips(
-                                            MainWindow::tr("Press %1 To Exit Full Screen").arg(shortcut));
-                                    } else {
-                                        VNoteX::getInst().showTips("");
-                                    }
-                                });
-            menu->addAction(fullScreenAct);
-        }
-
-        auto stayOnTopAct = menu->addAction(generateIcon("stay_on_top.svg"), MainWindow::tr("Stay on Top"),
-                                            p_win, &MainWindow::setStayOnTop);
-        stayOnTopAct->setCheckable(true);
-        WidgetUtils::addActionShortcut(stayOnTopAct,
-                                       coreConfig.getShortcut(CoreConfig::Shortcut::StayOnTop));
-
-        menu->addSeparator();
-
-        {
-            // Windows.
-            // MainWindow will clear the title of the dock widget for the tab bar, so we need to use
-            // another action to wrap the no-text action.
-            auto subMenu = menu->addMenu(MainWindow::tr("Windows"));
-            for (auto dock : p_win->getDocks()) {
-                // @act is owned by the QDockWidget.
-                auto act = dock->toggleViewAction();
-                auto actWrapper = subMenu->addAction(act->text());
-                actWrapper->setCheckable(act->isCheckable());
-                actWrapper->setChecked(act->isChecked());
-                MainWindow::connect(act, &QAction::toggled,
-                                    actWrapper, [actWrapper](bool checked) {
-                                        if (actWrapper->isChecked() != checked) {
-                                            actWrapper->setChecked(checked);
-                                        }
-                                    });
-                MainWindow::connect(actWrapper, &QAction::triggered,
-                                    act, [p_win, act]() {
-                                        act->trigger();
-                                        p_win->updateDockWidgetTabBar();
-                                    });
-            }
-        }
-
-        tb->addWidget(btn);
-    }
-
-    // Settings.
-    {
-        const auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
-
-        auto act = tb->addAction(generateIcon("settings_menu.svg"), MainWindow::tr("Settings"));
-        auto btn = dynamic_cast<QToolButton *>(tb->widgetForAction(act));
-        Q_ASSERT(btn);
-        btn->setPopupMode(QToolButton::InstantPopup);
-        btn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
-
-        auto menu = WidgetsFactory::createMenu(tb);
-        btn->setMenu(menu);
-
-        auto settingsAct = menu->addAction(generateIcon("settings.svg"),
-                                           MainWindow::tr("Settings"),
-                                           menu,
-                                           [p_win]() {
-                                               SettingsDialog dialog(p_win);
-                                               dialog.exec();
-                                           });
-        WidgetUtils::addActionShortcut(settingsAct,
-                                       coreConfig.getShortcut(CoreConfig::Shortcut::Settings));
-
-        menu->addSeparator();
-
-        setupConfigurationMenu(menu);
-
-        menu->addSeparator();
-
-        menu->addAction(MainWindow::tr("Reset Main Window Layout"),
-                        menu,
-                        [p_win]() {
-                            p_win->resetStateAndGeometry();
-                        });
-
-        menu->addSeparator();
-
-        menu->addAction(MainWindow::tr("Restart"),
-                        menu,
-                        [p_win]() {
-                            p_win->restart();
-                        });
-
-        auto quitAct = menu->addAction(MainWindow::tr("Quit"),
-                                       menu,
-                                       [p_win]() {
-                                           p_win->quitApp();
-                                       });
-        quitAct->setMenuRole(QAction::QuitRole);
-        WidgetUtils::addActionShortcut(quitAct,
-                                       coreConfig.getShortcut(CoreConfig::Shortcut::Quit));
-    }
-
-    // Help.
-    {
-        auto act = tb->addAction(generateIcon("help_menu.svg"), MainWindow::tr("Help"));
-        auto btn = dynamic_cast<QToolButton *>(tb->widgetForAction(act));
-        Q_ASSERT(btn);
-        btn->setPopupMode(QToolButton::InstantPopup);
-        btn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
-
-        auto menu = WidgetsFactory::createMenu(tb);
-        btn->setMenu(menu);
-
-        auto whatsThisAct = menu->addAction(generateIcon("whatsthis.svg"),
-                                            MainWindow::tr("What's This?"),
-                                            menu,
-                                            []() {
-                                                QWhatsThis::enterWhatsThisMode();
-                                            });
-        whatsThisAct->setToolTip(MainWindow::tr("Enter WhatsThis mode and click somewhere to show help information"));
-
-        menu->addSeparator();
-
-        menu->addAction(MainWindow::tr("Shortcuts Help"),
-                        menu,
-                        []() {
-                            const auto file = DocsUtils::getDocFile(QStringLiteral("shortcuts.md"));
-                            if (!file.isEmpty()) {
-                                auto paras = QSharedPointer<FileOpenParameters>::create();
-                                paras->m_readOnly = true;
-                                emit VNoteX::getInst().openFileRequested(file, paras);
-                            }
-                        });
-
-        menu->addAction(MainWindow::tr("Markdown Guide"),
-                        menu,
-                        []() {
-                            const auto file = DocsUtils::getDocFile(QStringLiteral("markdown_guide.md"));
-                            if (!file.isEmpty()) {
-                                auto paras = QSharedPointer<FileOpenParameters>::create();
-                                paras->m_readOnly = true;
-                                emit VNoteX::getInst().openFileRequested(file, paras);
-                            }
-                        });
-
-        menu->addSeparator();
-
-        menu->addAction(MainWindow::tr("View Logs"),
-                        menu,
-                        []() {
-                            const auto file = ConfigMgr::getInst().getLogFile();
-                            if (QFileInfo::exists(file)) {
-                                auto paras = QSharedPointer<FileOpenParameters>::create();
-                                paras->m_readOnly = true;
-                                emit VNoteX::getInst().openFileRequested(file, paras);
-                            }
-                        });
+    setupExpandButton(p_win, tb);
 
-        menu->addSeparator();
-
-        menu->addAction(MainWindow::tr("%1 Home Page").arg(qApp->applicationDisplayName()),
-                        menu,
-                        []() {
-                            WidgetUtils::openUrlByDesktop(QUrl("https://vnotex.github.io/vnote"));
-                        });
-
-        menu->addAction(MainWindow::tr("Feedback and Discussions"),
-                        menu,
-                        []() {
-                            WidgetUtils::openUrlByDesktop(QUrl("https://github.com/vnotex/vnote/discussions"));
-                        });
-
-        menu->addSeparator();
-
-        menu->addAction(MainWindow::tr("Check for Updates"),
-                        menu,
-                        [p_win]() {
-                            Updater updater(p_win);
-                            updater.exec();
-                        });
-
-        menu->addAction(MainWindow::tr("Contributors"),
-                        menu,
-                        []() {
-                            WidgetUtils::openUrlByDesktop(QUrl("https://github.com/vnotex/vnote/graphs/contributors"));
-                        });
-
-        menu->addAction(MainWindow::tr("About"),
-                        menu,
-                        [p_win]() {
-                            auto info = MainWindow::tr("<h3>%1</h3>\n<span>%2</span>\n").arg(qApp->applicationDisplayName(),
-                                                                                             qApp->applicationVersion());
-                            const auto text = DocsUtils::getDocText(QStringLiteral("about_vnotex.txt"));
-                            QMessageBox::about(p_win, MainWindow::tr("About"), info + text);
-                        });
+    setupSettingsButton(p_win, tb);
 
-        auto aboutQtAct = menu->addAction(MainWindow::tr("About Qt"));
-        aboutQtAct->setMenuRole(QAction::AboutQtRole);
-        MainWindow::connect(aboutQtAct, &QAction::triggered,
-                            qApp, &QApplication::aboutQt);
-    }
+    setupMenuButton(p_win, tb);
 
     return tb;
 }
@@ -666,3 +442,226 @@ void ToolBarHelper::updateQuickAccessMenu(QMenu *p_menu)
         p_menu->addAction(act);
     }
 }
+
+void ToolBarHelper::setupExpandButton(MainWindow *p_win, QToolBar *p_toolBar)
+{
+    const auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
+
+    auto btn = WidgetsFactory::createToolButton(p_toolBar);
+
+    auto menu = WidgetsFactory::createMenu(p_toolBar);
+    btn->setMenu(menu);
+
+    auto expandAct = menu->addAction(generateIcon("expand.svg"),
+                                     MainWindow::tr("Expand Content Area"));
+    WidgetUtils::addActionShortcut(expandAct,
+                                   coreConfig.getShortcut(CoreConfig::Shortcut::ExpandContentArea));
+    expandAct->setCheckable(true);
+    MainWindow::connect(expandAct, &QAction::triggered,
+                        p_win, &MainWindow::setContentAreaExpanded);
+    MainWindow::connect(p_win, &MainWindow::layoutChanged,
+                        [expandAct, p_win]() {
+                            expandAct->setChecked(p_win->isContentAreaExpanded());
+                        });
+    btn->setDefaultAction(expandAct);
+
+    {
+        auto fullScreenAct = new FullScreenToggleAction(p_win,
+                                                        generateIcon("fullscreen.svg"),
+                                                        menu);
+        const auto shortcut = coreConfig.getShortcut(CoreConfig::Shortcut::FullScreen);
+        WidgetUtils::addActionShortcut(fullScreenAct, shortcut);
+        MainWindow::connect(fullScreenAct, &FullScreenToggleAction::fullScreenToggled,
+                            p_win, [shortcut](bool p_fullScreen) {
+                                if (p_fullScreen) {
+                                    VNoteX::getInst().showTips(
+                                        MainWindow::tr("Press %1 To Exit Full Screen").arg(shortcut));
+                                } else {
+                                    VNoteX::getInst().showTips("");
+                                }
+                            });
+        menu->addAction(fullScreenAct);
+    }
+
+    auto stayOnTopAct = menu->addAction(generateIcon("stay_on_top.svg"), MainWindow::tr("Stay on Top"),
+                                        p_win, &MainWindow::setStayOnTop);
+    stayOnTopAct->setCheckable(true);
+    WidgetUtils::addActionShortcut(stayOnTopAct,
+                                   coreConfig.getShortcut(CoreConfig::Shortcut::StayOnTop));
+
+    menu->addSeparator();
+
+    {
+        // Windows.
+        // MainWindow will clear the title of the dock widget for the tab bar, so we need to use
+        // another action to wrap the no-text action.
+        auto subMenu = menu->addMenu(MainWindow::tr("Windows"));
+        for (auto dock : p_win->getDocks()) {
+            // @act is owned by the QDockWidget.
+            auto act = dock->toggleViewAction();
+            auto actWrapper = subMenu->addAction(act->text());
+            actWrapper->setCheckable(act->isCheckable());
+            actWrapper->setChecked(act->isChecked());
+            MainWindow::connect(act, &QAction::toggled,
+                                actWrapper, [actWrapper](bool checked) {
+                                    if (actWrapper->isChecked() != checked) {
+                                        actWrapper->setChecked(checked);
+                                    }
+                                });
+            MainWindow::connect(actWrapper, &QAction::triggered,
+                                act, [p_win, act]() {
+                                    act->trigger();
+                                    p_win->updateDockWidgetTabBar();
+                                });
+        }
+    }
+
+    p_toolBar->addWidget(btn);
+}
+
+void ToolBarHelper::setupSettingsButton(MainWindow *p_win, QToolBar *p_toolBar)
+{
+    const auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
+
+    auto act = p_toolBar->addAction(generateIcon("settings_menu.svg"), MainWindow::tr("Settings"));
+    auto btn = dynamic_cast<QToolButton *>(p_toolBar->widgetForAction(act));
+    Q_ASSERT(btn);
+    btn->setPopupMode(QToolButton::InstantPopup);
+    btn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
+
+    auto menu = WidgetsFactory::createMenu(p_toolBar);
+    btn->setMenu(menu);
+
+    auto settingsAct = menu->addAction(MainWindow::tr("Settings"),
+                                       menu,
+                                       [p_win]() {
+                                           SettingsDialog dialog(p_win);
+                                           dialog.exec();
+                                       });
+    WidgetUtils::addActionShortcut(settingsAct,
+                                   coreConfig.getShortcut(CoreConfig::Shortcut::Settings));
+
+    menu->addSeparator();
+
+    setupConfigurationMenu(menu);
+
+    menu->addSeparator();
+
+    menu->addAction(MainWindow::tr("Reset Main Window Layout"),
+                    menu,
+                    [p_win]() {
+                        p_win->resetStateAndGeometry();
+                    });
+
+    menu->addSeparator();
+
+    menu->addAction(MainWindow::tr("Restart"),
+                    menu,
+                    [p_win]() {
+                        p_win->restart();
+                    });
+
+    auto quitAct = menu->addAction(MainWindow::tr("Quit"),
+                                   menu,
+                                   [p_win]() {
+                                       p_win->quitApp();
+                                   });
+    quitAct->setMenuRole(QAction::QuitRole);
+    WidgetUtils::addActionShortcut(quitAct,
+                                   coreConfig.getShortcut(CoreConfig::Shortcut::Quit));
+}
+
+void ToolBarHelper::setupMenuButton(MainWindow *p_win, QToolBar *p_toolBar)
+{
+    auto act = p_toolBar->addAction(generateIcon("menu.svg"), MainWindow::tr("Menu"));
+    auto btn = dynamic_cast<QToolButton *>(p_toolBar->widgetForAction(act));
+    Q_ASSERT(btn);
+    btn->setPopupMode(QToolButton::InstantPopup);
+    btn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
+
+    auto menu = WidgetsFactory::createMenu(p_toolBar);
+    btn->setMenu(menu);
+
+    menu->addAction(MainWindow::tr("View Logs"),
+                    menu,
+                    []() {
+                        const auto file = ConfigMgr::getInst().getLogFile();
+                        if (QFileInfo::exists(file)) {
+                            auto paras = QSharedPointer<FileOpenParameters>::create();
+                            paras->m_readOnly = true;
+                            paras->m_sessionEnabled = false;
+                            emit VNoteX::getInst().openFileRequested(file, paras);
+                        }
+                    });
+
+    {
+        menu->addSeparator();
+
+        menu->addAction(MainWindow::tr("Shortcuts Help"),
+                        menu,
+                        []() {
+                            const auto file = DocsUtils::getDocFile(QStringLiteral("shortcuts.md"));
+                            if (!file.isEmpty()) {
+                                auto paras = QSharedPointer<FileOpenParameters>::create();
+                                paras->m_readOnly = true;
+                                paras->m_sessionEnabled = false;
+                                emit VNoteX::getInst().openFileRequested(file, paras);
+                            }
+                        });
+
+        menu->addAction(MainWindow::tr("Markdown Guide"),
+                        menu,
+                        []() {
+                            const auto file = DocsUtils::getDocFile(QStringLiteral("markdown_guide.md"));
+                            if (!file.isEmpty()) {
+                                auto paras = QSharedPointer<FileOpenParameters>::create();
+                                paras->m_readOnly = true;
+                                paras->m_sessionEnabled = false;
+                                emit VNoteX::getInst().openFileRequested(file, paras);
+                            }
+                        });
+
+        auto helpMenu = menu->addMenu(MainWindow::tr("Help"));
+
+        helpMenu->addAction(MainWindow::tr("Home Page"),
+                            helpMenu,
+                            []() {
+                                WidgetUtils::openUrlByDesktop(QUrl("https://vnotex.github.io/vnote"));
+                            });
+
+        helpMenu->addAction(MainWindow::tr("Feedback and Discussions"),
+                            helpMenu,
+                            []() {
+                                WidgetUtils::openUrlByDesktop(QUrl("https://github.com/vnotex/vnote/discussions"));
+                            });
+
+        helpMenu->addSeparator();
+
+        helpMenu->addAction(MainWindow::tr("Check for Updates"),
+                            helpMenu,
+                            [p_win]() {
+                                Updater updater(p_win);
+                                updater.exec();
+                            });
+
+        helpMenu->addAction(MainWindow::tr("Contributors"),
+                            helpMenu,
+                            []() {
+                                WidgetUtils::openUrlByDesktop(QUrl("https://github.com/vnotex/vnote/graphs/contributors"));
+                            });
+
+        helpMenu->addAction(MainWindow::tr("About"),
+                            helpMenu,
+                            [p_win]() {
+                                auto info = MainWindow::tr("<h3>%1</h3>\n<span>%2</span>\n").arg(qApp->applicationDisplayName(),
+                                                                                                 qApp->applicationVersion());
+                                const auto text = DocsUtils::getDocText(QStringLiteral("about_vnotex.txt"));
+                                QMessageBox::about(p_win, MainWindow::tr("About"), info + text);
+                            });
+
+        auto aboutQtAct = helpMenu->addAction(MainWindow::tr("About Qt"));
+        aboutQtAct->setMenuRole(QAction::AboutQtRole);
+        MainWindow::connect(aboutQtAct, &QAction::triggered,
+                            qApp, &QApplication::aboutQt);
+    }
+}

+ 6 - 0
src/widgets/toolbarhelper.h

@@ -38,6 +38,12 @@ namespace vnotex
         static void updateQuickAccessMenu(QMenu *p_menu);
 
         static void setupConfigurationMenu(QMenu *p_menu);
+
+        static void setupExpandButton(MainWindow *p_win, QToolBar *p_toolBar);
+
+        static void setupSettingsButton(MainWindow *p_win, QToolBar *p_toolBar);
+
+        static void setupMenuButton(MainWindow *p_win, QToolBar *p_toolBar);
     };
 } // ns vnotex
 

+ 1 - 1
src/widgets/viewsplit.cpp

@@ -148,7 +148,7 @@ void ViewSplit::setupCornerWidget()
         m_menuButton->setPopupMode(QToolButton::InstantPopup);
         m_menuButton->setProperty(PropertyDefs::c_actionToolButton, true);
 
-        auto act = new QAction(s_menuIcon, tr("Workspaces and Splits"), m_menuButton);
+        auto act = new QAction(s_menuIcon, tr("Menu"), m_menuButton);
         m_menuButton->setDefaultAction(act);
 
         auto menu = WidgetsFactory::createMenu(m_menuButton);

+ 14 - 1
src/widgets/viewwindow.cpp

@@ -536,6 +536,14 @@ QAction *ViewWindow::addAction(QToolBar *p_toolBar, ViewWindowToolBarHelper::Act
         break;
     }
 
+    case ViewWindowToolBarHelper::Print:
+    {
+        act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
+        connect(act, &QAction::triggered,
+                this, &ViewWindow::print);
+        break;
+    }
+
     default:
         Q_ASSERT(false);
         break;
@@ -1318,7 +1326,7 @@ bool ViewWindow::isSessionEnabled() const
 
 void ViewWindow::toggleDebug()
 {
-    qDebug() << "debug is not supported";
+    qWarning() << "debug is not supported";
 }
 
 void ViewWindow::updateViewModeMenu(QMenu *p_menu)
@@ -1328,3 +1336,8 @@ void ViewWindow::updateViewModeMenu(QMenu *p_menu)
     auto act = p_menu->addAction(tr("View Mode Not Supported"));
     act->setEnabled(false);
 }
+
+void ViewWindow::print()
+{
+    qWarning() << "print is not supported";
+}

+ 2 - 0
src/widgets/viewwindow.h

@@ -178,6 +178,8 @@ namespace vnotex
 
         virtual void toggleDebug();
 
+        virtual void print();
+
     protected:
         bool eventFilter(QObject *p_obj, QEvent *p_event) Q_DECL_OVERRIDE;
 

+ 7 - 0
src/widgets/viewwindowtoolbarhelper.cpp

@@ -412,6 +412,13 @@ QAction *ViewWindowToolBarHelper::addAction(QToolBar *p_tb, Action p_action)
         break;
     }
 
+    case Action::Print:
+    {
+        act = p_tb->addAction(ToolBarHelper::generateIcon("print_editor.svg"), ViewWindow::tr("Print"));
+        addActionShortcut(act, editorConfig.getShortcut(Shortcut::Print), viewWindow);
+        break;
+    }
+
     default:
         Q_ASSERT(false);
         break;

+ 2 - 1
src/widgets/viewwindowtoolbarhelper.h

@@ -48,7 +48,8 @@ namespace vnotex
             SectionNumber,
             InplacePreview,
             ImageHost,
-            Debug
+            Debug,
+            Print
         };
 
         static QAction *addAction(QToolBar *p_tb, Action p_action);

+ 14 - 0
tests/test_core/test_notebook/testnotebookdatabase.cpp

@@ -83,6 +83,20 @@ void TestNotebookDatabase::testNode()
     QScopedPointer<DummyNode> node6(new DummyNode(Node::Flag::Content, 5, "cab", m_notebook.data(), node4.data()));
     addAndQueryNode(node6.data(), false);
 
+    // Node 7/8, with non-exist parent.
+    QScopedPointer<DummyNode> node7(new DummyNode(Node::Flag::Content, 55, "caba", m_notebook.data(), node6.data()));
+    QScopedPointer<DummyNode> node8(new DummyNode(Node::Flag::Content, 555, "cabaa", m_notebook.data(), node7.data()));
+    {
+        bool ret = m_dbAccess->addNode(node8.data(), false);
+        QVERIFY(!ret);
+
+        ret = m_dbAccess->addNodeRecursively(node8.data(), false);
+        queryAndVerifyNode(node7.data());
+        QVERIFY(m_dbAccess->existsNode(node7.data()));
+        queryAndVerifyNode(node8.data());
+        QVERIFY(m_dbAccess->existsNode(node8.data()));
+    }
+
     // queryNodeParentPath().
     {
         testQueryNodeParentPath(rootNode.data());

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно